| name | questions-answers |
| description | Q&A system in Raamattu Nyt — full pipeline from search-query classification through question upsert, AI answer generation, community answers, voting, admin moderation, anchor questions, AND info-palaset (info blocks). Use for Q&A search results, question classification logic, community answer forms/moderation, AI answer generation/prompts, admin Q&A pages, anchor/similar questions, votes, Q&A bugs, answer types/display, QuestionPage/QuestionsSearchSection/AdminQuestionsPage, and for **info-palaset / info blocks**: reusable content blocks attached to questions/topics/spiritual paths, rendered in page-tila (InfoTextCard) and cinema-tila (InfoView/InfoFlow/InfoCinema), the admin info-block library (AdminInfoBlocksPage, InfoBlockEditor, /ohjaamo/info-blocks), attach dialogs, info_blocks/question_info_blocks/topic_info_blocks/spiritual_path_info_blocks tables, and "Kysymys > info-pala" tasks. |
Questions & Answers System
Full-stack Q&A pipeline: search → classify → upsert → answer (AI/community/admin) → moderate → publish.
Architecture Overview
User search query
→ questionClassifier.ts (client-side)
→ upsert-question (edge fn: normalize, hash, classify, deduplicate)
→ QuestionsSearchSection renders:
├── Answers grouped by type (bullet → editorial → community → AI)
├── Info-palaset (info blocks attached to the question — see below)
├── CommunityAnswerForm (auth-gated)
├── QuestionConsentBlock (AI generation / human request)
├── AnchorQuestionsSection (topic-linked curated Q&A)
└── SimilarQuestionsSection (trigram similarity)
Key Files
Edge Functions
| Function | Path | Purpose |
|---|
upsert-question | supabase/functions/upsert-question/ | Normalize, classify, upsert, find similar |
generate-ai-answer | supabase/functions/generate-ai-answer/ | AI answer via Claude (paid, quota-checked) |
submit-community-answer | supabase/functions/submit-community-answer/ | User-submitted answer (free, needs admin approval) |
vote | supabase/functions/vote/ | +1/-1 voting on questions/answers |
Hooks (apps/raamattu-nyt/src/hooks/)
| Hook | File | Purpose |
|---|
useUpsertQuestion | useQuestions.ts | Mutation: upsert question via edge fn |
useGenerateAiAnswer | useQuestions.ts | Mutation: generate AI answer (quota-checked) |
useSubmitCommunityAnswer | useQuestions.ts | Mutation: submit community answer |
useVote | useQuestions.ts | Mutation: vote on question/answer |
usePublishedQuestion | useQuestions.ts | Query: single published question by slug |
useQuestionAnswers | useQuestions.ts | Query: published answers for question |
useAdminQuestions | useQuestions.ts | Query: all questions with answer stats |
useAdminAnswers | useQuestions.ts | Query: all answers (including unpublished) |
useAnchorQuestions | useAnchorQuestions.ts | Query: anchor Q&A grouped by topic |
Components (apps/raamattu-nyt/src/components/search/)
| Component | Purpose |
|---|
QuestionsSearchSection | Main Q&A display in search results |
QuestionConsentBlock | AI answer / human request consent |
CommunityAnswerForm | User answer submission form |
SimilarQuestionsSection | Trigram-similar questions |
AnchorQuestionsSection | Topic-linked curated Q&A |
Pages
| Page | Route | Purpose |
|---|
QuestionPage.tsx | /kysymys/:slug | Public single question view + admin tools |
AdminQuestionsPage.tsx | /ohjaamo/questions | Full admin Q&A dashboard |
PremiumQuestionsPage.tsx | /premium/questions | Public questions browsing |
Core Libraries
| File | Purpose |
|---|
src/lib/questionClassifier.ts | Client-side question detection (Finnish) |
Database Schema (bible_schema)
For full schema details: See references/schema.md
Tables
- questions — Normalized questions with classification, status, voting
- answers — Answers with author_type, rich content, key_verses, topics, strongs_refs
- votes — User votes (+1/-1) on questions/answers (unique per user)
- topic_anchor_questions — Links questions as anchor Q&A for topics
Answer Author Types
| Type | Created by | Published by default? |
|---|
bullet | Admin | Yes |
admin | Admin | Yes |
system | Import/seed | Yes |
ai | Edge function | No (needs admin review) |
community | Authenticated user | No (needs admin approval) |
Question Status Flow
draft → needs_review → approved → published
└→ rejected
RLS Summary
- Anon/Auth: Read published questions + published non-hidden answers
- Auth: Read own questions + own community answers, insert votes, submit community answers
- Admin: Full CRUD on all questions, answers, votes
Common Patterns
Add new answer type
- Add CHECK constraint value in migration
- Update
AnswerData interface in QuestionsSearchSection.tsx
- Update
Answer type in useQuestions.ts
- Add rendering logic in
renderAnswerCard
- Update admin management in
AdminQuestionsPage.tsx
Add new question classification
- Update classifier patterns in
questionClassifier.ts
- Mirror logic in
upsert-question edge function
- Update CHECK constraint if new DB value needed
- Add UI handling in
QuestionsSearchSection
Modify AI answer generation
- Edit prompt template via
ai-prompt-manager skill
- Edge function:
generate-ai-answer/index.ts
- Output validation: excerpt, key_verses, topics, strongs_refs, related_questions
- Model/vendor configured via
ai_feature_bindings table
Add feature to community answers
- Edge function:
submit-community-answer/index.ts
- Hook:
useSubmitCommunityAnswer in useQuestions.ts
- Form:
CommunityAnswerForm.tsx (search) or inline in QuestionPage.tsx
- Admin tab: "Yhteisövastaukset" in
AdminQuestionsPage.tsx
Info-palaset (info blocks)
Reusable content blocks (bible_schema.info_blocks) attached to questions, topics, and
spiritual paths. One of two answer mechanisms for a question (alongside community
answers). Admin-curated — no AI generation and no classifier (unlike questions).
[!important] Key invariant
An info-pala is rendered by TWO components: InfoTextCard (page-tila) and InfoView
(cinema-tila). Edit whichever the request targets and keep both in sync.
Tables (bible_schema)
- info_blocks —
slug, title_fi/en, body_md/en, body_html/en, excerpt/en,
is_published, is_handled, is_hidden, is_core (gates attachability), author_type
(admin/community/system), icon, bg_color, image_url, key_verses (display-only),
key_prayers, action_links (route/url/grand_plan; legacy action_grand_plan_id).
- question_info_blocks / topic_info_blocks / spiritual_path_info_blocks — junctions
(
sort_order; paths also carry binding_id).
RPCs
get_info_blocks_by_slugs(p_slugs) — public, published blocks by slug
get_attachable_info_blocks() — admin-only (SECURITY DEFINER), core blocks + attach counts
get_spiritual_path_info_block_slugs[_admin]() — path bindings
Key files
| Concern | File |
|---|
| CRUD hook | hooks/useInfoBlocks.ts |
| Fetch by slug | hooks/info-blocks/useInfoBlocksBySlugs.ts |
| Question-attached | hooks/questions/useQuestionInfoBlocks.ts (+ admin variant) |
| Topic-attached | hooks/topics/useTopicInfoBlocks.ts |
| Path bindings | hooks/info-blocks/useSpiritualPathInfoBlock{Bindings,Mutations}.ts |
| Page render (1 block) | pages/question-detail/InfoTextCard.tsx (wrapper QuestionInfoSection.tsx) |
| Cinema render | components/cinema/InfoView.tsx (1) · InfoFlow.tsx (snap-scroll N) · InfoCinema.tsx (shell) |
| Attach dialog | pages/question-detail/AddInfoBlockDialog.tsx · components/info-blocks/InfoBlockAttachDialog.tsx |
| Action links | components/info-blocks/InfoBlockActions.tsx |
| Path render | components/spiritual-path/SpiritualPathInfoBlock.tsx |
| Admin | pages/AdminInfoBlocksPage.tsx (/ohjaamo/info-blocks) · pages/admin-info-blocks/InfoBlockEditor.tsx |
Q&A cinema integration
QuestionCinemaApp renders published community answers (via answerToInfoBlock()) +
attached info blocks through the same InfoFlow/InfoView — answers first, then info blocks.
Common patterns
- Create/edit an info-pala →
InfoBlockEditor (fill both FI + EN; is_core gates attachability).
- Attach to question/topic/path → attach dialog → junction row with
sort_order.
- Change appearance → page =
InfoTextCard, cinema = InfoView — edit both.
- Info blocks are read via RPC + typed
bibleSchemaRpc (not direct .from("info_blocks")) → mock those in tests.
Full info-block schema + RLS: See references/schema.md.
Shared UI Components
- BibleReferencePickerPopover — Verse picker popover (used across 6 files)
- SafeTextarea — Input with XSS protection, markup detection
- RichContentRenderer — Renders body_html from rich editor
- VerseContentCard — Displays verse reference with content
- FeedbackThumbs / FeedbackText — Answer feedback (AI answers)
References