# kasunnmsu/meat-app architecture

> Architecture diagram of the GitHub repository kasunnmsu/meat-app, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/kasunnmsu/meat-app
- Repository: https://github.com/kasunnmsu/meat-app

## Overview

Beef Choice Study App collects responses for a three-session beef-choice experiment, ending with demographics and a combined survey record. Participants start a full survey or an individual session, rank options, read seal descriptions in Session 2, and rank priced options in Session 3. API routes validate and save submissions for session-wise and combined exports; the README also documents database persistence and fallback data sources. Edges use README statements or source-index references; unsampled implementation details are not assumed.

Main entry points: [`app/session-3/page.tsx`](https://github.com/kasunnmsu/meat-app/blob/main/app/session-3/page.tsx) (Priced ranking), [`lib/saveWithRetry.ts`](https://github.com/kasunnmsu/meat-app/blob/main/lib/saveWithRetry.ts) (Save retry queue), [`app/page.tsx`](https://github.com/kasunnmsu/meat-app/blob/main/app/page.tsx) (Survey entry), [`app/session-1/page.tsx`](https://github.com/kasunnmsu/meat-app/blob/main/app/session-1/page.tsx) (Session 1 ranking)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_participant["Participant entry"]
  node_start["Survey entry<br/>[page.tsx]"]
  node_consent["Consent<br/>[page.tsx]"]
end

subgraph group_study["Study tasks"]
  node_session1["Session 1 ranking<br/>[page.tsx]"]
  node_sealreading["Seal descriptions<br/>[page.tsx]"]
  node_session2["Session 2 ranking<br/>[page.tsx]"]
  node_session3["Priced ranking<br/>[page.tsx]"]
  node_demographics["Demographics"]
end

subgraph group_interface["Shared interface"]
  node_ranking["Ranking interaction<br/>[RankingScreen.tsx]"]
  node_localization["Language and location<br/>[i18n.tsx]"]
end

subgraph group_persistence["Submission and results"]
  node_retry["Save retry queue<br/>[saveWithRetry.ts]"]
  node_sessionapi["Session save routes<br/>[route.ts]"]
  node_fullapi["Full survey route<br/>[route.ts]"]
  node_topseals["Top seals lookup<br/>[route.ts]"]
  node_validation["Payload validation"]
  node_export["Excel and JSON exports<br/>[dataExports.ts]"]
  node_workbooks["Workbook rows<br/>[resultWorkbooks.ts]"]
  node_database[("Study database<br/>[studyDatabase.ts]")]
  node_results[("Local result files<br/>[dataPaths.ts]")]
end

node_participant(("Participant"))

node_participant -->|"starts survey"| node_start
node_start -.->|"continues to"| node_consent
node_start -->|"starts session"| node_session1
node_start -->|"starts session"| node_sealreading
node_start -->|"starts session"| node_session3
node_sealreading -->|"unlocks ranking"| node_session2
node_session1 -->|"uses ranking"| node_ranking
node_sealreading -->|"uses ranking"| node_ranking
node_session3 -->|"uses ranking"| node_ranking
node_session1 -.->|"collects at end"| node_demographics
node_session2 -.->|"collects at end"| node_demographics
node_session3 -->|"collects final"| node_demographics
node_session3 -->|"requests top seals"| node_topseals
node_session1 -->|"saves with retry"| node_retry
node_session2 -->|"saves with retry"| node_retry
node_session3 -->|"saves with retry"| node_retry
node_demographics -->|"saves with retry"| node_retry
node_retry -.->|"posts submissions"| node_sessionapi
node_retry -.->|"posts combined data"| node_fullapi
node_sessionapi -->|"validates payload"| node_validation
node_fullapi -->|"validates payload"| node_validation
node_sessionapi -->|"writes exports"| node_export
node_fullapi -->|"writes exports"| node_export
node_export -->|"builds workbooks"| node_workbooks
node_sessionapi -->|"saves submission"| node_database
node_fullapi -->|"saves submission"| node_database
node_export -.->|"writes local files"| node_results
node_topseals -->|"reads saved sessions"| node_database
node_session1 -->|"uses translations"| node_localization
node_session2 -->|"uses translations"| node_localization
node_session3 -->|"uses translations"| node_localization

click node_start "https://github.com/kasunnmsu/meat-app/blob/main/app/page.tsx"
click node_consent "https://github.com/kasunnmsu/meat-app/blob/main/app/tcle/page.tsx"
click node_session1 "https://github.com/kasunnmsu/meat-app/blob/main/app/session-1/page.tsx"
click node_sealreading "https://github.com/kasunnmsu/meat-app/blob/main/app/session-2/descriptions/page.tsx"
click node_session2 "https://github.com/kasunnmsu/meat-app/blob/main/app/session-2/descriptions/page.tsx"
click node_session3 "https://github.com/kasunnmsu/meat-app/blob/main/app/session-3/page.tsx"
click node_demographics "https://github.com/kasunnmsu/meat-app/blob/main/components/DemographicsForm.tsx"
click node_ranking "https://github.com/kasunnmsu/meat-app/blob/main/components/RankingScreen.tsx"
click node_localization "https://github.com/kasunnmsu/meat-app/blob/main/lib/i18n.tsx"
click node_retry "https://github.com/kasunnmsu/meat-app/blob/main/lib/saveWithRetry.ts"
click node_sessionapi "https://github.com/kasunnmsu/meat-app/blob/main/app/api/session-1/save/route.ts"
click node_fullapi "https://github.com/kasunnmsu/meat-app/blob/main/app/api/full-survey/save/route.ts"
click node_topseals "https://github.com/kasunnmsu/meat-app/blob/main/app/api/session-3/top-seals/route.ts"
click node_validation "https://github.com/kasunnmsu/meat-app/blob/main/lib/payloadValidation.ts"
click node_export "https://github.com/kasunnmsu/meat-app/blob/main/lib/dataExports.ts"
click node_workbooks "https://github.com/kasunnmsu/meat-app/blob/main/lib/resultWorkbooks.ts"
click node_database "https://github.com/kasunnmsu/meat-app/blob/main/lib/studyDatabase.ts"
click node_results "https://github.com/kasunnmsu/meat-app/blob/main/lib/dataPaths.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_start,node_consent toneBlue
class node_session1,node_sealreading,node_session2,node_session3,node_demographics toneAmber
class node_ranking,node_localization toneMint
class node_retry,node_sessionapi,node_fullapi,node_topseals,node_validation,node_export,node_workbooks,node_database,node_results toneRose
class node_participant toneIndigo
```

## Components

### Participant entry

- [Survey entry](https://github.com/kasunnmsu/meat-app/blob/main/app/page.tsx): `app/page.tsx`
- [Consent](https://github.com/kasunnmsu/meat-app/blob/main/app/tcle/page.tsx): `app/tcle/page.tsx`

### Study tasks

- [Session 1 ranking](https://github.com/kasunnmsu/meat-app/blob/main/app/session-1/page.tsx): `app/session-1/page.tsx`
- [Seal descriptions](https://github.com/kasunnmsu/meat-app/blob/main/app/session-2/descriptions/page.tsx): `app/session-2/descriptions/page.tsx`
- [Session 2 ranking](https://github.com/kasunnmsu/meat-app/blob/main/app/session-2/descriptions/page.tsx): `app/session-2/descriptions/page.tsx`
- [Priced ranking](https://github.com/kasunnmsu/meat-app/blob/main/app/session-3/page.tsx): `app/session-3/page.tsx`
- [Demographics](https://github.com/kasunnmsu/meat-app/blob/main/components/DemographicsForm.tsx): `components/DemographicsForm.tsx`

### Shared interface

- [Ranking interaction](https://github.com/kasunnmsu/meat-app/blob/main/components/RankingScreen.tsx): `components/RankingScreen.tsx`
- [Language and location](https://github.com/kasunnmsu/meat-app/blob/main/lib/i18n.tsx): `lib/i18n.tsx`

### Submission and results

- [Save retry queue](https://github.com/kasunnmsu/meat-app/blob/main/lib/saveWithRetry.ts): `lib/saveWithRetry.ts`
- [Session save routes](https://github.com/kasunnmsu/meat-app/blob/main/app/api/session-1/save/route.ts): `app/api/session-1/save/route.ts`
- [Full survey route](https://github.com/kasunnmsu/meat-app/blob/main/app/api/full-survey/save/route.ts): `app/api/full-survey/save/route.ts`
- [Top seals lookup](https://github.com/kasunnmsu/meat-app/blob/main/app/api/session-3/top-seals/route.ts): `app/api/session-3/top-seals/route.ts`
- [Payload validation](https://github.com/kasunnmsu/meat-app/blob/main/lib/payloadValidation.ts): `lib/payloadValidation.ts`
- [Excel and JSON exports](https://github.com/kasunnmsu/meat-app/blob/main/lib/dataExports.ts): `lib/dataExports.ts`
- [Workbook rows](https://github.com/kasunnmsu/meat-app/blob/main/lib/resultWorkbooks.ts): `lib/resultWorkbooks.ts`
- [Study database](https://github.com/kasunnmsu/meat-app/blob/main/lib/studyDatabase.ts): `lib/studyDatabase.ts`
- [Local result files](https://github.com/kasunnmsu/meat-app/blob/main/lib/dataPaths.ts): `lib/dataPaths.ts`

### Other components

- **Participant**

## Connections

- Participant → Survey entry: starts survey (evidence: `README.md`)
- Survey entry → Consent: continues to
- Survey entry → Session 1 ranking: starts session (evidence: `README.md`)
- Survey entry → Seal descriptions: starts session (evidence: `README.md`)
- Survey entry → Priced ranking: starts session (evidence: `README.md`)
- Seal descriptions → Session 2 ranking: unlocks ranking (evidence: `README.md`)
- Session 1 ranking → Ranking interaction: uses ranking (evidence: `app/session-1/page.tsx`)
- Seal descriptions → Ranking interaction: uses ranking (evidence: `app/session-2/descriptions/page.tsx`)
- Priced ranking → Ranking interaction: uses ranking (evidence: `app/session-3/page.tsx`)
- Session 1 ranking → Demographics: collects at end (evidence: `README.md`)
- Session 2 ranking → Demographics: collects at end (evidence: `README.md`)
- Priced ranking → Demographics: collects final (evidence: `README.md`)
- Priced ranking → Top seals lookup: requests top seals (evidence: `app/session-3/page.tsx`)
- Session 1 ranking → Save retry queue: saves with retry (evidence: `app/session-1/page.tsx`)
- Session 2 ranking → Save retry queue: saves with retry (evidence: `app/session-2/descriptions/page.tsx`)
- Priced ranking → Save retry queue: saves with retry (evidence: `app/session-3/page.tsx`)
- Demographics → Save retry queue: saves with retry (evidence: `app/demographics/page.tsx`)
- Save retry queue → Session save routes: posts submissions
- Save retry queue → Full survey route: posts combined data
- Session save routes → Payload validation: validates payload (evidence: `app/api/session-1/save/route.ts`)
- Full survey route → Payload validation: validates payload (evidence: `app/api/full-survey/save/route.ts`)
- Session save routes → Excel and JSON exports: writes exports (evidence: `app/api/session-1/save/route.ts`)
- Full survey route → Excel and JSON exports: writes exports (evidence: `app/api/full-survey/save/route.ts`)
- Excel and JSON exports → Workbook rows: builds workbooks (evidence: `lib/resultWorkbooks.ts`)
- Session save routes → Study database: saves submission (evidence: `app/api/session-1/save/route.ts`)
- Full survey route → Study database: saves submission (evidence: `app/api/full-survey/save/route.ts`)
- Excel and JSON exports → Local result files: writes local files
- Top seals lookup → Study database: reads saved sessions (evidence: `app/api/session-3/top-seals/route.ts`)
- Session 1 ranking → Language and location: uses translations (evidence: `app/session-1/page.tsx`)
- Session 2 ranking → Language and location: uses translations (evidence: `app/session-2/descriptions/page.tsx`)
- Priced ranking → Language and location: uses translations (evidence: `app/session-3/page.tsx`)
