Contributing
Thank you for considering a contribution to FORGE. Whether you are reporting a bug, proposing a feature, improving documentation, or submitting code, this guide walks you through the process from setup to pull request.
Getting Started
Prerequisites
Before contributing, make sure you have the following installed:
| Tool | Version | Purpose |
|---|---|---|
| Rust | 1.75+ | Compile FORGE CLI and core |
| Cargo | (bundled with Rust) | Build system and package manager |
| Git | 2.30+ | Version control |
| Node.js | 18+ | Build and preview documentation |
| Docker | 24+ | Run integration tests |
| PostgreSQL | 15+ | Database for integration tests |
Clone and Build
# Clone the repository
git clone https://github.com/forge/forge.git
cd forge
# Build the project
cargo build
# Run the test suite
cargo test
# Run with debug output
RUST_LOG=debug cargo run -- new --name=testappTIP
The first build downloads and compiles all dependencies, which may take a few minutes. Subsequent builds are incremental and much faster.
Verify Your Setup
Run the following to confirm everything works:
# Build in release mode
cargo build --release
# Run clippy for lint checks
cargo clippy -- -D warnings
# Check formatting
cargo fmt --checkProject Structure
FORGE is organized as a Cargo workspace with two crates:
forge/
+-- Cargo.toml # Workspace root
+-- forge-cli/ # CLI binary crate
| +-- src/
| | +-- main.rs # Entry point and command routing
| | +-- commands/ # CLI command implementations
| | +-- utils/ # CLI utilities (output, prompts)
| +-- Cargo.toml
|
+-- forge-core/ # Library crate (business logic)
| +-- src/
| | +-- lib.rs # Library root
| | +-- config/ # Project configuration parsing
| | +-- generator/ # Code generation engine
| | +-- template/ # Template loading and rendering
| | +-- providers/ # Provider contract definitions
| | +-- validators/ # Input and config validation
| +-- Cargo.toml
|
+-- templates/ # Tera template files
| +-- backends/
| | +-- rust/ # Rust + Axum backend templates
| +-- frontends/
| | +-- nextjs/ # Next.js frontend templates
| +-- infra/ # Docker, Caddy, config templates
|
+-- docs/ # VitePress documentation (this site)
+-- tests/ # Integration tests
+-- README.mdKey Crates
| Crate | Type | Description |
|---|---|---|
forge-cli | Binary | Parses CLI arguments, dispatches commands, manages terminal output |
forge-core | Library | Config parsing, template rendering, file generation, validation |
Development Workflow
1. Create a Branch
Always work on a feature branch, never directly on main:
# Create a branch from main
git checkout main
git pull origin main
git checkout -b feat/my-featureUse these branch name prefixes:
| Prefix | Purpose | Example |
|---|---|---|
feat/ | New feature | feat/add-nuxtjs-support |
fix/ | Bug fix | fix/template-rendering-error |
docs/ | Documentation only | docs/update-api-contracts |
refactor/ | Code restructuring | refactor/simplify-generator |
test/ | Test additions | test/add-config-validation |
2. Make Changes
Write your code following the style guidelines below. Keep commits focused -- each commit should represent a single logical change.
3. Test Your Changes
# Run all tests
cargo test
# Run a specific test
cargo test test_name
# Run tests with output
cargo test -- --nocapture
# Run clippy
cargo clippy -- -D warnings
# Check formatting
cargo fmt --check4. Submit a Pull Request
# Push your branch
git push -u origin feat/my-featureThen open a pull request on GitHub. Include:
- A clear title describing what the PR does
- A description of the changes and why they are needed
- Steps to test the changes manually (if applicable)
- Screenshots for UI changes
WARNING
All pull requests must pass CI checks before merging. This includes tests, clippy, and formatting.
Template Development
Templates are the heart of FORGE. Every file in a generated project is rendered from a Tera template.
Template File Structure
Template files use the .tera extension and live under templates/:
templates/backends/rust/api/src/handlers/auth.rs.teraThis template generates the file:
{output}/apps/api/src/handlers/auth.rsTemplate Variables
Templates have access to the project configuration via context variables:
{{ project_name }} - Application name
{{ project_name_pascal }} - PascalCase name
{{ auth_method }} - "email", "mobile", or "otp"
{{ default_language }} - Default language code
{{ languages }} - Array of language objects
{{ features }} - Enabled featuresConditional Generation
Use Tera conditionals to include or exclude code based on configuration:
// In a .tera template file
{% if auth_method == "otp" %}
pub async fn send_otp(/* ... */) -> Result<Json<Value>, AppError> {
// OTP-specific logic
}
{% endif %}Testing Templates
Test that your templates render correctly by generating a project and inspecting the output:
# Build FORGE
cargo build
# Generate a test project
./target/debug/forge new --name=test-output
# Inspect the generated files
cat test-output/apps/api/src/handlers/auth.rsTIP
When modifying templates, always test with multiple configuration combinations (different auth methods, different languages, features enabled/disabled) to ensure all code paths render correctly.
Template Style Guidelines
- Maintain the output file's language conventions (e.g., Rust idioms for
.rs.terafiles) - Use
{% raw %}...{% endraw %}blocks around content that contains Tera-like syntax (e.g., JSX curly braces) - Keep template logic minimal -- prefer generating clean, readable code over clever template tricks
- Add comments in the generated output explaining non-obvious patterns
Code Style
Rust Code
FORGE follows standard Rust conventions enforced by rustfmt and clippy:
# Format all code
cargo fmt
# Run linter with warnings as errors
cargo clippy -- -D warningsKey conventions:
- Use
snake_casefor functions, variables, and module names - Use
PascalCasefor types, traits, and enums - Prefer
Result<T, E>over panics - Use
thiserrorfor error types - Document public APIs with
///doc comments - Keep functions under 50 lines when possible
Commit Messages
Follow the Conventional Commits specification:
feat: add Nuxt.js frontend generator
fix: resolve template rendering for RTL languages
docs: update API contracts reference
refactor: simplify config parsing logic
test: add unit tests for permission validation
chore: update dependenciesCommit message rules:
- Use the imperative mood (
add, notaddedoradds) - Keep the subject line under 72 characters
- Add a body for complex changes explaining the "why"
- Reference issue numbers when applicable:
fix: handle empty slug (#42)
Testing
FORGE uses three levels of testing:
Unit Tests
Test individual functions and modules in isolation.
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_project_name() {
assert!(validate_name("my-app").is_ok());
assert!(validate_name("My App").is_err());
assert!(validate_name("123app").is_err());
}
}Integration Tests
Test the full generation pipeline from config to output files.
// tests/integration/generate_test.rs
#[test]
fn test_generate_rust_backend() {
let config = ProjectConfig {
name: "test-app".into(),
backend: Backend::Rust,
auth_method: AuthMethod::Email,
..Default::default()
};
let output = tempdir().unwrap();
generate_project(&config, output.path()).unwrap();
// Verify expected files exist
assert!(output.path().join("apps/api/src/main.rs").exists());
assert!(output.path().join("apps/api/Cargo.toml").exists());
}Template Rendering Tests
Verify that templates produce valid output for all configuration combinations.
#[test]
fn test_auth_handler_email_method() {
let context = create_context(AuthMethod::Email);
let output = render_template("backends/rust/api/src/handlers/auth.rs.tera", &context);
assert!(output.contains("pub async fn login"));
assert!(!output.contains("pub async fn send_otp"));
}
#[test]
fn test_auth_handler_otp_method() {
let context = create_context(AuthMethod::Otp);
let output = render_template("backends/rust/api/src/handlers/auth.rs.tera", &context);
assert!(output.contains("pub async fn login"));
assert!(output.contains("pub async fn send_otp"));
}Documentation Contributions
The documentation site is built with VitePress and lives in the docs/ directory.
Running the Docs Locally
cd docs
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run buildWriting Documentation
- Use VitePress features:
::: tip,::: warning,::: dangercallouts - Use code groups (
::: code-group) for multi-language or multi-format examples - Add tables for structured data instead of long prose
- Include working code examples whenever possible
- Link to related pages using relative paths:
[Authentication](/backend/authentication)
File Naming
- Use lowercase with hyphens:
api-contracts.md, notApiContracts.md - Place files in the appropriate directory matching the sidebar structure
- Update
.vitepress/config.mtsif adding a new page to the sidebar
Issue Reporting
Bug Reports
When filing a bug report, include:
- FORGE version (
forge --version) - Operating system and version
- Rust version (
rustc --version) - Steps to reproduce the issue
- Expected behavior vs. actual behavior
- Error output (full terminal output, not screenshots)
- Configuration (
forge.yamlcontents, if relevant)
TIP
Use the GitHub issue template when available. It guides you through providing all the necessary information.
Feature Requests
Feature requests should include:
- Problem statement -- what are you trying to accomplish?
- Proposed solution -- how should FORGE handle it?
- Alternatives considered -- other approaches you thought of
- Context -- who would benefit from this feature?
Code of Conduct
All contributors are expected to follow the project's Code of Conduct:
- Be respectful -- Treat everyone with respect. Disagree constructively.
- Be constructive -- Focus on what is best for the project and community.
- Be collaborative -- Share knowledge and help others.
- Be patient -- Not everyone has the same experience level.
- No harassment -- Harassment of any kind will not be tolerated.
Violations should be reported to the project maintainers via email. All reports are kept confidential.
Getting Help
If you need help with your contribution:
- Open a Discussion for questions
- Check existing Issues for known problems
- Read the Architecture Contracts for API specifications
- Review the Database Schema for data model reference
See Also
- Introduction -- Project overview and philosophy
- Template System -- How Tera templates work
- Code Generation -- The generation pipeline
- Roadmap -- Planned features and priorities