···11+## Context
22+33+The public runner currently ends with a fixed completion state embedded in `components/public-form-runner.tsx`. Creators cannot tailor that final screen to explain what happens next or direct respondents to another destination.
44+55+This change touches both creator-facing and respondent-facing flows. Form metadata already lives on the `Form` record and is edited through the builder settings panel, so the completion state should follow the same pattern rather than introducing a separate entity.
66+77+## Goals / Non-Goals
88+99+**Goals:**
1010+- Let creators configure the completion text shown after a successful submission.
1111+- Let creators optionally provide a follow-up link that appears on the completion state.
1212+- Preserve a safe default completion state for older forms and forms with no custom content.
1313+- Keep the implementation aligned with the existing form metadata update flow.
1414+1515+**Non-Goals:**
1616+- Rich text editing for completion content.
1717+- Per-response or conditional completion messages.
1818+- Multiple follow-up links or button styling customization.
1919+- Tracking follow-up link clicks.
2020+2121+## Decisions
2222+2323+### Store completion content directly on the `Form` model
2424+Add dedicated form-level fields for completion content instead of a JSON blob or separate table. This keeps the feature easy to validate, serialize, and expose through existing builder/public form payloads.
2525+2626+Proposed fields:
2727+- `completionTitle`: short heading shown after submission
2828+- `completionMessage`: supporting copy shown below the heading
2929+- `completionLinkLabel`: optional CTA label
3030+- `completionLinkUrl`: optional CTA URL
3131+3232+**Why this approach:**
3333+- Fits the existing form metadata model.
3434+- Avoids schema ambiguity and ad hoc JSON validation.
3535+- Makes default values and future migrations straightforward.
3636+3737+**Alternatives considered:**
3838+- Store completion settings in a JSON column on `Form`: more flexible, but weaker typing and more validation complexity.
3939+- Hardcode only a single customizable message string: simpler, but too limiting for the requested “next action + link” use case.
4040+4141+### Extend existing metadata update validation and API
4242+The builder already updates title, description, and slug via the form metadata flow. Completion fields should be added to the same schema and persistence path.
4343+4444+**Why this approach:**
4545+- One save action for all form-level settings.
4646+- No new endpoint or settings surface is required.
4747+- Keeps builder behavior predictable for creators.
4848+4949+**Alternatives considered:**
5050+- Separate completion-settings endpoint: unnecessary complexity for a small metadata extension.
5151+5252+### Treat the follow-up link as optional and only render it when complete
5353+The runner should show the CTA only when both label and URL are present and valid enough to save. Partial CTA input should not render a broken link.
5454+5555+**Why this approach:**
5656+- Prevents incomplete UI states.
5757+- Matches the user request without forcing every form to include a CTA.
5858+5959+**Alternatives considered:**
6060+- Render when only a URL exists: creates unclear CTA text.
6161+- Require a link for all forms: too restrictive.
6262+6363+### Keep fallback completion copy for existing forms
6464+Older forms should continue to show a coherent completion state even before creators edit the new settings.
6565+6666+**Why this approach:**
6767+- Avoids a migration that would require backfilling handcrafted content for every form.
6868+- Preserves the current experience while allowing progressive customization.
6969+7070+**Alternatives considered:**
7171+- Make new fields required with no defaults: risks blank or broken completion screens for existing forms.
7272+7373+## Risks / Trade-offs
7474+7575+- **More fields on `Form`** → Mitigation: use a small, explicit set of fields rather than a generalized content system.
7676+- **Invalid or unsafe link input** → Mitigation: validate URLs on save and render only complete CTA data.
7777+- **Long completion copy can overflow the current finish screen design** → Mitigation: keep inputs plain text, provide reasonable validation limits, and reuse the responsive card layout already used by the completion state.
7878+- **Migration introduces schema drift if not applied everywhere** → Mitigation: add a Prisma migration and ensure builder/public serializers read the new fields.
7979+8080+## Migration Plan
8181+8282+1. Add new completion fields to the Prisma `Form` model.
8383+2. Generate and apply a migration with safe defaults or nullable link fields.
8484+3. Extend form metadata validation, serialization, and update logic.
8585+4. Add builder settings inputs for completion title, completion message, and optional link label/URL.
8686+5. Update the public runner completion state to use saved form data with fallback defaults.
8787+6. Verify existing forms still submit successfully and display a valid completion state.
8888+8989+## Open Questions
9090+9191+- Should the CTA open in a new tab by default for external URLs?
9292+- Do we want URL validation to allow relative links, or only absolute `http/https` URLs?
9393+- Should the completion title/message have stricter length limits for better visual consistency?
···11+## Why
22+33+Creators currently get a fixed completion state after respondents submit a form. That makes it hard to guide people toward a next step such as visiting a resource, booking time, joining a waitlist, or reading follow-up information.
44+55+## What Changes
66+77+- Allow creators to configure the text shown after a successful form submission.
88+- Allow creators to optionally add a follow-up link in the submission completion state.
99+- Replace the current fixed completion copy in the public runner with the form-specific completion content.
1010+- Keep a sensible default completion message for forms that have not been customized.
1111+1212+## Capabilities
1313+1414+### New Capabilities
1515+- None.
1616+1717+### Modified Capabilities
1818+- `conversational-form-builder`: creators can edit post-submission completion content for an owned form.
1919+- `anonymous-form-runner`: respondents see the form's configured completion content and optional follow-up link after submission.
2020+2121+## Impact
2222+2323+- Affected specs: `conversational-form-builder`, `anonymous-form-runner`
2424+- Affected code: form metadata model, builder settings UI, public runner completion state, form serialization and persistence
2525+- Affected APIs: form metadata update flow and any form payloads that expose completion content to the runner
···11+## MODIFIED Requirements
22+33+### Requirement: Form submission stores anonymous responses
44+The system SHALL allow a respondent to submit a completed published form anonymously, SHALL store only the form response data needed for review, without using creator login credentials as part of submission identity, and SHALL show a completion state based on the form's configured completion content.
55+66+#### Scenario: Respondent submits a completed form
77+- **WHEN** a respondent completes the final step of a published form and submits it
88+- **THEN** the system stores an anonymous response for that form and shows the form's completion state
99+1010+#### Scenario: Form has custom completion content
1111+- **WHEN** a respondent submits a published form whose creator configured custom completion text
1212+- **THEN** the system shows the saved completion heading and message after submission
1313+1414+#### Scenario: Form has a configured follow-up link
1515+- **WHEN** a respondent submits a published form whose creator configured a follow-up link label and URL
1616+- **THEN** the system shows the follow-up link in the completion state after submission
1717+1818+#### Scenario: Form has no custom completion content
1919+- **WHEN** a respondent submits a published form without customized completion settings
2020+- **THEN** the system shows the default completion content after submission
···11+## ADDED Requirements
22+33+### Requirement: Creator can configure post-submission completion content
44+The system SHALL allow an authenticated creator to edit the completion content for an owned form, including a completion heading, supporting message, and an optional follow-up link label and URL.
55+66+#### Scenario: Creator saves custom completion text
77+- **WHEN** an authenticated creator updates the completion heading or supporting message for an owned form
88+- **THEN** the system saves the updated completion content as part of that form's settings
99+1010+#### Scenario: Creator saves a follow-up link
1111+- **WHEN** an authenticated creator provides both a follow-up link label and URL for an owned form
1212+- **THEN** the system saves the follow-up link so it can be shown after submission
1313+1414+#### Scenario: Creator leaves follow-up link incomplete
1515+- **WHEN** an authenticated creator leaves the follow-up link label or URL empty
1616+- **THEN** the system does not save or expose a partial follow-up link for the form
···11+## 1. Data model and validation
22+33+- [x] 1.1 Add completion title, message, link label, and link URL fields to the `Form` model and create a Prisma migration
44+- [x] 1.2 Extend form metadata validation to accept completion content and reject incomplete or invalid follow-up link data
55+- [x] 1.3 Update form serialization and update logic so builder and public form payloads include the new completion settings
66+77+## 2. Builder settings support
88+99+- [x] 2.1 Add completion content inputs to the builder form settings panel
1010+- [x] 2.2 Populate the new builder inputs from existing form metadata and persist them through the existing save settings action
1111+- [x] 2.3 Verify builder behavior for default values, empty CTA fields, and validation feedback
1212+1313+## 3. Public runner completion state
1414+1515+- [x] 3.1 Update the public form runner to render saved completion title and message after successful submission
1616+- [x] 3.2 Render the optional follow-up link only when both CTA label and URL are available
1717+- [x] 3.3 Preserve fallback completion copy for forms without customized completion settings
1818+1919+## 4. Verification
2020+2121+- [x] 4.1 Test that existing forms still submit successfully and show a valid completion state
2222+- [x] 4.2 Run build and relevant checks to confirm the new metadata flow works end-to-end
+14-2
openspec/specs/anonymous-form-runner/spec.md
···4141- **THEN** the system blocks advancement and indicates that an answer is required
42424343### 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.
4444+The system SHALL allow a respondent to submit a completed published form anonymously, SHALL store only the form response data needed for review, without using creator login credentials as part of submission identity, and SHALL show a completion state based on the form's configured completion content.
45454646#### 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
4848+- **THEN** the system stores an anonymous response for that form and shows the form's completion state
4949+5050+#### Scenario: Form has custom completion content
5151+- **WHEN** a respondent submits a published form whose creator configured custom completion text
5252+- **THEN** the system shows the saved completion heading and message after submission
5353+5454+#### Scenario: Form has a configured follow-up link
5555+- **WHEN** a respondent submits a published form whose creator configured a follow-up link label and URL
5656+- **THEN** the system shows the follow-up link in the completion state after submission
5757+5858+#### Scenario: Form has no custom completion content
5959+- **WHEN** a respondent submits a published form without customized completion settings
6060+- **THEN** the system shows the default completion content after submission
···6969#### Scenario: Creator reads helper copy in the builder
7070- **WHEN** an authenticated creator views builder headings, descriptions, or empty states
7171- **THEN** the system uses short task-oriented copy that explains the current editing context without persuasive or ornamental language
7272+7373+### Requirement: Creator can configure post-submission completion content
7474+The system SHALL allow an authenticated creator to edit the completion content for an owned form, including a completion heading, supporting message, and an optional follow-up link label and URL.
7575+7676+#### Scenario: Creator saves custom completion text
7777+- **WHEN** an authenticated creator updates the completion heading or supporting message for an owned form
7878+- **THEN** the system saves the updated completion content as part of that form's settings
7979+8080+#### Scenario: Creator saves a follow-up link
8181+- **WHEN** an authenticated creator provides both a follow-up link label and URL for an owned form
8282+- **THEN** the system saves the follow-up link so it can be shown after submission
8383+8484+#### Scenario: Creator leaves follow-up link incomplete
8585+- **WHEN** an authenticated creator leaves the follow-up link label or URL empty
8686+- **THEN** the system does not save or expose a partial follow-up link for the form
···11+-- AlterTable
22+ALTER TABLE "Form" ADD COLUMN "completionLinkLabel" TEXT,
33+ADD COLUMN "completionLinkUrl" TEXT,
44+ADD COLUMN "completionMessage" TEXT NOT NULL DEFAULT 'Your response was submitted anonymously. The creator can review your answers, but they are not linked to a login or account.',
55+ADD COLUMN "completionTitle" TEXT NOT NULL DEFAULT 'Thanks for taking the time.';
+15-11
prisma/schema.prisma
···7272}
73737474model Form {
7575- id String @id @default(cuid())
7676- userId String
7777- title String @default("Untitled form")
7878- description String @default("")
7979- slug String @unique
8080- status FormStatus @default(DRAFT)
8181- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
8282- blocks FormBlock[]
8383- responses Response[]
8484- createdAt DateTime @default(now())
8585- updatedAt DateTime @updatedAt
7575+ id String @id @default(cuid())
7676+ userId String
7777+ title String @default("Untitled form")
7878+ description String @default("")
7979+ completionTitle String @default("Thanks for taking the time.")
8080+ completionMessage String @default("Your response was submitted anonymously. The creator can review your answers, but they are not linked to a login or account.")
8181+ completionLinkLabel String?
8282+ completionLinkUrl String?
8383+ slug String @unique
8484+ status FormStatus @default(DRAFT)
8585+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
8686+ blocks FormBlock[]
8787+ responses Response[]
8888+ createdAt DateTime @default(now())
8989+ updatedAt DateTime @updatedAt
86908791 @@index([userId, updatedAt(sort: Desc)])
8892}