P/N 01Case studyPersonal startup

HERISAGA — History as Playable Stories
A bilingual mobile app that turns Albanian history into playable stories, with interactive lessons, review sessions and progress tracking. I co-founded HERISAGA, and we are building it toward a production release and in the near future expanding with global history.
- Role
- Co-Founder, Full-Stack Software Engineer
- Team
- Co-founding team (2)
- Duration
- 4 Months
- Year
- 2026
- Stack
- Flutter · Dart · Riverpod · go_router · Drift/SQLite · Lottie · TypeScript · Node.js · NestJS · Kysely · Zod · PostgreSQL · Supabase Auth · OpenAPI · JSON Schema · Docker · GitHub Actions · Sentry · PostHog
Outcomes
2438
Mobile tests passing
- 501
API checks passing across integration, security, end-to-end and smoke suites
- 4
Interactive question formats
- 2
Languages: English and Albanian
Problem
History often reaches learners as a wall of dates and names. HERISAGA turns it into a journey: short narratives, interactive questions and review sessions that help learners connect events and understand why they matter. It starts with Albanian history, for students, heritage learners and curious readers in English and Albanian.
Constraints
Lessons must feel instant on a phone, yet rewards must be trustworthy: retries, flaky connections and interrupted sessions can never lose progress or award XP twice. Content keeps evolving after release, and the interface has to handle longer Albanian text across both themes.
Architecture
A Flutter app, built with Riverpod, go_router and a local Drift/SQLite store, talks to a NestJS API over HTTP/JSON, with Supabase handling authentication. Published episodes arrive as immutable content from a CDN, while answer bundles come from a separate API endpoint. The API grades answers, schedules reviews and records XP, streaks and progress in PostgreSQL through restricted database roles. Shared OpenAPI and JSON Schema contracts keep the app and API aligned.
5 parts, 4 connections.
- N01 — Episode CDN
- N02 — Supabase Auth
- N03 — Flutter app
- N04 — NestJS API
- N05 — PostgreSQL
- Episode CDN to Flutter app, episodes
- Supabase Auth to Flutter app, sign-in
- Flutter app to NestJS API, HTTP/JSON
- NestJS API to PostgreSQL, progress
Key decisions
Separate instant feedback from reward authority. Answers are checked locally, so lessons feel instant, but the server re-grades every submission and alone decides XP, streaks and progression.
Pin each session to a content revision. A lesson in progress never changes under the learner, even when editors publish a new version.
Idempotent events and atomic transactions for progress. A repeated or interrupted request can never duplicate rewards or corrupt a streak.

Results
The app and API are implemented and in integration and release validation, ahead of a production launch. In the latest recorded local verification, 2,438 mobile tests and 501 API checks passed across integration, security, end-to-end and smoke suites.
The screens below are the real app, every flow in light and dark and in English and Albanian. Swipe a strip, or use its arrows.

Light · English

Light · Albanian

Dark · English

Dark · Albanian

Continue a lesson · light

Continue a lesson · dark

Read the passage

A question

An answer chosen

Correct, and why

True or false, missed

The next passage

Lesson completed

Read the passage

A question

An answer chosen

Not quite, and why

True or false, correct

Lesson completed

Dark · a lesson ready

Dark · by lesson

Light · a lesson ready

Light · by lesson

Profile · dark

Profile · light

Settings · light

Settings · dark

Edit profile · light

Edit profile · dark
Reflection
I would take one real episode through the full journey, from publication to playback, grading and progress recovery, earlier in the project, and grow the features around that proven path. I would keep the strict split between fast local feedback and server-side authority.