# How I Built ForgeKit: An Open-Source Engineering Acceleration Platform That Scaffolds Production-Ready Projects in Under 60 Seconds

%[https://github.com/SubhanshuMG/ForgeKit] 

* * *

## The Problem Nobody Talks About Honestly

It is 9 AM on a Monday. Your team just got greenlit on a new microservice. You spin up a fresh repo and then spend the next three hours doing this:

> You copy the Dockerfile from the last project. Strip out service-specific stuff. Realize you forgot the health check. Set up GitHub Actions from a Stack Overflow template that still references Node 16, which hit EOL two years ago. Wire up ESLint, then discover your team standardized on a different config six months ago. Create `.env.example`, forget two variables, find out at 11 PM during code review.

You have not written a single line of product code.

This compounds across every new project, every new contributor onboarding, every side project started at 10 PM that burns out before the interesting part begins. It is not a skill problem. It is a tooling problem.

> **Engineers lose 2+ hours on every new project to the exact same setup work. ForgeKit eliminates it in one command.**

%[https://youtu.be/NLMJQa4lyLI] 

* * *

## What ForgeKit Is

[ForgeKit](https://github.com/SubhanshuMG/ForgeKit) is an open-source engineering acceleration platform. One command scaffolds a fully wired, production-ready project: Dockerfile, docker-compose, GitHub Actions CI, test setup, environment config, health endpoint, and stack-specific sensible defaults.

```bash
forgekit new my-api --template api-service
```

No config to set up. No template repos to fork and clean. The project runs on the first try.

It ships as a TypeScript monorepo published to npm, with six production-grade templates and a React 18 + Vite web dashboard for browsing and launching scaffolds visually.

* * *

## Real-World Example: Zero to Running FastAPI Service

Say you are an ML engineer who needs a FastAPI service to expose a model endpoint. The usual path: virtualenv setup, remembering pydantic v2 syntax changes, SQLAlchemy async session wiring, getting the multi-stage Docker build right so the image is not 2 GB, writing CI from scratch.

With ForgeKit:

```bash
npm install -g forgekit-cli

forgekit new model-serving-api --template api-service
```

```plaintext
  ForgeKit, Engineering Acceleration Platform

  Scaffolding model-serving-api from template api-service...
  ✓ Scaffolded 14 files in 1.2s

  Next steps:
    cd model-serving-api
    pip install -r requirements.txt
    cp .env.example .env
    docker-compose up
```

### What gets generated

| File | What it does |
| --- | --- |
| `main.py` | FastAPI app entrypoint with router |
| `app/config.py` | Pydantic Settings, env var loading |
| `app/database.py` | SQLAlchemy async session factory |
| `app/routes/health.py` | `/health` endpoint with typed response |
| `tests/test_health.py` | Pytest test passes immediately |
| `Dockerfile` | Multi-stage build, non-root user |
| `docker-compose.yml` | App + PostgreSQL with healthcheck |
| `.env.example` | Every variable documented |

Everything runs. Tests pass. Docker image builds clean. You are building your actual product within minutes.

* * *

## All Six Templates

| Template | Stack | Use Case |
| --- | --- | --- |
| `web-app` | Node.js + React + TypeScript + Express + Vite | Full-stack web apps |
| `api-service` | Python + FastAPI + PostgreSQL + Docker | REST APIs, ML serving |
| `ml-pipeline` | Python + Jupyter + MLflow + scikit-learn | Reproducible ML experiments |
| `next-app` | Next.js + Tailwind + TypeScript | Frontend-first apps |
| `go-api` | Go + Gin + PostgreSQL | High-performance APIs |
| `serverless` | AWS Lambda + TypeScript | Event-driven functions |

Every template ships with a Dockerfile, docker-compose, `.env.example`, and at least one passing test.

* * *

## Architecture

![](https://cdn.hashnode.com/uploads/covers/6442da7c019a6adb6b507559/4aa99af6-330c-4237-a0c7-177a62105a0b.png align="center")

ForgeKit is not a glorified `cp -r`. It has a clean five-layer architecture built for security and extensibility.

| Layer | Responsibility | Key Modules |
| --- | --- | --- |
| **Interface** | User interaction, CLI prompts, web dashboard | `packages/cli/`, `packages/web/` |
| **Application** | Orchestration, validation, execution tracking | `commands/new.ts`, `core/validator.ts` |
| **Service** | Scaffolding engine, template resolver, file writer, security guard | `core/scaffold.ts`, `core/security.ts` |
| **Data** | Template registry, audit logs, config | `templates/registry.json`, `core/audit.ts` |
| **Infrastructure** | CI/CD, npm publishing, docs hosting | `.github/workflows/`, `docs/` |

### The Scaffold Lifecycle

When you run `forgekit new`, here is exactly what happens under the hood:

```plaintext
forgekit new
    → sanitizeProjectName()        [strips to a-z0-9 only]
    → validateTemplateId()          [regex + blocks path traversal]
    → getTemplate()                 [reads registry.json]
    → writeTemplateFiles()          [for each file:]
        → validatePathContainment() [blocks ../../ escapes]
        → Handlebars.compile()      [renders .hbs templates]
        → fs.outputFile()           [writes to disk]
    → validateHookCommand()         [allowlist: npm/pip/python only]
    → spawnSync(shell: false)       [runs post-scaffold hooks]
    → trackEvent()                  [opt-out telemetry]
```

Full source: [packages/cli/src/core/](https://github.com/SubhanshuMG/ForgeKit/tree/main/packages/cli/src/core)

* * *

## Security by Design

Security is a design constraint, not a checklist item. The core assumption is that templates are untrusted input. A malicious template must not escape the output directory or run arbitrary code.

> A template cannot write outside the project root. A hook cannot run `curl | bash`. A project name cannot inject a path traversal. These are enforced at the code level, not by convention.

### The four defenses

**Path traversal prevention** validates every destination path against the project root before any write:

```typescript
// core/security.ts
export function validatePathContainment(
  targetRoot: string,
  filePath: string
): boolean {
  const resolvedRoot = path.resolve(targetRoot);
  const resolvedFile = path.resolve(targetRoot, filePath);
  return resolvedFile.startsWith(resolvedRoot + path.sep);
}
```

**Command injection prevention** via an explicit allowlist. Only `npm`, `npx`, `yarn`, `pnpm`, `pip`, `pip3`, `python`, and `python3` are allowed. `spawnSync` uses `shell: false`.

**Name sanitization** strips everything except `[a-z0-9-_]`. The string `../../etc/passwd` becomes `etc-passwd`. No special characters reach the filesystem.

**External template validation** checks `github:` and `npm:` prefixed IDs against a strict regex before any network call.

### Every generated project ships secure by default

| Default | What it protects against |
| --- | --- |
| Non-root Docker `USER appuser` | Container breakout escalation |
| `.env.example` with no real secrets | Credential leaks in version control |
| `.gitignore` excludes `.env` | Accidental secret commits |
| PostgreSQL healthcheck in compose | Startup race conditions |
| Multi-stage Docker builds | Bloated images with build tools exposed |
| Pinned dependency versions | Supply chain drift |

* * *

## Generated Code That Actually Runs

The health route in every `api-service` scaffold:

```python
from fastapi import APIRouter
from pydantic import BaseModel

router = APIRouter()

class HealthResponse(BaseModel):
    status: str
    version: str

@router.get("/health", response_model=HealthResponse)
async def health_check():
    return HealthResponse(status="ok", version="0.1.0")
```

The test that ships alongside it, passing on first run:

```python
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_health_check():
    response = client.get("/api/v1/health")
    assert response.status_code == 200
    assert response.json()["status"] == "ok"
```

Your CI is green before you write a single line of product code.

%[https://gist.github.com/SubhanshuMG/29a54512c27445b1d45f07da2d3a40fa] 

* * *

## The Template System

Each template is a directory of files. Some are raw (copied as-is), some are Handlebars `.hbs` files for variable interpolation. The registry at `templates/registry.json` defines the manifest:

```json
{
  "id": "api-service",
  "name": "API Service (Python + FastAPI)",
  "stack": ["python", "fastapi", "postgresql", "docker"],
  "files": [
    { "src": "main.py", "dest": "main.py" },
    { "src": "README.md.hbs", "dest": "README.md" },
    { "src": "Dockerfile", "dest": "Dockerfile" }
  ],
  "hooks": [
    { "type": "post-scaffold", "command": "pip", "args": ["install", "-r", "requirements.txt"] }
  ]
}
```

Handlebars files use `{{name}}` to inject the project name at scaffold time:

```handlebars
# {{name}}

A FastAPI service scaffolded with ForgeKit.
```

Full registry: [templates/registry.json](https://github.com/SubhanshuMG/ForgeKit/blob/main/templates/registry.json)

* * *

## Testing Strategy

Three layers, each with a specific purpose.

**Unit tests** cover the security functions: sanitizer, path containment, hook allowlist, template ID regex.

**Integration tests** scaffold a real project into a temp directory and verify the full file tree:

```typescript
it("creates all expected files", async () => {
  const result = await scaffold({
    projectName: "test-api",
    templateId:  "api-service",
    outputDir:   os.tmpdir(),
    variables:   { name: "test-api" },
    skipInstall: true,
  });

  expect(result.success).toBe(true);
  expect(result.filesCreated).toContain(
    path.join(os.tmpdir(), "test-api", "main.py")
  );
});
```

**Smoke tests** run the full CLI binary end-to-end against a real filesystem.

Full test suite: [packages/cli/src/\_\_tests\_\_](https://github.com/SubhanshuMG/ForgeKit/tree/main/packages/cli/src/__tests__)

* * *

## CI/CD Pipeline

Seven GitHub Actions workflows, each with a single job:

| Workflow | Trigger | Purpose |
| --- | --- | --- |
| `ci.yml` | push, PR | Typecheck + lint + test + build (Node 20/22 matrix) |
| `publish.yml` | release tag | npm publish, gated on CI |
| `codeql.yml` | push, schedule | Static analysis |
| `security-scan.yml` | push | Dependency audit |
| `dco-check.yml` | PR | Developer Certificate of Origin |
| `docs.yml` | push to main | VitePress docs to GitHub Pages |
| `release-drafter.yml` | PR merge | Auto-draft changelog |

Workflows: [.github/workflows/](https://github.com/SubhanshuMG/ForgeKit/tree/main/.github/workflows)

* * *

## How to Add Your Own Template

**Full step-by-step guide (expand)**

**1.** Create the directory: `mkdir templates/django-api`

**2.** Add your files (`.hbs` for Handlebars interpolation):

```plaintext
templates/django-api/
├── manage.py.hbs
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
├── .env.example
└── README.md.hbs
```

**3.** Register in `templates/registry.json`:

```json
{
  "id": "django-api",
  "name": "Django API",
  "stack": ["python", "django", "drf", "postgresql"],
  "files": [
    { "src": "manage.py.hbs", "dest": "manage.py" },
    { "src": "Dockerfile", "dest": "Dockerfile" }
  ],
  "hooks": [
    { "type": "post-scaffold", "command": "pip", "args": ["install", "-r", "requirements.txt"] }
  ]
}
```

**4.** Use `{{name}}` in `.hbs` files for project name injection.

**5.** Write a test, open a PR. That is the full loop.

* * *

## The CLI

```bash
# Scaffold (interactive mode)
forgekit new

# Scaffold with flags
forgekit new my-api --template api-service

# Preview without writing files
forgekit new preview --template go-api --dry-run

# List templates
forgekit list

# Check your environment
forgekit doctor
```

* * *

## Why Apache 2.0 and DCO

**Apache 2.0 over MIT:** Includes an explicit patent grant and trademark protection. For an engineering platform, companies will depend on both matters. MIT leaves them ambiguous.

**DCO over CLA:** A per-commit sign-off (`git commit -s`) stating you have the right to submit the code. Same legal effect as a CLA, zero friction. Every PR enforces it via `dco-check.yml`.

* * *

## Roadmap

| Phase | Status | Focus |
| --- | --- | --- |
| Foundation | Done | Repo structure, governance, CI |
| Day-one value | Done | CLI, 6 templates, web dashboard, npm |
| Multi-role expansion | Next | Rails, Rust/Axum, React Native templates |
| Security + audit | Planned | RBAC, audit log, policy validation |
| Community growth | Planned | Public template registry, contribution pathways |
| Enterprise | Future | Team templates, analytics, self-hosted |

Full roadmap: [ROADMAP.md](https://github.com/SubhanshuMG/ForgeKit/blob/main/ROADMAP.md)

* * *

## Get Started

```bash
npm install -g forgekit-cli
forgekit new
```

> **The repo is public, CI is green, the package is live on npm. Star the repo. Try the CLI. Contribute a template.**

%[https://www.producthunt.com/products/forgekit-2] 

* * *

## Contributing

Best first contributions right now:

*   **Add a new template** (highest impact, see guide above)
    
*   **Improve error messages** in `packages/cli/src/core/`
    
*   **Add test coverage** for security function edge cases
    
*   **Improve the web dashboard** (React 18 + Vite)
    
*   **Write or improve docs** (VitePress)
    

[CONTRIBUTING.md](https://github.com/SubhanshuMG/ForgeKit/blob/main/CONTRIBUTING.md) has the full guide.

* * *

> **GitHub:** [github.com/SubhanshuMG/ForgeKit](https://github.com/SubhanshuMG/ForgeKit)  
> **npm:** [npmjs.com/package/forgekit-cli](https://www.npmjs.com/package/forgekit-cli)  
> **Website:** [forgekit.build](https://forgekit.build)

*Apache 2.0. Built by* [*Subhanshu Mohan Gupta*](https://subhanshumg.com)*.*
