Skip to main content

Command Palette

Search for a command to run...

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

Every engineer has lost a Monday morning to wiring up the same Dockerfile, the same GitHub Actions workflow and the same ESLint config they wrote three projects ago. ForgeKit eliminates that entirely. One command. Production-ready project.

Updated
10 min read
How I Built ForgeKit: An Open-Source Engineering Acceleration Platform That Scaffolds Production-Ready Projects in Under 60 Seconds
S

A versatile DevSecOps Engineer specialized in creating secure, scalable, and efficient systems that bridge development and operations. My expertise lies in automating complex processes, integrating AI-driven solutions, and ensuring seamless, secure delivery pipelines. With a deep understanding of cloud infrastructure, CI/CD, and cybersecurity, I thrive on solving challenges at the intersection of innovation and security, driving continuous improvement in both technology and team dynamics.

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 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.

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:

npm install -g forgekit-cli

forgekit new model-serving-api --template api-service
  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

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:

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/


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:

// 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:

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:

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:

{
  "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:

# {{name}}

A FastAPI service scaffolded with ForgeKit.

Full registry: 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:

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__


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/


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):

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

3. Register in templates/registry.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

# 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


Get Started

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 has the full guide.


GitHub: github.com/SubhanshuMG/ForgeKit
npm: npmjs.com/package/forgekit-cli
Website: forgekit.build

Apache 2.0. Built by Subhanshu Mohan Gupta.

I

Really useful framing here.

One thing I've been exploring from the other side of this — building an autonomous AI agency that actually runs itself day-to-day — is that the hardest part isn't the capability, it's the trust loop. Getting a human to approve something once and then never ask again is the whole game.

We've been calling that a "preauth cache" — a ledger of what's already approved so the agent never re-asks. Three articles on it just went live on our publication if anyone's wrestling with the same problem: https://dollaragency.hashnode.dev

Appreciate the post.

AI-Native Infrastructure & Security Architecture Research | Subhanshu Mohan Gupta

Part 1 of 50

Independent research and deep technical exploration of AI-driven DevSecOps, resilient cloud architecture, cross-chain systems and large-scale distributed architecture.

Up next

Building a Deployment Health Validator

5 Subtle Bugs That Break Production (and how to find them)