Turn a plain-English software idea into a complete, structured software specification. SpecPilot runs the idea through a sequence of AI agent stages (understand → requirements → user stories → milestones → format) and streams live progress to the UI, then presents a structured document with project summary, target users, roles, functional & non-functional requirements, user stories, milestones, and technical considerations.
Optionally, users can create an account and sign in. When signed in, every generated specification is automatically saved to their account, and they can browse and reopen their previously generated specifications. Generation itself stays open to everyone — signing in only adds persistence.
- Frontend: React 18 + TypeScript + Vite + Tailwind CSS (
frontend/) - Backend: Node.js + Express + TypeScript (
backend/) - AI: Fetch.ai / ASI:One hosted inference endpoint (OpenAI-compatible chat completions)
- Auth & storage: Firebase Authentication (Email/Password) + Cloud Firestore. The frontend uses Firebase only for authentication; all Firestore access goes through the backend via the Firebase Admin SDK (see Firebase setup below).
- Node.js 20 LTS or newer
- A Fetch.ai / ASI:One API key (for real generation)
- A Firebase project (only if you want authentication + saved specifications; generation works without it) — see Firebase setup
# Backend
cd backend
npm install
cp .env.example .env # then edit .env and set FETCH_AI_API_KEY (see below)
# Frontend
cd ../frontend
npm installBackend configuration lives in backend/.env (git-ignored). Copy it from
backend/.env.example and set your real values — most importantly FETCH_AI_API_KEY.
Every variable is documented in backend/.env.example and in
specs/001-specpilot/quickstart.md.
The backend reads
.envonly at startup. After editing it, restart the backend.
The frontend defaults to proxying /api to http://localhost:4000. To point it elsewhere,
set VITE_API_BASE_URL in frontend/.env (see frontend/.env.example). The frontend also
reads VITE_FIREBASE_* values for authentication — see
Firebase setup.
# Terminal 1 — backend (http://localhost:4000)
cd backend
npm run dev
# Terminal 2 — frontend (http://localhost:5173, proxies /api → backend)
cd frontend
npm run devOpen http://localhost:5173.
Authentication and saved specifications are optional. Without any Firebase configuration the
app still generates specifications for everyone (anonymously); the backend simply returns
auth_unavailable for the /api/me/* persistence endpoints, and the UI's sign-in features are
inert. To enable accounts + saved specifications, set up a Firebase project:
- In the Firebase console, create a project (this app was
developed against project id
specpilot-ad3ba— use your own). - Authentication → Sign-in method → enable Email/Password.
- Firestore Database → create a database (production mode is fine — the rules below lock out direct client access).
Register a Web app in Project settings and copy its config into frontend/.env
(see frontend/.env.example). These values are public by design for a web client:
VITE_FIREBASE_API_KEY=...
VITE_FIREBASE_AUTH_DOMAIN=your-project-id.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
VITE_FIREBASE_APP_ID=...
The frontend uses Firebase for authentication only — it never talks to Firestore directly.
Generate a service account key (Project settings → Service accounts → Generate new private
key) and save it as backend/firebase-service-account.json (git-ignored). Then in backend/.env
(see backend/.env.example):
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_SERVICE_ACCOUNT_PATH=./firebase-service-account.json
Alternatively, set FIREBASE_SERVICE_ACCOUNT to the service-account JSON inlined as a string
(handy for hosted deployments). The backend verifies each request's Firebase ID token and performs
all Firestore reads/writes with the Admin SDK. On startup it logs whether Firebase Admin
initialized ([firebase-admin] initialized for project "…"), so misconfiguration is visible
immediately.
Both the service-account path and
backend/.envare resolved relative to the backend directory, so the backend can be started from any working directory.
Because all persistence goes through the Admin SDK (which bypasses Security Rules), the rules in
firestore.rules deny all direct client access — the backend's ID-token
verification is the sole authorization boundary. Deploy them with the
Firebase CLI:
firebase deploy --only firestore:rulesThe project is pinned in .firebaserc; update it to your own project id.
- Data model: saved specifications live at
users/{uid}/specifications/{id}— each user's records are naturally isolated by their auth uid. - Save: when a signed-in user's generation succeeds, the specification is saved to their account automatically (best-effort — a save failure never interrupts the result view).
- Browse / reopen: My Specifications (
/library) lists a user's saved specifications newest-first; opening one (/library/:id) renders it with the same view as a fresh result. - Rename: the pencil beside the title (on a fresh result or a saved one) edits it in place — Enter or clicking away saves. When the specification exists in the account, the new title is written to Firestore before the screen updates; for a guest it simply renames the result on screen.
- Delete: the trash icon beside the title deletes a specification after a confirmation prompt — from the library list, an open saved specification, or a fresh result once it has been saved to the account. Deleting whatever is on screen returns to the library. A guest's result has no stored record, so the action isn't offered there.
- Auth-only routes (
/library,/library/:id) are guarded and redirect to/loginwhen signed out.
Production runs the frontend on Vercel and the backend on Render (a long-running Node
web service — not serverless). The two are on different origins, so the frontend calls the
backend at VITE_API_BASE_URL and the backend enables CORS for the frontend origin
(CORS_ORIGIN).
Uses render.yaml (Blueprint). In the Render dashboard: New + → Blueprint,
point at this repo. It creates a web service with:
- Root directory:
backend - Build:
npm install && npm run build - Start:
npm start(node dist/server.js) - Health check:
/api/health
Set these environment variables in the Render dashboard (do not commit them):
| Variable | Notes |
|---|---|
FETCH_AI_API_KEY |
secret |
FETCH_AI_ENDPOINT_URL |
e.g. https://api.asi1.ai/v1 |
FETCH_AI_MODEL |
e.g. asi1-mini |
GENERATION_TIMEOUT_MS, IDEA_MIN_LENGTH, IDEA_MAX_LENGTH |
defaults in render.yaml |
FIREBASE_PROJECT_ID |
your Firebase project id |
FIREBASE_SERVICE_ACCOUNT |
the service-account JSON inlined as one string (use this on Render; FIREBASE_SERVICE_ACCOUNT_PATH is for local dev) |
CORS_ORIGIN |
the deployed frontend origin, e.g. https://your-app.vercel.app |
PORTis injected by Render automatically — do not set it. The server readsprocess.env.PORT.
Uses frontend/vercel.json (SPA rewrite so React routes survive a
refresh). In the Vercel dashboard: Add New → Project, import this repo, and set:
- Root directory:
frontend - Build command:
npm run build· Output directory:dist(auto-detected viavercel.json)
Set these environment variables:
| Variable | Value |
|---|---|
VITE_API_BASE_URL |
the deployed backend URL, e.g. https://specpilot-backend.onrender.com |
VITE_FIREBASE_API_KEY, VITE_FIREBASE_AUTH_DOMAIN, VITE_FIREBASE_PROJECT_ID, VITE_FIREBASE_APP_ID |
from your Firebase Web app config |
- Deploy the backend first to get its Render URL.
- Deploy the frontend with
VITE_API_BASE_URL= that Render URL. - Set the backend's
CORS_ORIGINto the Vercel URL and redeploy the backend. - Deploy the Firestore rules once:
firebase deploy --only firestore:rules.
Both projects expose the same scripts:
| Script | What it does |
|---|---|
npm run dev |
Start in watch mode |
npm run build |
Type-check and build |
npm run typecheck |
Type-check only |
npm run lint |
ESLint |
npm run format / npm run format:check |
Prettier write / check |
npm test |
Run the test suite (Vitest) |
The backend also has npm start to run the compiled server from dist/.
cd backend && npm test # unit, contract, and integration tests
cd frontend && npm test # component and flow testsEnd-to-end run and validation steps for every user flow (generate, progress, result, download,
copy, generate-again, cancel, and the failure/timeout path) are in
specs/001-specpilot/quickstart.md.
The full specification and design live under specs/001-specpilot/:
spec.md (requirements), plan.md (architecture), data-model.md, contracts/api.md,
research.md, and quickstart.md. Project principles are in
.specify/memory/constitution.md.