Stop prompting. Start delegating. The full-stack monorepo where Claude Code, Cursor, Gemini CLI, Kiro, Copilot, and Windsurf all read one company handbook — and ship identical, production-grade code on the first try.
⚡ Quick Start · 😤 The Problem · 🏢 How It Works · 🔥 Battle-Tested · ⭐ Star History
You open Cursor, type "create a user profile page", and get:
- A file in the wrong folder
useStatefor form fields instead of react-hook-form- Raw
fetch()instead of your HTTP client console.logeverywhere- No Zod validation, no error boundaries, no types
You hired a 10x engineer and got an intern with amnesia. Every prompt starts from zero. Every tool has its own opinions. You spend more time reviewing AI slop than you'd spend writing the code yourself.
That's not vibe coding. That's babysitting.
A real company doesn't re-explain its culture to every new hire. It hands them the handbook.
This repo has one: AGENTS.md — the emerging open standard for agent instructions (CLAUDE.md is a symlink, so every tool finds it). It defines the architecture, the naming laws, the testing rules, the fireable offenses. Every AI agent reads it before writing a single line.
┌─────────────────────────────────┐
│ AGENTS.md (the handbook) │
│ CLAUDE.md ──► symlink │
└───────────────┬─────────────────┘
┌────────┬────────┼────────┬─────────┐
▼ ▼ ▼ ▼ ▼
Claude Cursor Copilot Gemini Windsurf
└────────┴────────┴────────┴─────────┘
▼
✅ identical, rule-compliant code
And because trust is good but gates are better, nothing ships without passing the Five Gates:
typecheck→lint→test→build→audit— enforced locally by husky, enforced again in CI, and deploys are CI-gated with staging/production separation. If an agent (or a human) breaks a rule, the pipeline says no. Period.
You review outcomes, not syntax. That's the whole product.
create-next-app |
t3-app |
🎩 Vibe Code Stack For CEOs | |
|---|---|---|---|
| AI understands your architecture | - | - | One AGENTS.md, every agent |
| Feature-Sliced Design v2.1 | - | Partial | Strict, Steiger + ESLint enforced |
| Full monorepo (3 apps + RPC backend) | - | - | Turborepo, 9 workspaces |
| Type-safe end to end | - | tRPC | Connect-RPC (Protobuf) + next-safe-action |
| CI-gated deploys (staging/prod) | - | - | GitHub Environments + wrangler |
| Pre-commit AI code review | - | - | Code Review Graph MCP |
| Headless, accessible UI | - | - | Ark UI v5 (WAI-ARIA) |
| Security headers (CSP/HSTS/CORS) | - | - | Nonce-based CSP, OWASP-ready |
| Audited by a fleet of AI agents | - | - | 26 agents, 86 findings, all fixed ✅ |
Most boilerplates say "production-ready." We made 26 AI agents prove it.
We ran a multi-agent production-readiness audit: 10 specialist auditors tore through security, architecture, testing, CI/CD, performance, config, and dependencies in parallel — then every critical finding was handed to an adversarial verifier agent whose only job was to refute it against the real code.
The result: 86 findings. 0 refuted. All 9 high-severity blockers fixed — including a CSP nonce bug that would have broken production, a Turborepo cache flaw that could have shipped mock-auth to prod, and full backend CORS. Then the fix wave: 4 parallel agent teams, 300+ files touched, every gate re-run green.
✅ typecheck 9/9 workspaces
✅ biome 190 files, 0 errors
✅ eslint 6/6 workspaces
✅ tests 94/94 passing
✅ build 5/5 production builds
✅ audit 0 known vulnerabilities
This is what "your AI org follows the handbook" looks like in practice — the repo you're cloning was hardened by the same workflow it sells.
Frontend boundaries are executable, not just conventions. All three frontends use an FSD-inspired layered architecture checked by Steiger plus ESLint. The dapp keeps Next's framework entrypoints thin and gives application code explicit layer names:
apps/dapp/
app/ Next pages/layout/Route Handlers — delegation only
proxy.ts Next proxy entrypoint
src/
bootstrap/ App composition: routes, providers, metadata, errors, styles
screens/ Complete route screens (api/model/ui)
features/ Reusable user interactions such as sign-in
entities/ Session domain API and model
shared/ API client, config, focused libraries, routes, UI kit
- Imports point downward only:
bootstrap → screens → widgets → features → entities → shared - Same-layer slices are isolated; every slice/segment has a Public API
- Segment names describe purpose (
api,model,ui,config), not file type - Optional layers stay absent until they add value — dapp has no
widgetsyet bootstrap/screensavoid overloading framework and FSDapp/pagesnames- Components never call
fetch(); same-slice API modules use the Shared client
| Workspace | Stack | Deploys to | |
|---|---|---|---|
| 🛍️ | apps/dapp |
Next.js 16 App Router on vinext (Vite) | Cloudflare Workers |
| 🛠️ | apps/admin |
React 19 SPA — Rsbuild, route-split, code-split | Cloudflare Pages |
| 🪧 | apps/landing |
Astro — ships literally zero JS | Cloudflare Workers |
| 🧭 | services/admin-rpc |
Admin auth + market facade — Connect, JWT, gRPC client to trading-rpc | Docker |
| ⚙️ | services/trading-rpc |
Nest/Fastify hybrid — Connect + gRPC, PostgreSQL 18, /healthz |
Docker |
| 🌐 | services/api-gateway |
Edge gateway Worker — CORS allowlist, upstream proxy | Cloudflare Workers |
| 📜 | packages/protocol |
Protobuf schemas, buf lint + breaking-change gate in CI | — |
| 🧠 | packages/api-core |
One RPC implementation, two runtimes (Node + edge) | — |
| 🔌 | packages/api-client |
End-to-end typed browser client | — |
- Nonce-based CSP wired the way Next.js actually requires (on the request headers — most tutorials get this wrong)
- iron-session encrypted cookies + cryptographic session validation in middleware
- Zod at every trust boundary; constant-time credential comparison; login rate limiting
- Static CSP via
_headersfor admin/landing; allowlist-driven CORS across the backend - Boot-time kill switch: production refuses to start with placeholder secrets
Husky pre-commit → CI (typecheck, check:ci, lint, test, test:coverage, build) → CI-gated deploys (develop → staging, main → production behind manual approval) → release-please automates versioning per workspace. Nobody deploys from a laptop. Nothing skips the gates.
🤖 Pre-commit AI Code Review (Code Review Graph MCP)
Every commit triggers a semantic impact analysis powered by a Tree-sitter knowledge graph:
- Detects which functions, components, and modules are affected
- Scores risk level of changes
- Flags architectural violations before they reach PR review
- Provides blast radius visualization
This isn't linting — it's structural understanding of your codebase.
| Framework | Next.js 16 (App Router) on vinext (Vite) |
| Language | TypeScript 6 (strict mode) |
| Styling | Panda CSS + Ark UI v5 (headless, WAI-ARIA) |
| Server State | TanStack Query v5 |
| Client State | Zustand v5 + nuqs (URL state) |
| Forms | react-hook-form + Zod v4 |
| Server Actions | next-safe-action v8 (end-to-end typed) |
| Tables | TanStack Table v8 |
| HTTP | ofetch via shared xhr client (dapp) · Connect-RPC client (admin) |
| Auth | iron-session v8 (encrypted cookies) |
| Animations | Motion (Framer Motion v12) |
| Testing | Vitest v4 + Testing Library + MSW v2 + Playwright |
| Linting | Biome v2 + ESLint (architectural rules) + buf lint |
| Monitoring | Sentry — client/server/edge on dapp, DSN-gated on every app + trading-rpc |
| Monorepo | Turborepo + pnpm workspaces (strict env allowlists, cached gates) |
| Backend API | Connect RPC (Protobuf/buf) — one core, two runtimes (Workers + Node) |
| Database | PostgreSQL 18 + Drizzle ORM/Kit over a bounded node-postgres pool |
| CI/CD | GitHub Actions — Five Gates + Playwright + Dependabot + release-please + CI-gated deploys |
| Containers | Docker definitions centralized in infra/docker (multi-stage, non-root) |
Install and activate mise first. Mise is the repository's supported toolchain and command interface. pnpm stays under the hood for dependency resolution and workspace execution.
For the complete per-environment onboarding, provisioning, deployment, and
rollback runbook, see
docs/setup-and-deployment.en.md
(Tiếng Việt).
# Clone
git clone https://github.com/NoahDuongMaster/vibe-code-stack-for-ceos.git
cd vibe-code-stack-for-ceos
# Install the locked Node.js/pnpm toolchain and frozen dependencies
mise run setup
# Copy the complete local defaults once on a fresh clone.
cp .env.sample .env
cp apps/dapp/.env.sample apps/dapp/.env
cp apps/dapp/.dev.vars.sample apps/dapp/.dev.vars
cp apps/admin/.env.sample apps/admin/.env
cp apps/landing/.env.sample apps/landing/.env
cp services/trading-rpc/.env.sample services/trading-rpc/.env
cp services/admin-rpc/.env.sample services/admin-rpc/.env
cp services/api-gateway/.dev.vars.sample services/api-gateway/.dev.vars
# Start native hot reload plus its Docker VPC infrastructure
mise run dev
# …or one department
mise run dev:web # Next.js app → http://localhost:46000
mise run dev:admin # React admin SPA → http://localhost:46001
mise run dev:landing # Astro landing → http://localhost:46002
mise run dev:api # Native Connect-RPC; starts PostgreSQL first
mise run dev:admin-api # Admin RPC facade → trading-rpc native gRPC
mise run dev:gateway # Gateway → http://localhost:46003
mise run dev:backend # Gateway + native admin-rpc + native trading-rpcLocal listeners use the repository-specific 46000–46010 range rather than
common framework/database ports. Docker VPC origins use 46104–46107 so they
can run beside both native RPC services. Override Docker host ports in the root
.env if one of these ports is already occupied.
mise run dev starts PostgreSQL, the VPC-visible trading-rpc origin, and
cloudflared before Turbo starts the six native hot-reload processes. Ctrl-C
stops the native processes but keeps that infrastructure ready for a fast
restart. Stop it explicitly when finished:
mise run dev:infra:stopThe gateway task starts its Docker origin and Tunnel dependency before running the Worker locally with its remote development binding:
mise run dev:gateway
# In a second terminal
curl -sS -X POST http://127.0.0.1:46003/trading.v1.TradingService/GetMarkets \
-H 'content-type: application/json' \
-H 'connect-protocol-version: 1' \
--data '{"coinIds":["bitcoin","ethereum"],"vsCurrency":"usd"}'mise run dev:gateway selects env.development from wrangler.jsonc; Worker code
runs locally while TRADING_RPC.fetch() executes through Cloudflare's remote
VPC binding. The binding is mandatory in every environment; the gateway fails
closed when it is absent and never falls back to a direct URL.
The development VPC Service targets the network-scoped Docker alias
trading-rpc.internal:3001; override it before startup with
TRADING_RPC_PRIVATE_HOSTNAME when an environment needs a different internal
DNS suffix.
trading-rpc keeps Connect/gRPC on 3001/50051 inside its container. Host
diagnostics use 46104/46105, leaving native 46004/46005 free. For a
reliable CoinGecko quota, add a free Demo key as COINGECKO_API_KEY in
services/trading-rpc/.env: the Node service owns the TradingService use
case and its CoinGecko adapter, while the gateway only proxies the Connect
request. Staging and production require isolated TRADING_RPC VPC Service IDs
before those environments can proxy this capability.
admin-rpc exposes auth.v1.AuthService/Login and
admin.v1.AdminService/GetMarkets. Login credentials and JWT signing stay on
the server; the browser receives a short-lived signed token, and the gateway
protects non-public RPC routes with the matching secret. The market facade
validates the admin request, calls trading.v1.TradingService/GetMarkets over
native gRPC, validates the downstream response, and returns the coin market
fields without owning CoinGecko or database logic. Browser/admin traffic calls
both services through the gateway's separate ADMIN_RPC VPC Service binding:
curl -sS -X POST http://127.0.0.1:46003/admin.v1.AdminService/GetMarkets \
-H 'content-type: application/json' \
-H 'connect-protocol-version: 1' \
--data '{"coinIds":["bitcoin","ethereum"],"vsCurrency":"usd"}'Terraform registers admin-rpc.internal:3001 and
trading-rpc.internal:3001 as separate VPC Services. Deployment CI reads their
IDs from encrypted remote state and generates the environment-specific Wrangler
config; no fake or manually copied service ID is committed. The two RPC images
and the PostgreSQL/pgBackRest image deploy to one private EC2 host per
environment through immutable ECR tags and Systems Manager, without SSH or
public RPC/database ports. See
infra/terraform/README.md for the complete
AWS/Cloudflare bootstrap, plan, apply, rollout, and rollback runbook.
Then point your AI tool of choice at the repo. It reads AGENTS.md and behaves. That's it — that's the onboarding.
🐳 Docker environments
infra/docker is the single source of truth for container builds. Development
uses one shared non-root workspace image for the Cloudflare-native apps,
dedicated admin-rpc and trading-rpc images, a pgBackRest-enabled PostgreSQL
18 image based on the official image, and cloudflare/cloudflared:latest.
Every build uses the repo root as its context.
# Development: six runtimes + PostgreSQL + cloudflared
mise run docker:start
# Development: one app/service plus its declared dependencies
mise run docker:start:dapp
mise run docker:start:admin
mise run docker:start:landing
mise run docker:start:api-gateway
mise run docker:start:admin-rpc
mise run docker:start:trading-rpc
# Follow or stop the complete development stack
make logs-development
mise run docker:stop
# Staging → http://localhost:46200
docker compose -f infra/docker/compose.yaml -f infra/docker/compose.staging.yaml up --build
# Production → http://localhost:80
docker compose -f infra/docker/compose.yaml -f infra/docker/compose.prod.yaml up --buildDevelopment exposes dapp on 46000, admin on 46001, landing on 46002, the
gateway on 46003, trading-rpc Connect/gRPC on 46104/46105, and admin-rpc
Connect/gRPC on 46106/46107 in the Docker stack. Native trading-rpc uses
46004/46005, and native admin-rpc uses 46006/46007; the separate
VPC-origin ports allow both pairs to run together. PostgreSQL is available only
on loopback port 46008 and persists through the named postgres-data volume.
The trading-rpc capability owns its Drizzle schema and generated migration
journal. Use pnpm --filter @services/trading-rpc db:generate after changing
the schema and pnpm --filter @services/trading-rpc db:migrate to migrate a
configured database outside normal service bootstrap.
It requires the rotated tunnel token at
infra/docker/secrets/cloudflare-tunnel-token; see
infra/docker/README.md. Use
make start-staging|start-production for the other environments and
make check-docker after configuration changes. Staging expects
apps/dapp/.env.staging; production expects
apps/dapp/.env.production.local. Both are git-ignored and required at runtime.
🔑 Environment variables
Declared in apps/dapp/src/shared/config/env.ts with Zod validation. Application
configuration never reads process.env outside validated config boundaries;
framework-owned execution flags are the documented exception. Every committed
sample contains runnable local values; copy the samples shown in Quick Start
before starting the stack.
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_PROJECT_NAME |
Yes | App / project display name |
NEXT_PUBLIC_BASE_URL |
Yes | Public base URL (must be a valid URL) |
SESSION_SECRET |
Yes | iron-session secret (32+ chars) |
DEMO_AUTH_EMAIL |
Yes | Login email for the built-in demo auth flow (src/features/sign-in/model/verify-credentials.server.ts) — the server refuses to boot without it |
DEMO_AUTH_PASSWORD |
Yes | Login password for the built-in demo auth flow — refuses to boot without it, and refuses to boot in production if left as a known placeholder |
NEXT_PUBLIC_API_ENDPOINT |
Yes | API gateway base URL |
NEXT_PUBLIC_CORS_COOKIE |
Optional | Cookie domain for CORS |
NEXT_PUBLIC_SENTRY_DSN |
Optional | Sentry DSN (blank disables Sentry) |
CORS_ORIGINS / CORS_RESOURCE |
Optional | Server-only CORS allowlists |
SENTRY_ORG / SENTRY_PROJECT |
Optional, build-time only | Enables the Sentry plugin in next.config.ts — set as GitHub Environment vars in deploy.yml, not in .env |
SENTRY_AUTH_TOKEN |
Optional, build-time only | Required alongside the two above to upload source maps — set as a GitHub Environment secret |
| Command (repo root) | What it does |
|---|---|
mise run setup |
Install the locked toolchain and frozen dependencies |
mise run dev |
Start native apps and their PostgreSQL/VPC infrastructure |
mise run dev:web / dev:admin / dev:landing / dev:api / dev:admin-api / dev:gateway |
Start one workspace and its required infrastructure |
mise run dev:backend |
Start the gateway, admin-rpc, and trading-rpc together |
mise run dev:infra:stop |
Stop infrastructure created for native development |
mise run build |
Build every workspace |
mise run typecheck |
Run TypeScript checks across all workspaces |
mise run lint |
Run ESLint, Biome, buf, and architecture checks |
mise run check / check:ci / format |
Apply Biome fixes / run the read-only gate / format files |
mise run test |
Run toolchain and workspace unit tests |
mise run test:coverage |
Enforce frontend feature/entity coverage thresholds |
mise run test:e2e |
Run dapp Playwright tests |
mise run test:e2e:production |
Build and test the dapp production server |
mise run test:docker |
Test release images and PostgreSQL backup/restore |
mise run test:protocol |
Check generated protobuf code and compatibility |
mise run security:audit |
Reject known high-severity dependency vulnerabilities |
mise run verify |
Run every definition-of-done gate sequentially |
mise run docker:start / docker:stop / docker:check |
Operate or validate the complete Docker development stack |
mise run docker:start:dapp / docker:start:admin / docker:start:landing |
Start one frontend container and its declared dependencies |
mise run docker:start:api-gateway / docker:start:admin-rpc / docker:start:trading-rpc |
Start one backend container and its dependencies |
Use direct pnpm only for targeted workspace commands that have no mise task. Deployment remains GitHub Actions-only.
.
├── apps/
│ ├── dapp/ Next.js 16 app (vinext) — layered architecture
│ ├── admin/ React 19 admin SPA — layered architecture
│ └── landing/ Astro marketing site (zero JS)
├── packages/
│ ├── protocol/ Protobuf/Connect contracts (buf codegen → src/gen)
│ ├── api-core/ Runtime-agnostic Connect service + CORS-aware fetch handler
│ └── api-client/ End-to-end typed Connect RPC client
├── services/
│ ├── api-gateway/ Connect RPC on Cloudflare Workers (edge + upstream proxy)
│ ├── admin-rpc/ Admin RPC facade → trading-rpc over native gRPC
│ └── trading-rpc/ Coin market source of truth on Node.js
├── infra/docker/ All Dockerfiles + shared Compose/environment overlays
├── AGENTS.md ★ The company handbook — every AI agent reads this
├── CLAUDE.md → symlink to AGENTS.md
├── turbo.json Turborepo task pipeline
└── pnpm-workspace.yaml Workspaces + dependency overrides
- Fork the repo
- Create a branch:
feat(scope)/short-description(Conventional Commits, lowercase kebab) - Follow the handbook:
AGENTS.md - Pass the gates:
mise run verify - Open a PR
Yes — your AI agent can do all five steps. That's the point. 🎩
If this saved you time, star the repo — it helps other CEOs find their handbook.
Built by Noah Duong · MIT License