···11+# Lively Forms
22+33+Lively Forms is a Typeform-inspired conversational form builder built with Next.js, Auth.js, Prisma, PostgreSQL, Tailwind, Framer Motion, and dnd-kit.
44+55+## Stack
66+77+- Next.js App Router
88+- TypeScript
99+- Tailwind CSS
1010+- shadcn/ui-style local primitives
1111+- Framer Motion
1212+- dnd-kit
1313+- Auth.js (`next-auth`) with Google OAuth for creators
1414+- Prisma + PostgreSQL
1515+- Podman Compose for local Postgres
1616+1717+## Local setup
1818+1919+### 1. Install dependencies
2020+2121+```bash
2222+bun install
2323+```
2424+2525+### 2. Start Postgres with Podman
2626+2727+```bash
2828+bun run db:up
2929+```
3030+3131+This uses `compose.yaml` and starts a local Postgres container on `localhost:5432`.
3232+3333+### 3. Create local env file
3434+3535+```bash
3636+cp .env.example .env
3737+```
3838+3939+Fill in:
4040+- `AUTH_SECRET`
4141+- `AUTH_GOOGLE_ID`
4242+- `AUTH_GOOGLE_SECRET`
4343+- `NEXTAUTH_URL` (keep `http://localhost:3000` for local dev)
4444+4545+Generate a secret, for example:
4646+4747+```bash
4848+openssl rand -base64 32
4949+```
5050+5151+### 4. Configure Google OAuth for local development
5252+5353+Yes — Google OAuth can work locally, but you must create your own OAuth client in Google Cloud and allow localhost.
5454+5555+In Google Cloud Console:
5656+5757+1. Open **APIs & Services → Credentials**
5858+2. Create an **OAuth 2.0 Client ID**
5959+3. Choose **Web application**
6060+4. Add these local settings:
6161+6262+**Authorized JavaScript origins**
6363+- `http://localhost:3000`
6464+6565+**Authorized redirect URIs**
6666+- `http://localhost:3000/api/auth/callback/google`
6767+6868+Then copy the generated values into `.env`:
6969+7070+```env
7171+AUTH_GOOGLE_ID="your-client-id"
7272+AUTH_GOOGLE_SECRET="your-client-secret"
7373+```
7474+7575+If these values are missing or wrong, Google will show:
7676+- `Error 401: invalid_client`
7777+- `The OAuth client was not found`
7878+7979+### 5. Run Prisma migration
8080+8181+```bash
8282+bun run prisma:migrate
8383+```
8484+8585+### 6. Start the app
8686+8787+```bash
8888+bun run dev
8989+```
9090+9191+Open `http://localhost:3000`.
9292+9393+## Useful commands
9494+9595+```bash
9696+bun run dev
9797+bun run build
9898+bun run lint
9999+bun run db:up
100100+bun run db:down
101101+bun run db:logs
102102+bun run prisma:generate
103103+bun run prisma:migrate
104104+bun run prisma:studio
105105+```
106106+107107+## Product surfaces
108108+109109+### Creator app
110110+- `/login`
111111+- `/dashboard`
112112+- `/forms/[id]/edit`
113113+- `/forms/[id]/responses`
114114+- `/forms/[id]/responses/[responseId]`
115115+116116+### Public app
117117+- `/f/[slug]`
118118+119119+## Current v0 scope
120120+121121+- Creator Google sign-in
122122+- Owned form dashboard
123123+- Master-detail builder
124124+- Block types:
125125+ - text
126126+ - short text
127127+ - long text
128128+ - single choice
129129+ - multiple choice
130130+- Publish / unpublish
131131+- Anonymous public submissions
132132+- Responses list and detail views
133133+134134+## Notes
135135+136136+- Creator auth is used only for creating, editing, publishing, and reviewing forms.
137137+- Public respondents do not log in.
138138+- Responses are stored anonymously.
139139+- Editing a published form updates the live public form immediately in v0.
+17
app/(creator)/actions.ts
···11+"use server";
22+33+import { redirect } from "next/navigation";
44+55+import { getServerAuthSession } from "@/lib/auth";
66+import { createDraftForm } from "@/lib/forms";
77+88+export async function createFormAction() {
99+ const session = await getServerAuthSession();
1010+1111+ if (!session?.user?.id) {
1212+ redirect("/login");
1313+ }
1414+1515+ const form = await createDraftForm(session.user.id);
1616+ redirect(`/forms/${form.id}/edit`);
1717+}
+5
app/(creator)/dashboard/loading.tsx
···11+import { LoadingShell } from "@/components/loading-shell";
22+33+export default function DashboardLoading() {
44+ return <LoadingShell title="dashboard" />;
55+}
+103
app/(creator)/dashboard/page.tsx
···11+import Link from "next/link";
22+import { ArrowRight, Plus } from "lucide-react";
33+44+import { EmptyState } from "@/components/empty-state";
55+import { Badge } from "@/components/ui/badge";
66+import { Button } from "@/components/ui/button";
77+import { Card } from "@/components/ui/card";
88+import { getServerAuthSession } from "@/lib/auth";
99+import { listFormsForOwner } from "@/lib/forms";
1010+import { formatDate } from "@/lib/utils";
1111+import { createFormAction } from "@/app/(creator)/actions";
1212+1313+export default async function DashboardPage() {
1414+ const session = await getServerAuthSession();
1515+ const forms = await listFormsForOwner(session!.user.id);
1616+1717+ return (
1818+ <div className="space-y-8">
1919+ <section className="flex flex-col gap-4 rounded-[32px] border border-black/8 bg-[linear-gradient(180deg,rgba(255,255,255,0.95),rgba(235,247,235,0.92))] px-8 py-8 shadow-[0_24px_70px_rgba(15,23,42,0.06)] lg:flex-row lg:items-end lg:justify-between">
2020+ <div className="space-y-3">
2121+ <p className="text-xs font-semibold uppercase tracking-[0.28em] text-[var(--accent)]">Creator dashboard</p>
2222+ <h1 className="font-display text-5xl leading-tight text-[var(--ink)]">Build linear forms that feel composed.</h1>
2323+ <p className="max-w-2xl text-sm leading-7 text-[var(--muted)]">
2424+ Start drafts fast, keep editing focused, and send people into a one-screen-at-a-time runner that stays
2525+ anonymous on submission.
2626+ </p>
2727+ </div>
2828+ <form action={createFormAction}>
2929+ <Button size="lg" type="submit">
3030+ <Plus className="size-4" />
3131+ New form
3232+ </Button>
3333+ </form>
3434+ </section>
3535+3636+ {forms.length === 0 ? (
3737+ <EmptyState
3838+ eyebrow="No forms yet"
3939+ title="Start with a draft and shape the conversation."
4040+ description="Every new form begins with a welcome text block and a first question so you can immediately refine the flow."
4141+ action={
4242+ <form action={createFormAction}>
4343+ <Button type="submit">
4444+ <Plus className="size-4" />
4545+ Create your first form
4646+ </Button>
4747+ </form>
4848+ }
4949+ />
5050+ ) : (
5151+ <section className="grid gap-5 lg:grid-cols-2">
5252+ {forms.map((form) => (
5353+ <Card key={form.id} className="p-6">
5454+ <div className="flex items-start justify-between gap-4">
5555+ <div>
5656+ <Badge className={form.status === "PUBLISHED" ? "bg-[var(--accent-soft)] text-[#2f5d35]" : "bg-black/5"}>
5757+ {form.status === "PUBLISHED" ? "Published" : "Draft"}
5858+ </Badge>
5959+ <h2 className="mt-4 font-display text-3xl text-[var(--ink)]">{form.title}</h2>
6060+ <p className="mt-3 max-w-xl text-sm leading-7 text-[var(--muted)]">
6161+ {form.description || "No description yet — open the builder to shape the story of the form."}
6262+ </p>
6363+ </div>
6464+ <Link href={`/forms/${form.id}/edit`}>
6565+ <Button variant="secondary" size="sm">
6666+ Edit
6767+ </Button>
6868+ </Link>
6969+ </div>
7070+7171+ <div className="mt-6 grid gap-3 text-sm text-[var(--muted)] sm:grid-cols-3">
7272+ <div>
7373+ <p className="text-xs font-semibold uppercase tracking-[0.24em] text-[var(--accent)]">Share URL</p>
7474+ <p className="mt-2 truncate">/{form.slug}</p>
7575+ </div>
7676+ <div>
7777+ <p className="text-xs font-semibold uppercase tracking-[0.24em] text-[var(--accent)]">Responses</p>
7878+ <p className="mt-2">{form.responseCount}</p>
7979+ </div>
8080+ <div>
8181+ <p className="text-xs font-semibold uppercase tracking-[0.24em] text-[var(--accent)]">Updated</p>
8282+ <p className="mt-2">{formatDate(form.updatedAt)}</p>
8383+ </div>
8484+ </div>
8585+8686+ <div className="mt-6 flex flex-wrap gap-3">
8787+ <Link href={`/forms/${form.id}/edit`}>
8888+ <Button>
8989+ Open builder
9090+ <ArrowRight className="size-4" />
9191+ </Button>
9292+ </Link>
9393+ <Link href={`/forms/${form.id}/responses`}>
9494+ <Button variant="secondary">View responses</Button>
9595+ </Link>
9696+ </div>
9797+ </Card>
9898+ ))}
9999+ </section>
100100+ )}
101101+ </div>
102102+ );
103103+}
+5
app/(creator)/forms/[id]/edit/loading.tsx
···11+import { LoadingShell } from "@/components/loading-shell";
22+33+export default function EditFormLoading() {
44+ return <LoadingShell title="form builder" />;
55+}
···11+import NextAuth from "next-auth";
22+33+import { authOptions } from "@/lib/auth";
44+55+const handler = NextAuth(authOptions);
66+77+export { handler as GET, handler as POST };
···11+import type { Metadata } from "next";
22+import { Fraunces, Manrope } from "next/font/google";
33+import "./globals.css";
44+55+const fraunces = Fraunces({
66+ variable: "--font-fraunces",
77+ subsets: ["latin"],
88+});
99+1010+const manrope = Manrope({
1111+ variable: "--font-manrope",
1212+ subsets: ["latin"],
1313+});
1414+1515+export const metadata: Metadata = {
1616+ title: "Lively Forms",
1717+ description: "Lively Forms is a conversational form builder with an elegant creator workflow.",
1818+};
1919+2020+export default function RootLayout({
2121+ children,
2222+}: Readonly<{
2323+ children: React.ReactNode;
2424+}>) {
2525+ return (
2626+ <html lang="en">
2727+ <body className={`${fraunces.variable} ${manrope.variable}`}>{children}</body>
2828+ </html>
2929+ );
3030+}
+40
app/login/page.tsx
···11+import { redirect } from "next/navigation";
22+33+import { GoogleSignInButton } from "@/components/auth/google-sign-in-button";
44+import { Card } from "@/components/ui/card";
55+import { getServerAuthSession } from "@/lib/auth";
66+77+export default async function LoginPage() {
88+ const session = await getServerAuthSession();
99+1010+ if (session?.user?.id) {
1111+ redirect("/dashboard");
1212+ }
1313+1414+ return (
1515+ <main className="mx-auto flex min-h-screen max-w-4xl items-center px-6 py-16">
1616+ <Card className="grid w-full overflow-hidden lg:grid-cols-[1.1fr_0.9fr]">
1717+ <div className="bg-[#191611] p-10 text-white lg:p-14">
1818+ <p className="text-xs font-semibold uppercase tracking-[0.3em] text-[#b9dfb9]">Lively Forms creator access</p>
1919+ <h1 className="mt-8 font-display text-5xl leading-tight">Sign in to craft the form experience.</h1>
2020+ <p className="mt-6 max-w-md text-sm leading-7 text-white/70">
2121+ Creator auth is used only for owning, editing, publishing, and reviewing forms. Public respondents never
2222+ log in and their submissions stay anonymous.
2323+ </p>
2424+ </div>
2525+ <div className="flex items-center justify-center bg-[linear-gradient(180deg,rgba(255,255,255,0.92),rgba(237,247,237,0.96))] p-10 lg:p-14">
2626+ <div className="w-full max-w-sm space-y-6">
2727+ <div>
2828+ <p className="text-xs font-semibold uppercase tracking-[0.28em] text-[var(--accent)]">Lively Forms login</p>
2929+ <h2 className="mt-3 font-display text-4xl text-[var(--ink)]">Use Google to continue.</h2>
3030+ </div>
3131+ <p className="text-sm leading-7 text-[var(--muted)]">
3232+ Keep auth simple in v0 and stay focused on the form builder and conversational runner.
3333+ </p>
3434+ <GoogleSignInButton />
3535+ </div>
3636+ </div>
3737+ </Card>
3838+ </main>
3939+ );
4040+}
+24
app/not-found.tsx
···11+import Link from "next/link";
22+33+import { Button } from "@/components/ui/button";
44+import { Card } from "@/components/ui/card";
55+66+export default function NotFound() {
77+ return (
88+ <main className="mx-auto flex min-h-screen max-w-3xl items-center px-6 py-16">
99+ <Card className="w-full px-8 py-10 text-center">
1010+ <p className="text-xs font-semibold uppercase tracking-[0.28em] text-[var(--accent)]">Not found</p>
1111+ <h1 className="mt-4 font-display text-4xl text-[var(--ink)]">That page or form doesn’t exist.</h1>
1212+ <p className="mx-auto mt-3 max-w-lg text-sm leading-7 text-[var(--muted)]">
1313+ If you were expecting a public form, it may still be in draft. If you were editing a creator form, you may
1414+ not have access to it.
1515+ </p>
1616+ <div className="mt-6 flex justify-center">
1717+ <Link href="/">
1818+ <Button>Back home</Button>
1919+ </Link>
2020+ </div>
2121+ </Card>
2222+ </main>
2323+ );
2424+}
+96
app/page.tsx
···11+import Link from "next/link";
22+import { ArrowRight, Sparkles } from "lucide-react";
33+44+import { Button } from "@/components/ui/button";
55+import { Card } from "@/components/ui/card";
66+import { getServerAuthSession } from "@/lib/auth";
77+88+export default async function HomePage() {
99+ const session = await getServerAuthSession();
1010+1111+ return (
1212+ <main className="mx-auto flex min-h-screen w-full max-w-6xl flex-col px-6 py-10 lg:px-10">
1313+ <header className="flex items-center justify-between rounded-full border border-black/8 bg-white/60 px-5 py-3 backdrop-blur-sm">
1414+ <div>
1515+ <p className="text-xs font-semibold uppercase tracking-[0.32em] text-[var(--accent)]">Lively Forms</p>
1616+ <p className="text-xs text-[var(--muted)]">Conversational forms with a softer, brighter rhythm.</p>
1717+ </div>
1818+ <Link href={session?.user ? "/dashboard" : "/login"}>
1919+ <Button variant="secondary" size="sm">
2020+ {session?.user ? "Open dashboard" : "Creator login"}
2121+ </Button>
2222+ </Link>
2323+ </header>
2424+2525+ <section className="grid flex-1 items-center gap-8 py-12 lg:grid-cols-[1.25fr_0.9fr] lg:py-20">
2626+ <div className="space-y-8">
2727+ <div className="inline-flex items-center gap-2 rounded-full border border-black/8 bg-white/70 px-4 py-2 text-xs font-semibold uppercase tracking-[0.24em] text-[var(--accent)] backdrop-blur-sm">
2828+ <Sparkles className="size-3.5" />
2929+ Lively Forms v0
3030+ </div>
3131+ <div className="space-y-5">
3232+ <h1 className="max-w-4xl font-display text-6xl leading-none text-[var(--ink)] md:text-7xl">
3333+ Build forms that feel like a calm conversation.
3434+ </h1>
3535+ <p className="max-w-2xl text-lg leading-8 text-[var(--muted)]">
3636+ Create linear, elegant flows with focused screens, anonymous public submissions, and a polished
3737+ creator workflow made for shipping quickly.
3838+ </p>
3939+ </div>
4040+ <div className="flex flex-col gap-3 sm:flex-row">
4141+ <Link href={session?.user ? "/dashboard" : "/login"}>
4242+ <Button size="lg">
4343+ {session?.user ? "Go to dashboard" : "Start with Google"}
4444+ <ArrowRight className="size-4" />
4545+ </Button>
4646+ </Link>
4747+ <a href="#surfaces">
4848+ <Button variant="secondary" size="lg">
4949+ See product surfaces
5050+ </Button>
5151+ </a>
5252+ </div>
5353+ </div>
5454+5555+ <Card className="overflow-hidden bg-[linear-gradient(180deg,rgba(255,255,255,0.97),rgba(235,247,235,0.94))] p-6">
5656+ <div className="rounded-[24px] border border-black/8 bg-[#171411] p-6 text-white shadow-[0_24px_70px_rgba(23,20,17,0.26)]">
5757+ <p className="text-xs font-semibold uppercase tracking-[0.24em] text-[#b9dfb9]">Respondent experience</p>
5858+ <div className="mt-8 space-y-6">
5959+ <div className="h-1.5 rounded-full bg-white/10">
6060+ <div className="h-full w-1/2 rounded-full bg-[#9fd7a4]" />
6161+ </div>
6262+ <div className="space-y-4">
6363+ <p className="text-sm uppercase tracking-[0.3em] text-white/45">Step 2 of 4</p>
6464+ <h2 className="font-display text-4xl leading-tight">What should we call you?</h2>
6565+ <p className="max-w-sm text-sm leading-7 text-white/70">
6666+ Every step gets the full stage — large type, clean focus, and motion that keeps the flow moving.
6767+ </p>
6868+ </div>
6969+ <div className="rounded-[24px] border border-white/10 bg-white/5 p-4 text-white/55">Type your answer here…</div>
7070+ <div className="flex items-center justify-between">
7171+ <Button variant="secondary" className="border border-white/12 bg-white/8 text-white hover:bg-white/14">
7272+ Back
7373+ </Button>
7474+ <Button className="bg-[#9fd7a4] text-[#122012] hover:bg-[#b8e4bb]">Continue</Button>
7575+ </div>
7676+ </div>
7777+ </div>
7878+ </Card>
7979+ </section>
8080+8181+ <section id="surfaces" className="grid gap-6 pb-8 md:grid-cols-3">
8282+ {[
8383+ ["Creator dashboard", "Start new forms, manage drafts, and jump straight into editing without extra ceremony."],
8484+ ["Block builder", "A master-detail editor keeps structure simple while the public runner gets the design spotlight."],
8585+ ["Response review", "Read each submission in form order and keep the conversational context intact."],
8686+ ].map(([title, description]) => (
8787+ <Card key={title} className="p-6">
8888+ <p className="text-xs font-semibold uppercase tracking-[0.26em] text-[var(--accent)]">Surface</p>
8989+ <h3 className="mt-4 font-display text-3xl">{title}</h3>
9090+ <p className="mt-3 text-sm leading-7 text-[var(--muted)]">{description}</p>
9191+ </Card>
9292+ ))}
9393+ </section>
9494+ </main>
9595+ );
9696+}
···11+## Context
22+33+The repository currently contains only a starter Bun TypeScript app, so this change establishes both the initial product direction and the first real application architecture. The target product is a Typeform-inspired v0 with a polished linear runner, a simple authenticated creator experience, and anonymous public submissions. The main constraints are keeping scope intentionally narrow, shipping a credible end-to-end slice quickly, and preserving a clean foundation for later additions such as branching, richer block types, and theming.
44+55+## Goals / Non-Goals
66+77+**Goals:**
88+- Deliver an authenticated creator app for owning, editing, publishing, and reviewing forms.
99+- Deliver a public anonymous runner that presents one block per screen in a strictly linear flow.
1010+- Support exactly five v0 block types: text, short text, long text, single choice, and multiple choice.
1111+- Keep the builder implementation simple with a left-hand ordered block list and a right-hand settings editor.
1212+- Store responses reliably without coupling submissions to user authentication.
1313+- Establish a production-ready web stack that supports rapid iteration on product UX.
1414+1515+**Non-Goals:**
1616+- Branching logic, conditional steps, or dynamic next-step computation.
1717+- Collaboration, workspaces, or multi-editor ownership.
1818+- Deep analytics, charts, exports beyond basic response review, or integrations.
1919+- Respondent accounts, login-gated submissions, or identity-linked response history.
2020+- Full Typeform feature parity, advanced theming, embeds, uploads, or templates.
2121+2222+## Decisions
2323+2424+### 1. Use Next.js App Router as the application shell
2525+The project will move from the Bun starter entrypoint to a Next.js App Router application. This gives one framework for authenticated creator routes, public runner routes, server-rendered pages, route handlers, and server actions.
2626+2727+**Why this decision:**
2828+- The product needs both an authenticated app surface and public shareable pages.
2929+- App Router supports colocated UI and server logic with good TypeScript ergonomics.
3030+- It keeps deployment and routing simple for an app-shaped product.
3131+3232+**Alternatives considered:**
3333+- Keep Bun-only server code: too low-level for the product UX we need.
3434+- Split frontend and backend: cleaner separation, but unnecessary overhead for v0.
3535+3636+### 2. Use Auth.js only for creator authentication
3737+Authentication will exist only in creator-facing routes such as dashboard, form editing, publishing, and response review. Public form pages and submission endpoints will not require login, and submission data will not use or save creator credentials.
3838+3939+**Why this decision:**
4040+- Matches the product requirement for anonymous public submissions.
4141+- Keeps the respondent experience frictionless.
4242+- Minimizes privacy surface area in the initial release.
4343+4444+**Alternatives considered:**
4545+- Require respondent login: directly conflicts with product goals.
4646+- Support optional respondent auth from the start: adds complexity without v0 value.
4747+4848+### 3. Use Prisma with PostgreSQL for persistence
4949+The data layer will use PostgreSQL with Prisma models for users, forms, blocks, and responses.
5050+5151+**Why this decision:**
5252+- Strong fit for an authenticated multi-user web app.
5353+- Clear schema evolution path as forms grow in complexity.
5454+- Good integration with Next.js and Auth.js.
5555+5656+**Alternatives considered:**
5757+- SQLite: acceptable for prototypes, but weaker for a hosted multi-user product foundation.
5858+- Pure JSON/file storage: too fragile for ownership, publishing, and response querying.
5959+6060+### 4. Model forms as ordered blocks, not only questions
6161+Each form will contain an ordered list of blocks with stable IDs. Block types are `text`, `short_text`, `long_text`, `single_choice`, and `multiple_choice`. Text blocks are part of the runner flow but do not collect answers.
6262+6363+**Why this decision:**
6464+- Matches the conversational runner requirement better than a question-only model.
6565+- Makes content-only screens first-class without special-case hacks.
6666+- Creates a clean path for later screen-like blocks such as welcome or thank-you variants.
6767+6868+**Alternatives considered:**
6969+- Question-only model with separate metadata screens: less expressive and harder to extend.
7070+7171+### 5. Store type-specific block settings in structured JSON on each block
7272+Shared block fields will include identity, order, title, description, and required state. Type-specific details such as placeholders and option lists will live in a JSON config field.
7373+7474+**Why this decision:**
7575+- Keeps the schema simple while block types are still evolving.
7676+- Avoids premature normalization of highly variable block settings.
7777+- Makes it easy to add more block types later without invasive migrations.
7878+7979+**Alternatives considered:**
8080+- Separate columns per block type: rigid and noisy for a narrow v0.
8181+- Separate tables per block type: over-modeled too early.
8282+8383+### 6. Store submitted answers as JSON keyed by block ID
8484+Responses will be anonymous records containing timestamps and an `answersJson` payload keyed by block ID. Question blocks will map to string or string-array values depending on block type; text blocks will have no answer entry.
8585+8686+**Why this decision:**
8787+- Fits the small fixed set of v0 block types.
8888+- Supports response rendering without complex joins or polymorphic answer tables.
8989+- Preserves flexibility while the product shape is still stabilizing.
9090+9191+**Alternatives considered:**
9292+- Fully normalized answer tables: more queryable, but adds complexity before it is needed.
9393+9494+### 7. Builder UX will use a master-detail layout
9595+The builder will use a left panel for ordered block management and a right panel for editing the selected block’s settings. Reordering will use dnd-kit. The builder is optimized for correctness and speed over maximal visual editing.
9696+9797+**Why this decision:**
9898+- Chosen explicitly to keep v0 simpler and more reliable.
9999+- Reduces state-management complexity compared with inline canvas editing.
100100+- Works well with a narrow set of block types.
101101+102102+**Alternatives considered:**
103103+- Canvas-first inline editing: more visually rich, but significantly higher implementation complexity.
104104+105105+### 8. Runner UX will prioritize one-block focus with motion and simple validation
106106+The public form runner will render exactly one block at a time with next/back navigation, a progress indicator, lightweight transitions, and per-step required validation. Progress will count all blocks in the flow, including text blocks, to preserve a predictable step count.
107107+108108+**Why this decision:**
109109+- Produces the intended Typeform-like feel.
110110+- Keeps the flow model straightforward because all steps are linear and visible.
111111+- Avoids confusion caused by hidden non-question screens.
112112+113113+**Alternatives considered:**
114114+- Render only answerable blocks in progress: slightly more compact, but less faithful to the actual flow.
115115+116116+### 9. Allow form editing after responses exist while keeping block IDs stable
117117+Creators may continue editing forms after responses have been collected. Block IDs must remain stable so existing responses can still be mapped back to the block structure they were submitted against.
118118+119119+**Why this decision:**
120120+- Supports a practical creator workflow without requiring full versioning in v0.
121121+- Minimizes data loss risk while keeping implementation scope contained.
122122+123123+**Alternatives considered:**
124124+- Lock forms after first response: too restrictive for real usage.
125125+- Full form versioning: valuable later, but too heavy for v0.
126126+127127+## Risks / Trade-offs
128128+129129+- **Editing forms after responses may create mismatches with historic answers** → Keep stable block IDs and present response data defensively using stored labels/config where needed in later iterations.
130130+- **JSON-based block config and answers trade queryability for speed** → Accept this for v0 and revisit normalization when analytics or filtering requirements appear.
131131+- **Next.js migration replaces the current starter shape completely** → Treat the current repo as scaffolding only and build the new app structure deliberately from scratch.
132132+- **Anonymous public submissions can invite spam or abuse** → Keep the initial submission surface minimal and add rate limiting or bot protection later if real usage demands it.
133133+- **Polished runner interactions can consume disproportionate frontend time** → Limit v0 motion to a few high-value transitions and keep the builder intentionally plain.
134134+135135+## Migration Plan
136136+137137+1. Replace the Bun starter entrypoint with a Next.js application structure.
138138+2. Add dependencies for Tailwind, shadcn/ui, Framer Motion, dnd-kit, Prisma, PostgreSQL, and Auth.js.
139139+3. Introduce Prisma schema and initial migrations for users, forms, blocks, and responses.
140140+4. Build creator authentication and protected app routes.
141141+5. Build the dashboard, builder, publish flow, public runner, and response review pages.
142142+6. Validate end-to-end flows locally with draft and published forms.
143143+144144+Rollback is straightforward at this stage because there is no existing production system or user data to preserve.
145145+146146+## Open Questions
147147+148148+- Which Auth.js provider strategy should be used first for creator sign-in: credentials, OAuth, or both?
149149+- Should v0 include draft autosave in the builder, or are explicit saves sufficient for the first cut?
150150+- Should response metadata include IP/user-agent fields for abuse investigation, or should v0 avoid storing them entirely?
···11+## Why
22+33+This project currently has no product direction beyond a starter Bun app. We want to establish a focused, buildable v0 for a Typeform-inspired product that emphasizes a polished one-screen-at-a-time form experience instead of broad feature parity.
44+55+## What Changes
66+77+- Introduce authenticated creator accounts for owning and managing forms.
88+- Add a form builder for creating linear conversational forms with a simple sidebar-and-editor workflow.
99+- Support five v0 block types: text, short text, long text, single choice, and multiple choice.
1010+- Add publish/unpublish and public shareable form links.
1111+- Add a public form runner that collects anonymous responses without requiring respondent authentication.
1212+- Add creator response views for listing and inspecting submitted responses.
1313+- Establish the initial technical foundation with Next.js, TypeScript, Tailwind CSS, shadcn/ui, Framer Motion, dnd-kit, Prisma, PostgreSQL, and Auth.js.
1414+1515+## Capabilities
1616+1717+### New Capabilities
1818+- `creator-auth`: authenticate creators so they can create, edit, publish, and review only their own forms.
1919+- `conversational-form-builder`: create and manage linear forms with ordered blocks, block editing, and publish/share controls.
2020+- `anonymous-form-runner`: present published forms as one-block-at-a-time conversational flows and accept anonymous public submissions.
2121+- `response-review`: let creators list and inspect responses submitted to forms they own.
2222+2323+### Modified Capabilities
2424+- None.
2525+2626+## Impact
2727+2828+- Replaces the current starter-only direction with a real web product architecture.
2929+- Introduces application routes for creator dashboards, form editing, public form access, and response review.
3030+- Adds authentication, database models, form/block/response persistence, and public submission endpoints.
3131+- Adds new frontend dependencies for app UI, motion, drag-and-drop, ORM, database access, and auth.
···11+## ADDED Requirements
22+33+### Requirement: Published forms are publicly accessible without respondent authentication
44+The system SHALL allow any respondent to open a published form's public route without signing in. Draft or unpublished forms SHALL NOT be available for public response collection.
55+66+#### Scenario: Respondent opens a published form
77+- **WHEN** a respondent navigates to the public route of a published form
88+- **THEN** the system displays the form runner without requiring authentication
99+1010+#### Scenario: Respondent opens an unpublished form
1111+- **WHEN** a respondent navigates to the public route of a draft or unpublished form
1212+- **THEN** the system does not allow public response collection for that form
1313+1414+### Requirement: Runner presents blocks in a linear one-at-a-time flow
1515+The system SHALL present form blocks in saved order and display exactly one block at a time with forward and backward navigation. Text blocks SHALL appear as part of the flow but SHALL NOT collect an answer.
1616+1717+#### Scenario: Respondent moves through the form
1818+- **WHEN** a respondent advances through a published form
1919+- **THEN** the system shows each block one at a time in the form's saved order
2020+2121+#### Scenario: Respondent returns to a previous block
2222+- **WHEN** a respondent navigates backward in the runner
2323+- **THEN** the system returns them to the previous block without breaking the saved in-progress answers for the session
2424+2525+### Requirement: Runner shows progress across the full flow
2626+The system SHALL display progress for the respondent based on the linear block sequence, including non-answerable text blocks.
2727+2828+#### Scenario: Respondent views a text block in the flow
2929+- **WHEN** a respondent is on a text block step
3030+- **THEN** the system includes that step in the visible progress through the form
3131+3232+### Requirement: Required question blocks are validated before advancement
3333+The system SHALL prevent a respondent from advancing past a required question block until a valid answer is provided for that block type.
3434+3535+#### Scenario: Respondent skips a required short text question
3636+- **WHEN** a respondent attempts to continue from a required text question without an answer
3737+- **THEN** the system blocks advancement and indicates that an answer is required
3838+3939+#### Scenario: Respondent skips a required multiple choice question
4040+- **WHEN** a respondent attempts to continue from a required multiple choice block without selecting any options
4141+- **THEN** the system blocks advancement and indicates that an answer is required
4242+4343+### Requirement: Form submission stores anonymous responses
4444+The system SHALL allow a respondent to submit a completed published form anonymously and SHALL store only the form response data needed for review, without using creator login credentials as part of submission identity.
4545+4646+#### Scenario: Respondent submits a completed form
4747+- **WHEN** a respondent completes the final step of a published form and submits it
4848+- **THEN** the system stores an anonymous response for that form and shows a completion state
···11+## ADDED Requirements
22+33+### Requirement: Creator can create and manage form metadata
44+The system SHALL allow an authenticated creator to create a form draft and edit its title and shareable identity needed for public publishing.
55+66+#### Scenario: Creator creates a new form
77+- **WHEN** an authenticated creator creates a form
88+- **THEN** the system creates a new draft form owned by that creator
99+1010+#### Scenario: Creator updates form title
1111+- **WHEN** an authenticated creator edits the title of an owned form
1212+- **THEN** the system saves the updated title for that form
1313+1414+### Requirement: Creator can manage an ordered list of supported blocks
1515+The system SHALL allow an authenticated creator to add, select, edit, reorder, and remove blocks in a form using only the supported v0 block types: text, short text, long text, single choice, and multiple choice.
1616+1717+#### Scenario: Creator adds a block
1818+- **WHEN** an authenticated creator adds a supported block type to an owned form
1919+- **THEN** the system appends the new block to the form with a stable block identifier
2020+2121+#### Scenario: Creator reorders blocks
2222+- **WHEN** an authenticated creator changes the order of blocks in an owned form
2323+- **THEN** the system saves the new block order for the form
2424+2525+#### Scenario: Creator removes a block
2626+- **WHEN** an authenticated creator removes a block from an owned form
2727+- **THEN** the system removes that block from the current form structure
2828+2929+### Requirement: Builder exposes block editing through a master-detail layout
3030+The system SHALL present a builder interface with an ordered block list for navigation and reordering and a separate editor panel for the selected block's settings.
3131+3232+#### Scenario: Creator selects a block
3333+- **WHEN** an authenticated creator selects a block in the block list
3434+- **THEN** the system displays that block's editable settings in the editor panel
3535+3636+### Requirement: Question blocks support required state and type-specific configuration
3737+The system SHALL allow question blocks to be marked as required and SHALL support type-specific configuration for placeholders and choice options. Text blocks SHALL NOT be answerable and SHALL NOT expose a required setting.
3838+3939+#### Scenario: Creator marks a short text question required
4040+- **WHEN** an authenticated creator enables required state for a question block
4141+- **THEN** the system saves that question block as required
4242+4343+#### Scenario: Creator edits single choice options
4444+- **WHEN** an authenticated creator updates the options for a single choice or multiple choice block
4545+- **THEN** the system saves the updated option list for that block
4646+4747+#### Scenario: Creator edits a text block
4848+- **WHEN** an authenticated creator edits a text block
4949+- **THEN** the system allows content updates without exposing answer validation settings
5050+5151+### Requirement: Creator can publish and unpublish forms
5252+The system SHALL allow an authenticated creator to publish or unpublish an owned form and SHALL expose a public shareable route only for published forms.
5353+5454+#### Scenario: Creator publishes a form
5555+- **WHEN** an authenticated creator publishes an owned form
5656+- **THEN** the system marks the form as published and makes its public route available for respondents
5757+5858+#### Scenario: Creator unpublishes a form
5959+- **WHEN** an authenticated creator unpublishes an owned form
6060+- **THEN** the system marks the form as unavailable for new public submissions
···11+## ADDED Requirements
22+33+### Requirement: Creator authentication gates creator features
44+The system SHALL require authentication before a user can access creator-only features, including creating forms, editing owned forms, publishing forms, and reviewing responses.
55+66+#### Scenario: Unauthenticated user opens creator dashboard
77+- **WHEN** an unauthenticated user navigates to a creator-only route
88+- **THEN** the system redirects them to sign in before showing creator functionality
99+1010+#### Scenario: Authenticated creator opens creator dashboard
1111+- **WHEN** an authenticated creator navigates to a creator-only route
1212+- **THEN** the system grants access to creator functionality associated with their account
1313+1414+### Requirement: Creator ownership is enforced for managed forms
1515+The system SHALL allow creators to manage only forms they own and SHALL prevent access to editing, publishing, or response review for forms owned by other creators.
1616+1717+#### Scenario: Creator opens an owned form
1818+- **WHEN** an authenticated creator requests a form they own
1919+- **THEN** the system allows them to edit and manage that form
2020+2121+#### Scenario: Creator opens another creator's form
2222+- **WHEN** an authenticated creator requests a form they do not own
2323+- **THEN** the system denies access to form management and response review for that form
···11+## ADDED Requirements
22+33+### Requirement: Creator can list responses for owned forms
44+The system SHALL allow an authenticated creator to view submitted responses for forms they own and SHALL prevent them from listing responses for forms owned by others.
55+66+#### Scenario: Creator opens responses for an owned form
77+- **WHEN** an authenticated creator opens the responses view for a form they own
88+- **THEN** the system displays the submitted responses for that form
99+1010+#### Scenario: Creator opens responses for another creator's form
1111+- **WHEN** an authenticated creator opens the responses view for a form they do not own
1212+- **THEN** the system denies access to that form's submitted responses
1313+1414+### Requirement: Creator can inspect a single response in form order
1515+The system SHALL allow an authenticated creator to open an individual response and inspect answers mapped to the corresponding form blocks in the saved block order.
1616+1717+#### Scenario: Creator opens one response
1818+- **WHEN** an authenticated creator selects a submitted response for a form they own
1919+- **THEN** the system displays that response's answers in the order of the form's blocks
2020+2121+#### Scenario: Creator inspects response with text blocks in the form
2222+- **WHEN** an authenticated creator views a response for a form that includes text blocks
2323+- **THEN** the system shows only answerable block responses while preserving the form order context for the submission
···11+## 1. Project foundation
22+33+- [x] 1.1 Replace the Bun starter app with a Next.js App Router project structure and baseline app shell
44+- [x] 1.2 Add and configure the core dependencies: Tailwind CSS, shadcn/ui, Framer Motion, dnd-kit, Prisma, PostgreSQL, and Auth.js
55+- [x] 1.3 Set up shared application utilities for database access, auth configuration, and route protection
66+77+## 2. Data model and persistence
88+99+- [x] 2.1 Define Prisma models and migrations for users, forms, form blocks, and anonymous responses
1010+- [x] 2.2 Implement server-side data access for creating, updating, ordering, publishing, and loading owned forms
1111+- [x] 2.3 Implement server-side response persistence for anonymous submissions and creator-side response retrieval
1212+1313+## 3. Creator authentication and ownership
1414+1515+- [x] 3.1 Implement creator sign-in and session handling with Auth.js
1616+- [x] 3.2 Protect creator-only routes and redirect unauthenticated users to sign in
1717+- [x] 3.3 Enforce form ownership checks for editing, publishing, and response review actions
1818+1919+## 4. Creator dashboard and builder
2020+2121+- [x] 4.1 Build the creator dashboard for listing owned forms and creating a new draft form
2222+- [x] 4.2 Build the form builder master-detail layout with a block list and selected-block editor panel
2323+- [x] 4.3 Implement block creation, selection, editing, deletion, and drag-and-drop reordering for the five v0 block types
2424+- [x] 4.4 Implement form metadata editing plus publish/unpublish and share-link controls
2525+2626+## 5. Public conversational runner
2727+2828+- [x] 5.1 Build the public published-form route and reject draft or unpublished forms from public response collection
2929+- [x] 5.2 Implement the one-block-at-a-time runner with next/back navigation, progress display, and motion transitions
3030+- [x] 5.3 Implement block-specific inputs and required validation for short text, long text, single choice, and multiple choice blocks
3131+- [x] 5.4 Implement anonymous submission and completion state for the final runner step
3232+3333+## 6. Response review
3434+3535+- [x] 6.1 Build the creator responses list view for an owned form
3636+- [x] 6.2 Build the single-response detail view with answers shown in form order
3737+- [x] 6.3 Ensure text blocks are handled correctly in response presentation while preserving flow context
3838+3939+## 7. Integration polish
4040+4141+- [x] 7.1 Connect end-to-end flows across dashboard, builder, publishing, public runner, and response review
4242+- [x] 7.2 Add basic empty, loading, and error states for key creator and respondent surfaces
4343+- [x] 7.3 Validate the v0 experience manually for anonymous submissions, ownership enforcement, and linear runner behavior
+20
openspec/config.yaml
···11+schema: spec-driven
22+33+# Project context (optional)
44+# This is shown to AI when creating artifacts.
55+# Add your tech stack, conventions, style guides, domain knowledge, etc.
66+# Example:
77+# context: |
88+# Tech stack: TypeScript, React, Node.js
99+# We use conventional commits
1010+# Domain: e-commerce platform
1111+1212+# Per-artifact rules (optional)
1313+# Add custom rules for specific artifacts.
1414+# Example:
1515+# rules:
1616+# proposal:
1717+# - Keep proposals under 500 words
1818+# - Always include a "Non-goals" section
1919+# tasks:
2020+# - Break tasks into chunks of max 2 hours
+48
openspec/specs/anonymous-form-runner/spec.md
···11+## ADDED Requirements
22+33+### Requirement: Published forms are publicly accessible without respondent authentication
44+The system SHALL allow any respondent to open a published form's public route without signing in. Draft or unpublished forms SHALL NOT be available for public response collection.
55+66+#### Scenario: Respondent opens a published form
77+- **WHEN** a respondent navigates to the public route of a published form
88+- **THEN** the system displays the form runner without requiring authentication
99+1010+#### Scenario: Respondent opens an unpublished form
1111+- **WHEN** a respondent navigates to the public route of a draft or unpublished form
1212+- **THEN** the system does not allow public response collection for that form
1313+1414+### Requirement: Runner presents blocks in a linear one-at-a-time flow
1515+The system SHALL present form blocks in saved order and display exactly one block at a time with forward and backward navigation. Text blocks SHALL appear as part of the flow but SHALL NOT collect an answer.
1616+1717+#### Scenario: Respondent moves through the form
1818+- **WHEN** a respondent advances through a published form
1919+- **THEN** the system shows each block one at a time in the form's saved order
2020+2121+#### Scenario: Respondent returns to a previous block
2222+- **WHEN** a respondent navigates backward in the runner
2323+- **THEN** the system returns them to the previous block without breaking the saved in-progress answers for the session
2424+2525+### Requirement: Runner shows progress across the full flow
2626+The system SHALL display progress for the respondent based on the linear block sequence, including non-answerable text blocks.
2727+2828+#### Scenario: Respondent views a text block in the flow
2929+- **WHEN** a respondent is on a text block step
3030+- **THEN** the system includes that step in the visible progress through the form
3131+3232+### Requirement: Required question blocks are validated before advancement
3333+The system SHALL prevent a respondent from advancing past a required question block until a valid answer is provided for that block type.
3434+3535+#### Scenario: Respondent skips a required short text question
3636+- **WHEN** a respondent attempts to continue from a required text question without an answer
3737+- **THEN** the system blocks advancement and indicates that an answer is required
3838+3939+#### Scenario: Respondent skips a required multiple choice question
4040+- **WHEN** a respondent attempts to continue from a required multiple choice block without selecting any options
4141+- **THEN** the system blocks advancement and indicates that an answer is required
4242+4343+### Requirement: Form submission stores anonymous responses
4444+The system SHALL allow a respondent to submit a completed published form anonymously and SHALL store only the form response data needed for review, without using creator login credentials as part of submission identity.
4545+4646+#### Scenario: Respondent submits a completed form
4747+- **WHEN** a respondent completes the final step of a published form and submits it
4848+- **THEN** the system stores an anonymous response for that form and shows a completion state
···11+## ADDED Requirements
22+33+### Requirement: Creator can create and manage form metadata
44+The system SHALL allow an authenticated creator to create a form draft and edit its title and shareable identity needed for public publishing.
55+66+#### Scenario: Creator creates a new form
77+- **WHEN** an authenticated creator creates a form
88+- **THEN** the system creates a new draft form owned by that creator
99+1010+#### Scenario: Creator updates form title
1111+- **WHEN** an authenticated creator edits the title of an owned form
1212+- **THEN** the system saves the updated title for that form
1313+1414+### Requirement: Creator can manage an ordered list of supported blocks
1515+The system SHALL allow an authenticated creator to add, select, edit, reorder, and remove blocks in a form using only the supported v0 block types: text, short text, long text, single choice, and multiple choice.
1616+1717+#### Scenario: Creator adds a block
1818+- **WHEN** an authenticated creator adds a supported block type to an owned form
1919+- **THEN** the system appends the new block to the form with a stable block identifier
2020+2121+#### Scenario: Creator reorders blocks
2222+- **WHEN** an authenticated creator changes the order of blocks in an owned form
2323+- **THEN** the system saves the new block order for the form
2424+2525+#### Scenario: Creator removes a block
2626+- **WHEN** an authenticated creator removes a block from an owned form
2727+- **THEN** the system removes that block from the current form structure
2828+2929+### Requirement: Builder exposes block editing through a master-detail layout
3030+The system SHALL present a builder interface with an ordered block list for navigation and reordering and a separate editor panel for the selected block's settings.
3131+3232+#### Scenario: Creator selects a block
3333+- **WHEN** an authenticated creator selects a block in the block list
3434+- **THEN** the system displays that block's editable settings in the editor panel
3535+3636+### Requirement: Question blocks support required state and type-specific configuration
3737+The system SHALL allow question blocks to be marked as required and SHALL support type-specific configuration for placeholders and choice options. Text blocks SHALL NOT be answerable and SHALL NOT expose a required setting.
3838+3939+#### Scenario: Creator marks a short text question required
4040+- **WHEN** an authenticated creator enables required state for a question block
4141+- **THEN** the system saves that question block as required
4242+4343+#### Scenario: Creator edits single choice options
4444+- **WHEN** an authenticated creator updates the options for a single choice or multiple choice block
4545+- **THEN** the system saves the updated option list for that block
4646+4747+#### Scenario: Creator edits a text block
4848+- **WHEN** an authenticated creator edits a text block
4949+- **THEN** the system allows content updates without exposing answer validation settings
5050+5151+### Requirement: Creator can publish and unpublish forms
5252+The system SHALL allow an authenticated creator to publish or unpublish an owned form and SHALL expose a public shareable route only for published forms.
5353+5454+#### Scenario: Creator publishes a form
5555+- **WHEN** an authenticated creator publishes an owned form
5656+- **THEN** the system marks the form as published and makes its public route available for respondents
5757+5858+#### Scenario: Creator unpublishes a form
5959+- **WHEN** an authenticated creator unpublishes an owned form
6060+- **THEN** the system marks the form as unavailable for new public submissions
+23
openspec/specs/creator-auth/spec.md
···11+## ADDED Requirements
22+33+### Requirement: Creator authentication gates creator features
44+The system SHALL require authentication before a user can access creator-only features, including creating forms, editing owned forms, publishing forms, and reviewing responses.
55+66+#### Scenario: Unauthenticated user opens creator dashboard
77+- **WHEN** an unauthenticated user navigates to a creator-only route
88+- **THEN** the system redirects them to sign in before showing creator functionality
99+1010+#### Scenario: Authenticated creator opens creator dashboard
1111+- **WHEN** an authenticated creator navigates to a creator-only route
1212+- **THEN** the system grants access to creator functionality associated with their account
1313+1414+### Requirement: Creator ownership is enforced for managed forms
1515+The system SHALL allow creators to manage only forms they own and SHALL prevent access to editing, publishing, or response review for forms owned by other creators.
1616+1717+#### Scenario: Creator opens an owned form
1818+- **WHEN** an authenticated creator requests a form they own
1919+- **THEN** the system allows them to edit and manage that form
2020+2121+#### Scenario: Creator opens another creator's form
2222+- **WHEN** an authenticated creator requests a form they do not own
2323+- **THEN** the system denies access to form management and response review for that form
+23
openspec/specs/response-review/spec.md
···11+## ADDED Requirements
22+33+### Requirement: Creator can list responses for owned forms
44+The system SHALL allow an authenticated creator to view submitted responses for forms they own and SHALL prevent them from listing responses for forms owned by others.
55+66+#### Scenario: Creator opens responses for an owned form
77+- **WHEN** an authenticated creator opens the responses view for a form they own
88+- **THEN** the system displays the submitted responses for that form
99+1010+#### Scenario: Creator opens responses for another creator's form
1111+- **WHEN** an authenticated creator opens the responses view for a form they do not own
1212+- **THEN** the system denies access to that form's submitted responses
1313+1414+### Requirement: Creator can inspect a single response in form order
1515+The system SHALL allow an authenticated creator to open an individual response and inspect answers mapped to the corresponding form blocks in the saved block order.
1616+1717+#### Scenario: Creator opens one response
1818+- **WHEN** an authenticated creator selects a submitted response for a form they own
1919+- **THEN** the system displays that response's answers in the order of the form's blocks
2020+2121+#### Scenario: Creator inspects response with text blocks in the form
2222+- **WHEN** an authenticated creator views a response for a form that includes text blocks
2323+- **THEN** the system shows only answerable block responses while preserving the form order context for the submission