Monorepo that powers RoboSite: a web app that generates Vite + React + Tailwind landing pages using OpenAI, builds them, and uploads both source and build output to S3.
- Web (
apps/web): UI for submitting prompts and tracking job status. - API (
apps/api): creates jobs and exposes status endpoints. - Worker (
apps/worker): generates files, runsvite build, and uploads to S3. - Redis: queue backend for BullMQ.
- Postgres: reserved for future metadata storage (optional right now).
- Web authenticates via API and stores a JWT.
- Web submits
{ clientId, prompt }to API with the JWT. - API saves the job in Postgres, enqueues it in Redis, and returns
jobId. - Worker consumes the job:
- copies a Vite + React + Tailwind template
- asks OpenAI for
src/**+public/**files - builds the project
- uploads
siteid/src/**andsiteid/build/**to S3
- Web polls
/api/jobs/:idfor status and result (from Postgres).
cp .env.example .env
# fill in your keys
docker compose up --buildOpen:
- Web:
http://localhost:3000 - API:
http://localhost:3001/health
npm install
npm run api
npm run worker
npm run webShared values live in .env and are loaded by Docker Compose.
Web
NEXT_PUBLIC_API_URL
API
API_PORTCORS_ORIGINREDIS_URLQUEUE_NAMEJOB_ATTEMPTSMAX_PROMPT_LENGTHJWT_SECRETJWT_TTL
Worker
WORKER_CONCURRENCYROBOSITE_KEEP_WORKDIR
OpenAI
OPENAI_API_KEYOPENAI_MODELOPENAI_API_URLOPENAI_MAX_TOKENSOPENAI_TIMEOUT_MSOPENAI_LOG_RESPONSEOPENAI_REASONING_EFFORTOPENAI_RESPONSE_FORMATOPENAI_ENABLE_JSON_REPAIROPENAI_JSON_REPAIR_MODELOPENAI_JSON_REPAIR_RESPONSE_FORMATOPENAI_JSON_REPAIR_MAX_CHARSOPENAI_FALLBACK_MODELOPENAI_ALLOW_FALLBACK
S3 / AWS
S3_BUCKETS3_PUBLIC_BASE_URLS3_ENDPOINTAWS_REGIONAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKENAWS_URL_PASSPORTS,AWS_BUCKET_PASSPORTS,AWS_ENDPOINT_CDN,AWS_ENDPOINTS3_OBJECT_ACL
Postgres (required)
POSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_DBDATABASE_URL
siteid/src/**— the Vite project sourcesiteid/build/**— the static build output
POST /api/auth/register→{ email, password }POST /api/auth/login→{ email, password }GET /api/me→Authorization: Bearer <token>