Data Model
The NordJari database is PostgreSQL (via Supabase), modelled with Prisma.
Entity overview
User
├── UserSeason (join: user × season)
│ └── Habit
│ └── HabitLog
├── UserBadge
├── CoachMessage
├── DailyPromptLog
└── UserConceptMonth
└── (references Concept)
Season
└── SeasonChallenge
Concept
├── ConceptWeek
│ └── ConceptHabit
└── ConceptBadgeCondition
Core tables
User
Stores profile data. leaderboardOptIn controls whether the user appears on the public leaderboard.
Season
Global season records (one per quarter per year). Seeded at the start of each year.
| Field | Description |
|---|---|
name | e.g. "Nord Q1 2026" |
type | nord or jari |
quarter | 1–4 |
startDate / endDate | Full quarter date range |
UserSeason
Joins a user to a season. Holds their running scorePct and status.
Habit
A single habit within a user's season. Has a targetPerWeek (default 5).
HabitLog
One record per habit per day. status is done, skip, or miss.
streakDaytracks the consecutive streak count at the time of logging- Unique constraint on
(habitId, logDate)— one log per habit per day
Badge
Catalogue of all badges (11 Nord + 11 Jari). Seeded once.
| conditionType | Description |
|---|---|
streak_days | Maintain X consecutive days |
season_score | Reach X% season score |
habits_completed | Log X total done entries |
season_finished | Complete all 90 days |
all_concepts_completed | Complete all 6 concept months (Master badge) |
UserBadge
Awarded when a condition is met. Unique on (userId, badgeId, seasonId) — one award per badge per season.
CoachMessage
Stores the AI coach conversation. role is user or assistant. weekKey (e.g. 2026-W20) is set on weekly brief messages to enable deduplication.
DailyPromptLog
One record per user per day per prompt type. promptType is gratitude, creativity, or reflection.
Concept tables
Concept
The 12 concept definitions (6 Nord + 6 Jari). Seeded once. order 1–5 are freely choosable; order 6 is locked until all 5 others are completed.
ConceptWeek
4 weeks per concept, each with a title, goal, and prompt.
ConceptHabit
Habits listed under each week's checklist. Seeded as Habit records when a user starts a concept month.
ConceptBadgeCondition
Defines what the user must achieve to earn a concept badge (e.g. days_outside >= 20).
UserConceptMonth
Tracks which concept a user is running in a given month.
| Field | Description |
|---|---|
status | active, completed, or abandoned |
year / month | The calendar month |
completedAt | Set when status → completed |
Unique on (userId, year, month) — one concept per user per month.
Key constraints
- Dates stored as UTC
logDatefields use@db.Date— date only, no time component- Season type (
nord/jari) derived fromlib/seasons.ts, never hardcoded in components - Service role key is server-only — client uses anon key + RLS