Developer-first launch platform for validating product demand before GA.
- 1. Project Summary
- 2. Why This Project Exists
- 3. Who Uses DevLaunch
- 4. Core Features
- 5. Widget Catalog
- 6. End-to-End User Flows
- 7. System Architecture
- 8. Package Responsibilities
- 9. Data Model
- 10. API Design
- 11. Mermaid Architecture Diagram
- 12. API Request/Response Examples
- 13. Security and Secret Management
- 14. Environment Setup
- 15. Scripts and Developer Workflow
- 16. Production Deployment
- 17. Contributor Onboarding Checklist
- 18. Budget and Cost Planning
- 19. Observability and Reliability
- 20. Troubleshooting Guide
- 21. Quality Gates
- 22. Roadmap
- 23. Glossary
DevLaunch is a SaaS-style platform where creators can publish early product pages, collect signals from real users, and decide whether to invest more development into a product.
In short, DevLaunch answers one question:
- "Is this product worth building further?"
Primary reference docs:
- Architecture notes:
docs/architecture.md - Prisma schema:
packages/db/prisma/schema.prisma
Many builders launch too late, after spending months on features without market proof. DevLaunch moves validation earlier by combining:
- waitlist demand
- qualitative feedback
- lightweight voting
- early-access checkout intent
Business value:
- reduces product risk
- improves roadmap quality
- turns assumptions into measurable signals
- Creates launch pages
- Tracks engagement and demand
- Reads feedback before investing in full build
- Discovers new products
- Joins waitlists
- Leaves feedback
- Purchases early access if convinced
- Monitors notifications and analytics
- Reviews project performance trends
- Manages account and security settings
- Product launch page creation with slug handling
- Discovery listing and ranking/trending behavior
- Waitlist capture and feedback collection
- Vote-based demand signaling
- Early-access checkout flow
- Dashboard summary and activity monitoring
- Notification and session management
| Widget | Purpose | UI/UX detail |
|---|---|---|
Trending Project Cards |
Highlight hot products | Rank badge, score chip, vote/waitlist metrics |
Project Hero Summary |
Context at first glance | Status, date, slug, metadata layout |
Project Quick Actions |
Fast outbound actions | Share, copy link, open website |
| Widget | Purpose | Interaction |
|---|---|---|
Waitlist CTA |
Capture user interest | Email input -> submit -> success feedback |
Feedback Composer |
Collect qualitative insight | Text input -> API submit -> feed update |
Feedback Feed |
Show social proof | Newest-first feedback list |
Vote Action |
Low-friction support signal | One-click vote with auth checks |
| Widget | Purpose | Flow detail |
|---|---|---|
Checkout Modal |
Monetize early demand | Email -> Review -> Checkout steps |
Consent Gate |
Legal clarity | Explicit agreement before payment action |
Payment Fallback |
Dev flow continuity | Mock checkout when provider is placeholder |
| Widget | Purpose | Data source |
|---|---|---|
Summary Cards |
Quick health check | Revenue, waitlist, notifications, top projects |
Mini Sparkline |
Trend visibility | Weekly and 14-day analytics slices |
Notification Center |
Actionable updates | Read/unread and activity feed |
Settings Panels |
Account control | Profile, password, session revocation |
- User signs in.
- Opens launch form and enters product details.
- System validates input with shared Zod schemas.
- API writes project + media in database.
- Product appears on discovery and detail pages.
- Visitor opens project page.
- Visitor joins waitlist and/or votes.
- Visitor leaves feedback text.
- Creator sees updated engagement and dashboard changes.
- Visitor starts checkout from project page.
- Email capture and review step complete.
- API requests provider checkout session.
- In dev invalid token scenarios, fallback route is used.
- Purchase intent is visible in creator metrics.
apps/
web/ Next.js 16 app router frontend
api/ Elysia.js API on Bun
packages/
ui/ Reusable design system components
db/ Prisma schema/client and query helpers
validation/ Zod schemas shared by API and web
types/ Shared TypeScript domain types
config/ Environment parser/config helpers
docs/
architecture.md- Presentation layer:
apps/webhandles routing, pages, client interactions, and theming.
- Application/API layer:
apps/apihandles auth, business rules, route orchestration, and service logic.
- Domain/shared contracts:
packages/validationandpackages/typesdefine shared shapes.
- Data/persistence layer:
packages/dbdefines Prisma models and database access patterns.
- Web component sends
POST /feedback. - API route parses body and validates schema.
- Service applies business checks (project existence, ownership rules if needed).
- Prisma writes feedback row.
- API responds with normalized payload.
- Web refreshes feed and updates UI state.
- clear separation of concerns
- typed contracts from edge to DB
- reusable packages in monorepo
- safe development fallbacks for external providers
- Next.js App Router pages
- Dashboard and project UI
- Client-side API integration and error display
- Elysia route modules
- Service-layer business logic
- Third-party integrations (Polar, email)
- Shared visual components
- Reusable layout/navigation building blocks
- Prisma schema and generated client
- Data query helpers and typed persistence access
- Shared Zod input/output schemas
- Unified payload validation for web and API
- Shared TypeScript domain models
- DTO-like utility types
- Environment variable parsing
- Runtime-safe configuration helpers
Main entities:
User,Session,CreatorProfileProject,ProjectMediaWaitlist,Feedback,VotePurchase,Notification,AnalyticsEvent
Relationship summary:
- User -> many Projects
- Project -> many Waitlist entries, Feedback records, Votes
- Project -> many AnalyticsEvent records
- User -> many Notifications and Sessions
Data rules and constraints:
- unique project slug
- ownership checks on mutating endpoints
- indexed read-heavy fields
- denormalized counters/trending score for discovery speed
Auth:
POST /auth/registerPOST /auth/loginGET /auth/session
Projects:
POST /projectsGET /projectsGET /projects/:slugPUT /projects/:idDELETE /projects/:id
Engagement:
POST /waitlistPOST /feedbackGET /feedback/project/:projectIdPOST /votes
Analytics:
GET /analytics/project/:id
Payments:
POST /payments/create-checkoutPOST /payments/webhook
Dashboard:
GET /dashboard/summaryGET /dashboard/project/:projectId/activityGET /dashboard/notificationsPUT /dashboard/notifications/:id/read
Settings:
GET /settings/mePUT /settings/profilePOST /settings/passwordGET /settings/sessionsDELETE /settings/sessions/:id
Health:
GET /health
- schema validation at route boundaries
- consistent error messages for UX clarity
- auth and ownership checks before writes
- explicit fallback behavior in dev integrations
flowchart LR
U[Visitor / Creator] --> W[Next.js Web App\napps/web]
W -->|HTTP JSON| A[Elysia API\napps/api]
A --> V[Zod Validation\npackages/validation]
A --> D[(PostgreSQL)]
A --> P[Prisma Client\npackages/db]
A --> B[Better Auth]
A --> R[Resend]
A --> O[Polar Billing]
W --> UI[Shared UI\npackages/ui]
A --> T[Shared Types\npackages/types]
A --> C[Config Helpers\npackages/config]
All examples below are sample payloads for local development. Secrets/tokens are intentionally redacted.
POST /auth/register
Request:
{
"name": "Jane Doe",
"email": "jane@example.com",
"password": "StrongPass123!"
}Success response (201):
{
"user": {
"id": "cm8abc123xyz",
"name": "Jane Doe",
"email": "jane@example.com"
},
"session": {
"id": "sess_01hxyz",
"expiresAt": "2026-04-11T12:00:00.000Z"
}
}POST /projects
Request:
{
"name": "FocusDock",
"slug": "focusdock",
"tagline": "Minimal focus dashboard for makers",
"description": "Track deep work, launch goals, and weekly output.",
"websiteUrl": "https://focusdock.dev",
"category": "Productivity"
}Success response (201):
{
"id": "cm8proj001abc",
"name": "FocusDock",
"slug": "focusdock",
"status": "draft",
"createdAt": "2026-03-12T10:15:00.000Z"
}Conflict response (409):
{
"error": {
"code": "PROJECT_SLUG_EXISTS",
"message": "Slug is already taken",
"suggestedSlug": "focusdock-app"
}
}POST /feedback
Request:
{
"projectId": "cm8proj001abc",
"message": "Looks clean. I'd love Notion sync and weekly report emails."
}Success response (201):
{
"id": "cm8fb001qwe",
"projectId": "cm8proj001abc",
"message": "Looks clean. I'd love Notion sync and weekly report emails.",
"createdAt": "2026-03-12T10:20:00.000Z"
}POST /payments/create-checkout
Request:
{
"projectId": "cm8proj001abc",
"email": "buyer@example.com"
}Success response (200):
{
"checkoutUrl": "https://polar.sh/checkout/<redacted>",
"provider": "polar"
}Dev fallback response (200):
{
"checkoutUrl": "/checkout/mock?projectId=cm8proj001abc",
"provider": "mock"
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request payload",
"details": {
"field": "email",
"reason": "Must be a valid email address"
}
}
}Use these examples for local API checks.
Health check:
curl http://localhost:3001/healthRegister user:
curl -X POST http://localhost:3001/auth/register \
-H "Content-Type: application/json" \
-d '{
"name":"Jane Doe",
"email":"jane@example.com",
"password":"StrongPass123!"
}'Create project:
curl -X POST http://localhost:3001/projects \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"name":"FocusDock",
"slug":"focusdock",
"tagline":"Minimal focus dashboard for makers",
"description":"Track deep work, launch goals, and weekly output.",
"websiteUrl":"https://focusdock.dev",
"category":"Productivity"
}'Submit feedback:
curl -X POST http://localhost:3001/feedback \
-H "Content-Type: application/json" \
-d '{
"projectId":"cm8proj001abc",
"message":"Looks clean. I'd love Notion sync and weekly report emails."
}'Start checkout:
curl -X POST http://localhost:3001/payments/create-checkout \
-H "Content-Type: application/json" \
-d '{
"projectId":"cm8proj001abc",
"email":"buyer@example.com"
}'- Never commit
.env. - Never publish real database URLs or provider tokens.
- Never include secrets in README, screenshots, issues, or logs.
- Rotate compromised credentials immediately.
DATABASE_URL="postgresql://<user>:<password>@<host>:5432/<database>"
BETTER_AUTH_SECRET="<strong-random-secret>"
BETTER_AUTH_URL="http://localhost:3000"
POLAR_ACCESS_TOKEN="<polar-access-token>"
POLAR_ORGANIZATION_ID="<polar-org-id>"
RESEND_API_KEY="<resend-api-key>"
UPLOADTHING_TOKEN="<uploadthing-token>"
NEXT_PUBLIC_API_URL="http://localhost:3001"NEXT_PUBLIC_*variables can appear in browser bundles.- Non-public variables are server-only.
- DB credentials and webhook secrets must stay private.
- Bun
>=1.2 - PostgreSQL
>=15
bun installbun run db:generate
bun run db:migratebun run devOptional single-app mode:
bun run --cwd apps/api dev
bun run --cwd apps/web devDefault local URLs:
- Web:
http://localhost:3000 - API:
http://localhost:3001
Root scripts:
bun run devbun run buildbun run typecheckbun run lintbun run db:generatebun run db:migrate
Scoped scripts:
- API:
bun run --cwd apps/api dev | build | start | typecheck - Web:
bun run --cwd apps/web dev | build | typecheck
Suggested daily workflow:
- Pull latest changes.
- Run
bun installif lockfile changed. - Run DB generate/migrate if schema changed.
- Start local apps.
- Typecheck before commit.
Recommended production topology:
- Web: Vercel (
apps/web) - API: Vercel Project (
apps/api) - DB: Managed PostgreSQL (Neon/Supabase/Vercel Postgres)
Create secure values for:
DATABASE_URLBETTER_AUTH_SECRETPOLAR_ACCESS_TOKENPOLAR_ORGANIZATION_IDRESEND_API_KEYUPLOADTHING_TOKEN
Do not reuse local placeholder values in production.
Vercel API project settings:
- Framework Preset:
Other - Root Directory:
apps/api - API entrypoint:
api/[...route].ts - Rewrites: handled by
apps/api/vercel.json
API environment variables:
NODE_ENV="production"
DATABASE_URL="postgresql://<user>:<password>@<host>:5432/<database>"
BETTER_AUTH_SECRET="<strong-random-secret>"
BETTER_AUTH_URL="https://<your-web-domain>"
CORS_ORIGIN="https://<your-web-domain>"
POLAR_ACCESS_TOKEN="<polar-access-token>"
POLAR_ORGANIZATION_ID="<polar-org-id>"
RESEND_API_KEY="<resend-api-key>"
UPLOADTHING_TOKEN="<uploadthing-token>"
NEXT_PUBLIC_API_URL="https://<your-api-domain>"Health check URL:
https://<your-api-domain>/health
Vercel project settings:
- Framework:
Next.js - Root Directory:
apps/web - Install Command:
bun install --frozen-lockfile - Build Command:
bun run build - Output: default Next.js output
Web environment variables:
NEXT_PUBLIC_API_URL="https://<your-api-domain>"- Set API
BETTER_AUTH_URLto the exact web production URL. - Set API
CORS_ORIGINto same web URL. - If you use multiple domains, separate by comma:
CORS_ORIGIN="https://app.example.com,https://www.example.com"
curl https://<your-api-domain>/healthExpected:
{"ok":true,"service":"devlaunch-api"}Then verify in browser:
- Web home opens correctly.
- Register/login works.
- Project creation works.
- Feedback and checkout flows return expected responses.
Use this checklist when a new contributor joins the project.
- Clone repository and install Bun.
- Create local
.envfrom.env.example. - Request required secrets from team vault (never from chat/email).
- Verify DB access using redacted/local credentials only.
- Run
bun install. - Run
bun run db:generate. - Run
bun run db:migrate. - Start app with
bun run devor per-app dev commands. - Confirm web at
http://localhost:3000. - Confirm API health at
http://localhost:3001/health.
- Run API typecheck:
bun run --cwd apps/api typecheck. - Run web typecheck:
bun run --cwd apps/web typecheck. - Follow shared schema contracts from
packages/validation. - Keep secrets out of commits, logs, screenshots, and PR text.
- Add/adjust tests when behavior changes.
- Include migration notes if schema changed.
- Add screenshots for UI changes.
- Document any new env variable in
.env.examplewith placeholder value.
| Item | Starter | Growth | Notes |
|---|---|---|---|
| PostgreSQL (managed) | $25 | $120 | backups, storage, read scaling |
| App hosting (web + api) | $20 | $100 | region and instance sizing |
| Media storage/CDN | $10 | $60 | logos, screenshots, assets |
| Email provider (Resend) | $10 | $50 | transactional volume |
| Observability/logging | $0-$20 | $60 | logs, alerts, traces |
| Domain + SSL + edge extras | $2 | $10 | DNS and edge services |
| Total | $67-$87 | $400 | excludes payment processing fees |
- provider fees are transaction-based
- keep mock checkout only in development
- use production secrets in secure stores only
Operational recommendations:
- expose health route checks in uptime monitor
- track API latency and error rates
- track checkout conversion and fallback ratio
- track waitlist conversion per project
- alert on payment webhook failures
Reliability posture:
- graceful fallbacks for non-critical external errors in dev
- strict validation to avoid corrupted writes
- route-level error messages for faster debugging
Cause:
- slug already exists.
Behavior:
- UI suggests alternative slug candidates.
Checklist:
- API is running on
:3001 GET http://localhost:3001/healthreturns200NEXT_PUBLIC_API_URLmatches runtime host- no host mismatch (
localhostvs127.0.0.1)
Cause:
- invalid or placeholder credentials.
Behavior:
- development fallback route is used safely.
Before commit:
bun run --cwd apps/api typecheck
bun run --cwd apps/web typecheckOptional smoke checks:
curl http://localhost:3001/health- richer dashboard widgets (funnel, retention)
- feedback sorting/filtering and pagination
- project update timeline widget
- background job queue for fanout email/notifications
- role-based admin moderation panel
- GA: General Availability release.
- Demand signal: measurable interest, such as waitlist, vote, purchase intent.
- Early access: paid or invite-based pre-release usage.
- Fallback checkout: safe dev-mode route when payment setup is invalid.
Private workspace project.