Files
Sauci/docs/question-types.md

3.3 KiB

Question interaction types

This is the maintained contract for the question interactions delivered through the daily question flow. It is separate from the couples quiz and dares loop, which have their own content and completion models.

Supported types

Type User interaction response_data and config Match semantics
swipe Choose yes or no, or skip. No response_data; config is unused. A no creates no match. The API also retains maybe matching for stored or replayed answers, producing yes_maybe or maybe_maybe; the current mobile card does not offer maybe.
text_answer Write an answer and send it, decline with no, or skip. response_data: { type: 'text_answer', text }; config is unused. Both partners must answer without a no. The match type is both_answered, with both payloads in response_summary.
audio Record and send an audio answer, or skip. response_data: { type: 'audio', media_path, duration_seconds }; optional config.max_duration_seconds limits recording and defaults to 60 seconds in the admin UI. Both partners must answer without a no. The match type is both_answered, with both payloads in response_summary.
photo Take or select and send a photo answer, or skip. response_data: { type: 'photo', media_path }; config is unused. Both partners must answer without a no. The match type is both_answered, with both payloads in response_summary.
who_likely Choose which partner is more likely. The current mobile flow submits this as yes. response_data: { type: 'who_likely', chosen_user_id }; config is unused. Once both partners respond, the match type is both_answered; the stored answer value does not gate that type's match calculation. Both choices are in response_summary.

Persistence and implementation ownership

questions.question_type defaults to swipe; the database check constraint and the canonical shared QuestionType union must contain the same values. questions.config is JSON configuration for a type. responses.response_data stores an individual non-swipe payload. matches.response_summary is a JSON object keyed by responder user ID and is populated for both_answered matches.

The canonical list is QuestionType in packages/shared/src/types/index.ts. The database constraint is in apps/api/drizzle/0003_answers_matches.sql. Match calculation is in apps/api/src/domains/answers/types.ts, the mobile renderer is apps/mobile/src/features/swipe/components/SwipeQuestionCard.tsx, and admin authoring options are in apps/admin/src/pages/content/QuestionsPage.tsx.

Change rule

When adding, removing, or changing a question type, its payload, configuration, or matching semantics, update this document in the same change. Update the shared type, database constraint, API, mobile, and admin consumers as required. npm run lint:harness checks the documented type list against the canonical shared union so an unreviewed list change fails routine verification.