Skip to content
Public template

About

A modular, Postgres-first, AI-native application foundation.

Topics

Resources

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

 

History

130 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DarkFactory — Full-Stack Project Scaffold: an astronaut faces a modular industrial factory whose stacked modules are labeled Frontend, Backend, Database, DevOps, Auth and Testing

DarkFactory

PR CI CodeQL Latest release License OpenSSF Best Practices Coverage gate 100%

DarkFactory is a strict-TypeScript monorepo template for starting a web product with the boring parts already wired. It ships Next App Router pages on Vite (vinext) deployed to Cloudflare Workers, PostgreSQL through Drizzle, contract-first oRPC with generated OpenAPI, Better Auth, and Tailwind + shadcn UI.

Every external service (email, analytics, AI, telemetry) sits behind a small port with an adapter, so you swap a provider by replacing an adapter, not by rewriting features. The database host is a config switch: plain Postgres, PlanetScale or Cloudflare Hyperdrive. Gates are strict: 100% coverage, four required CI lanes, and generated contracts and docs that must match the code. An optional operator plane runs a planned, approval-gated agent SDLC on top.

Lego bricks

Every workspace package declares a brick role in its package.json. Arrows mean "uses"; bun run docs:check enforces their direction:

flowchart LR
  app["🌐 <b>app</b><br/>apps/web<br/><i>turns bricks<br/>into pages</i>"]
  sdlc["🧭 <b>agent-sdlc</b><br/>operator, jobs<br/><i>optional AI crew,<br/>safe to delete</i>"]
  product["🧱 <b>product</b><br/>api · auth · db<br/>config · ui · state<br/>observability<br/><i>your rules and data</i>"]
  capability["🔌 <b>capability</b><br/>email · ai<br/>analytics<br/><i>swap vendors, not features</i>"]
  tooling["🧪 <b>tooling</b><br/>testkit<br/><i>throwaway test databases</i>"]

  app --> product & capability
  sdlc --> product & capability
  product --> capability
  tooling -.->|tests| product

  classDef appRole fill:#1f6feb,stroke:#0b3d91,color:#ffffff
  classDef productRole fill:#2ea44f,stroke:#1a7f37,color:#ffffff
  classDef capabilityRole fill:#bf8700,stroke:#7d4e00,color:#ffffff
  classDef sdlcRole fill:#8250df,stroke:#512a97,color:#ffffff
  classDef toolingRole fill:#6e7781,stroke:#424a53,color:#ffffff
  class app appRole
  class product productRole
  class capability capabilityRole
  class sdlc sdlcRole
  class tooling toolingRole
Loading

Nothing depends on an app, capability bricks depend on nothing but tooling, and product bricks never reach into the agent plane. The per-package graph, with every workspace edge and export, is generated from the package.json files: docs/generated/package-graph.md.

ai is the reference capability brick: a port, a Groq adapter, a recording fake and a browser guard, with no app wired to it yet. Copy its shape when you add a capability (docs/capabilities.md).

Quickstart

You need mise, which installs the toolchain pinned in mise.toml, and Docker for local Postgres (or your own PostgreSQL 17 with the roles in infra/docker/postgres.compose.yml).

Start your own project

Create your repository from the template with the GitHub CLI. It starts from one fresh commit, so none of the template's Git history comes with it. Rename it with init before you run setup:

gh repo create acme/acme-labs --template jeffscottward/darkfactory --private --clone && cd acme-labs
mise install
bun run init -- --name "Acme Labs" --slug acme-labs --scope @acme --domain acme.dev --repo acme/acme-labs
git commit -m "chore: initialize project" && git push

Init rewrites the package scope, slug, domain, repository URLs, env prefixes and database names in one pass. It removes instance-only history (the changelog, archives and the OpenSSF record) and then deletes itself. Add --without-operator to drop the opt-in agent-SDLC plane, --dry-run to preview, or --help to list every option. Then protect main.

To only try the template, git clone https://github.com/jeffscottward/darkfactory.git instead. That clone carries the template's full history, so never push it; bun run init -- … --fresh-history turns it into a project with a single root commit.

Run it from a checkout:

mise install
bun run setup
bun run dev

Open https://darkfactory.localhost and sign in as admin@domain.test with the development password Development123!. Details: docs/getting-started.md.

Commands

Command What it does
bun run setup Checks the toolchain, installs dependencies, writes .env with generated secrets, starts Postgres with Docker Compose, migrates, seeds dev accounts and writes the Worker .dev.vars. Safe to re-run.
bun run dev Refreshes .dev.vars and starts the web app over portless HTTPS at https://darkfactory.localhost.
bun run check Format check, lint (Biome and Markdown) and typecheck.
bun run test Every suite: unit, contract, operations, integration, then a build and the E2E and accessibility lane. Database suites run against the test database (TEST_DATABASE_URL), never the app database in .env.
bun run verify:prepush The pre-push hook: check, generated-artifact checks, and unit, contract and operations tests.
bun run verify Runs the same checks as the four CI lanes, locally.
bun run docs:generate / docs:check Regenerates or checks docs/generated/package-graph.md.
bun run generate:feature <name> Generates a feature slice: table, migration, repository, contract, service, portal page, docs and tests. Add --dry-run to preview.
bun run db:migrate Applies migrations. db:seed and db:reset also need -- --confirm-environment=development.
bun run deploy:web:check / deploy:web Validates the production database config and dry-runs the Worker deploy, or deploys it (docs/deploy.md).
bun run doctor Checks the toolchain, required env keys and the services declared in capabilities.yaml.
bun run graph:build Optional. Builds a local Graphify code graph for navigation. It is never committed.

Stack

Versions live in package.json, the catalog in pnpm-workspace.yaml and mise.toml.

Concern Default Swap point
Pages and routing vinext (Next App Router API on Vite) apps/web; see ADR-001 in ARCHITECTURE.md
Hosting Cloudflare Workers via @vinext/cloudflare apps/web/wrangler.jsonc, scripts/deployment/
Database host Postgres, PlanetScale or Hyperdrive DATABASE_PROVIDER profiles in packages/config/src/database.ts
ORM and migrations Drizzle Core: packages/db (not a swap point)
API oRPC contracts + generated OpenAPI Core: packages/api/src/contracts/ (not a swap point)
Auth Better Auth packages/auth
Email Resend (preview files locally) EmailPort in packages/email/src/index.ts; adapters in packages/email/src/server/provider.ts and contact.ts
Product analytics PostHog AnalyticsPort in packages/analytics/src/index.ts; adapter in packages/analytics/src/server/posthog.ts
AI Groq AiPort in packages/ai/src/index.ts; adapter in packages/ai/src/server/groq.ts
Traces and metrics OpenTelemetry TelemetryPort in packages/observability/src/port.ts; adapter in packages/observability/src/server/otel.ts
Structured events evlog StructuredEventSink in packages/observability/src/port.ts; adapter in packages/observability/src/server/evlog.ts
UI Tailwind + shadcn packages/ui
State XState (lifecycles), Zustand (UI-only) packages/state
Tests Vitest (100% gate), Playwright vitest.config.ts, playwright.config.ts
Lint and format Biome (ultracite/core), markdownlint biome.jsonc, .markdownlint-cli2.jsonc
Local HTTPS portless bun run dev
Workspace pnpm + Turborepo, Bun for scripts pnpm-workspace.yaml, turbo.json, mise.toml

Docs

About

A modular, Postgres-first, AI-native application foundation.

Topics

Resources

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages