Inspiration

The future is a city. By 2050 about two-thirds of humanity will live in one, and that single migration is quietly the largest driver of language extinction on Earth. A language almost never dies where it was born; it dies one generation after that place's children move to the this century, most of them carried by the Indigenous, immigrant, and diaspora communities now packed into our biggest cities.

We started from one face inside that city: a grandmother who dreams in a language her grandchild was never taught, one of the last in her family who can still speak it, surrounded by millions of people and no one left to speak it with. Her language has no course not because no one cares, but because documenting and teaching a language has always taken trained linguists years, and the world runs out of linguists long before it runs out of dying languages. We built Lantern as the missing civic infrastructure for that city: a public tool that manufactures the missing course on demand, from the few words a community still remembers.

What it does

Lantern is Duolingo for languages that are dying. Pick a language so endangered that no app, no textbook, and no course exists for it. Lantern takes a handful of remembered phrases, works out the grammar hidden inside them, and builds a real beginner course, in minutes, for a language that had nothing an hour before:

  • a cited vocabulary bank, every word traceable to the exact phrase that attests it;

  • the grammar patterns it discovered (for Māori: how tense rides on a particle before the verb, how number lives on the article, how possession marks by dropping a letter);

  • flashcards with pronunciation on a spaced-repetition schedule;

  • and a Contribute tab where adding one phrase, like Ka pai ("good"), rebuilds the entire course, richer, in seconds.

It ships with eight endangered languages, two of them (Māori and Cherokee) fully learnable today, including Ainu (about ten speakers left) and Manx and Cornish, both brought back from the brink by their own communities. It is, in effect, a civic amenity for the multilingual city: a place an urban family can go to keep its own language alive and hand it down.

Try it live at https://lantern-cyan.vercel.app, watch it learn Māori from 41 phrases, see the grammar it found, and take the course it built.

What makes it trustworthy is an inversion. An AI cannot truly know a language with fifty speakers, so asking it to "teach" one only produces confident hallucination, worse than useless for a critically endangered language. Lantern's model is therefore not the source of knowledge; it is an amplifier of the community's. It reasons only over the phrases it is given, cites every claim, and is forbidden, in code, from ever teaching a word that was not attested.

How we built it

  • Next.js 16 + TypeScript, deployed on Vercel, a civic tool any city resident opens in a browser, on a phone or a laptop, no install.

  • An induction engine that does interlinear analysis on the seed corpus, induces morphology from minimal pairs, and writes a lesson by recombining only attested vocabulary, via forced structured output validated at runtime with Zod.

  • The guardrail, in code, not in the prompt: every generated sentence and flashcard is tokenized and checked against the attested vocabulary; one unattested word and the item is discarded. That gives a probabilistic model a hard correctness property.

  • A course on the SM-2 spaced-repetition algorithm with in-browser Web Speech text-to-speech.

  • Live induction runs an LLM, Llama 3.3 70B on Groq, driven through the Anthropic SDK, with a verified hand-checked fallback so the demo never breaks; the contribution flywheel persists in MongoDB Atlas.

Accomplishments we're proud of, we measured it

This is not a concept video. It is a working web app, and we measured its behavior:

  FROM 41 MĀORI PHRASES, LANTERN RECOVERED

  ──────────────────────────────────────────────

    34   words, each cited to its source

     5   grammar patterns (tense, number, possession)

    12   flashcards on a spaced-repetition schedule

  ──────────────────────────────────────────────

     0   invented words reached a learner          ✓

  48/48  vocabulary items cited (both languages)   ✓

   7/7   generated practice sentences attested     ✓

Reproducible live at GET /api/metrics, the same numbers a judge can pull right now.

How it maps to the judging criteria

  • Innovation & creativity, an inversion: the AI is an amplifier of the community's knowledge, handed a hard, deterministic correctness property enforced in code, not a prompt.

  • Adherence to theme, civic, public-good infrastructure aimed at the defining cultural problem of the urban future: the languages a city quietly erases as people migrate into it. Infrastructure for who a city's people are, not just how it runs.

  • Real-world impact & usefulness, ships with eight real endangered languages, two fully learnable today, every word cited; the AI runs live on the deployed site, not a mockup.

  • Presentation, a film, a working deployment, and reproducible measured results at GET /api/metrics; the demo stands on its own.

  • User experience, Duolingo-simple: flashcards, audio you can hear, spaced repetition, and a one-field Contribute box that rebuilds the whole course in seconds.

What's next

Speaker-recorded audio, fluent-speaker review, printable primers for offline communities, and formal data-sovereignty controls so each community owns and governs its own words. The endpoint is a living, community-governed digital ark with an entry for every endangered language, each revivable the moment one elder seeds it, a piece of cultural infrastructure as ordinary in tomorrow's city as a library is in today's.


Advanced division, the full engineering build, end to end

A future city runs on infrastructure, and real infrastructure has two non-negotiable properties: it does not go down, and it does not lie. We built Lantern to that standard. This is not a weekend prototype with a pretty screenshot; it is a deployed, production-grade civic system you can load on your phone right now and stress-test yourself. We are entering the Advanced division because this is Advanced-tier work, and the rest of this write-up is the complete engineering account: every layer, every external dependency, every fail-safe, and the history of how it was built, so the judges can verify the depth instead of taking our word for it.

The proof, live (anyone can verify it this second)

Every number below is recomputed on each request at https://lantern-cyan.vercel.app/api/metrics. It is not a screenshot; it is the same code path that builds the lessons, reporting on itself.

  Hallucinated words that ever reached a learner
  0          zero. always. enforced in code by guardrail.check.ts
             |__________________________________________________

  Vocabulary with a real, cited source
  48 / 48    ##############################   100%

  Practice sentences passing the attestation gate
  7 / 7      ##############################   100%

How Lantern differs from a normal "AI tutor" you could build in a weekend:

  +------------------------------+-------------+--------------------+
  |                              | Generic AI  |      LANTERN       |
  +------------------------------+-------------+--------------------+
  | Invents words to fill gaps   |    yes      | forbidden in code  |
  | Cites a real source per word |    no       | 48/48   (100%)     |
  | Works for ~50-speaker langs  |    barely   | built for it       |
  | Proves its honesty live      |    no       | /api/metrics       |
  | Deployed, not a slideshow    |  sometimes  | yes, on Vercel     |
  +------------------------------+-------------+--------------------+

1. Architecture at a glance

Lantern is one Next.js 16 application (App Router, React Server Components, Turbopack) written end to end in TypeScript. There is no separate backend service: server logic lives in Server Components and Route Handlers on Vercel's Node runtime, right next to the UI that consumes them. For a civic tool that has to run on a cheap phone over a weak connection, that single-deployable, edge-served shape is the point.

                      THE BROWSER (any phone or laptop)
  +-----------------------------------------------------------------+
  | React Server Components (streamed HTML) + small client islands  |
  | Hero . LiveInduction . Workspace . Flashcards . ContributeForm  |
  +----------------+--------------------------------+---------------+
                   | server-rendered                | fetch() /api/*
                   v                                 v
  +-------------------------+        +------------------------------+
  | Next.js 16 (Vercel Node)|        | Route Handlers (/api/*)      |
  | RSC data loading        |        | contribute induce audio      |
  | layout pages metadata   |        | metrics stats auth/[...]     |
  +-----------+-------------+        +--------------+---------------+
              |                                     |
              v                                     v
  +-----------------------------------------------------------------+
  |              THE INDUCTION ENGINE  (src/lib/engine)             |
  |  tokenize -> normalize -> induce(LLM) -> GUARDRAIL(cite|reject) |
  |  -> attestation gate -> lesson assembly                        |
  +----+-------------+-------------+----------------+---------------+
       v             v             v                v
   +-------+    +---------+   +----------+    +-------------+
   | Groq  |    | MongoDB |   | Firestore|    | Vercel Blob |
   | LLM   |    | Atlas   |   | users /  |    | pronunciation|
   |3.3 70B|    | corpus  |   | auth     |    | audio (CDN) |
   +-------+    +---------+   +----------+    +-------------+
       |             |             |                |
       v             v             v                v
   fixture       in-memory     graceful         503 fail-soft
   fallback      fallback      auth gating      (storage off)

  Every external dependency has a fail-soft path. Nothing here can take
  the city's memory offline.

2. Request lifecycle (a resident opening their language)

  1. GET /lang/mi                (Server Component, Vercel Node, force-dynamic)
  2. getLanguageMeta("mi")       -> record; unknown id -> notFound() -> 404
  3. getStore()                  -> MongoDB Atlas (or in-memory if no URI)
  4. store.getPhrases("mi")      -> the cited corpus for this language
  5. <Workspace> hydrates; Learn tab calls the engine
  6. runInduction(corpus):
       tokenize + normalize every phrase (canonical, case-folded)
       LLM induces vocab + grammar FROM THOSE PHRASES ONLY
       Zod validates the LLM JSON (reject malformed shapes)
       GUARDRAIL drops any word not attested in the corpus
       assemble SRS cards + practice (attestation-gated)
  7. The learner sees only words a real speaker said. Always.

/api/metrics runs this exact path, so the honesty numbers are computed by the same code that builds lessons, not a separate flattering report.

3. The anti-hallucination guardrail, in full (the novel core)

A normal model pointed at a tiny corpus invents plausible words to fill gaps. In a future city, where Indigenous and immigrant languages are concentrated and dying fastest, an invented word does not just embarrass a demo, it can outlive the last fluent elder and quietly become "fact." We made that structurally impossible.

  • Canonical tokenization: one tokenizer, one normalizer, case-folded, with no stale copy anywhere in the codebase (a project invariant). Two strings are "the same word" only after both pass through it. This kills an entire class of false matches caused by casing, punctuation, and whitespace.
  • Cite-or-reject: every candidate word the model proposes is checked against the tokens that actually appear in the community's phrases.
  for each candidate word w:
     if normalize(w) in corpusTokens:   KEEP   (record its citation)
     else:                              REJECT (never reaches a learner)

There is no confidence threshold and no "probably fine." 100% citation coverage is not a metric we hope for; it is an invariant the code refuses to violate.

  • Attestation gate on generated sentences: practice sentences are built by recombining known words, then each is re-checked word by word, and if even one token was never said, the whole sentence is deleted before any learner sees it. That is why "practice sentences failing attestation" is always 0.
  Worked example, rejecting "taniwha"
  corpus: 41 attested Maori phrases (no "taniwha")
  model wants to teach "taniwha"
  guardrail: normalize("taniwha") in corpusTokens? NO -> DISCARDED on screen
  learner sees only the 34 words the 41 phrases actually contain

guardrail.check.ts runs the full induction over the shipped corpora and asserts 0 hallucinations and 100% citation, or it fails the build ritual. The honesty promise cannot quietly regress.

4. Frontend

  • Next.js 16 App Router with React Server Components: the hero and story stream as server HTML so there is no empty-void flash; only the interactive parts (Workspace tabs, Flashcards, ContributeForm, the LiveInduction demo) hydrate as client islands. The result loads fast on a cheap device, which is exactly what a civic tool needs.
  • A deliberate type system carries the argument: Fraunces (a warm serif) for emotion, IBM Plex Mono for the machine-checked artifacts (cited words, tense particles, live metrics) so "verified in code" is legible in the typography itself, and Hanken Grotesk for body, chosen specifically to avoid the Inter/Geist defaults every AI build ships.
  • Palette: deep warm ink, a single lantern-amber (ember) light source, and pounamu (greenstone) jade for life and revival. The hero fade-rise is a CSS animation that runs on first paint, not a JS entrance that flashes empty.
  • The LiveInduction demo animates the real pipeline: a corpus resolving into cited vocabulary, with the guardrail visibly discarding an invented word. It is the one thing a competitor cannot copy.
  • Flashcards run the SM-2 spaced-repetition schedule with in-browser text-to-speech (Web Speech API), so audio never leaves the device.
  • Measured quality on the live site: Lighthouse 100 Accessibility / 100 Best Practices / 100 SEO and roughly 100 Performance on every page (LCP 241ms, CLS 0.00), with a semantic single-main landmark and sequential heading order. Accessibility is not decoration here; civic infrastructure has to work for everyone.

5. Backend

  • The induction engine (src/lib/engine) orchestrates tokenize -> induce -> guardrail -> assemble. The LLM call (src/lib/llm.ts) speaks the OpenAI-compatible protocol to Groq, model llama-3.3-70b-versatile, and the response is parsed and validated with Zod before anything is trusted.
  • Route Handlers: /api/contribute (Zod-validated phrase intake), /api/induce, /api/audio (multipart upload), /api/metrics and /api/stats (the live proof), and /api/auth/[...nextauth].
  • Fail-soft is a first-class design value, not an afterthought (see section 9).

6. Data layer

  • MongoDB Atlas (M0 free tier, AWS us-east-1) stores the growing corpus and the stats. The store (src/lib/store.ts) is an interface with two implementations: a Mongo-backed store when MONGODB_URI is present, and an in-memory store when it is not, so the app boots and the demo works with zero configuration. Round-trip verified by scripts/mongo.check.ts (connect + insert + read + delete).
  • The Phrase model carries the text, meaning, category, source citation, and an optional audioUrl. Corpora in src/lib/seed are ground truth and never contain a word that cannot be attributed to a real source.
  • Firestore (firebase-admin) stores user records for auth: id, email, name, bcrypt passwordHash, provider, createdAt, emailVerified. Round-trip verified by scripts/firestore.check.ts.
  • Vercel Blob (public CDN) stores speaker-pronunciation clips. The upload path enforces a 5MB cap, an audio content-type allow-list, and a sanitized key (no path traversal), with addRandomSuffix to prevent collisions. Round-trip verified by scripts/blob.check.ts. It replaced Firebase Storage, which began requiring a billing card; we kept the entire stack on free tiers so a community can run this without a budget.

7. Authentication

  • Auth.js v5 (NextAuth) with three providers: Google, GitHub, and email/password (Credentials). Passwords are hashed with bcrypt; sessions are JWT.
  • Providers register only when their env is present, so an empty environment still boots the whole app. Auth is strictly additive: signing in adds synced progress and attribution but never gates the demo, because a civic tool must never lock a resident out of their own heritage behind a login.
  • Fail-soft gating: a single authConfigured() flag (AUTH_SECRET present) decides whether any auth UI renders. Without it the session provider is not mounted, the sign-in control is hidden, and /signin shows a graceful "accounts not switched on" panel instead of a form that would error, so an unconfigured deploy is clean, with no dead buttons and no console errors.
  • Includes forgot-password and email-verification flows.

8. Infrastructure and hosting

  • Hosted on Vercel; push to main auto-deploys. Production is lantern-cyan.vercel.app.
  • Twelve environment keys configure the full backend: AUTH_SECRET, AUTH_URL, GOOGLE_CLIENT_ID/SECRET, GITHUB_ID/SECRET, GROQ_API_KEY, FIREBASE_PROJECT_ID/CLIENT_EMAIL/PRIVATE_KEY, MONGODB_URI, BLOB_READ_WRITE_TOKEN.
  • The OAuth callback URLs are pre-registered for the production domain, so turning the backend on is a paste-and-redeploy with zero extra configuration.
  • Free-tier discipline throughout: MongoDB Atlas M0, Firestore Spark, Vercel Blob Hobby, Groq, GitHub/Google OAuth, no credit card anywhere. Cost is a real barrier to civic technology; we removed it.

9. Reliability engineering (infrastructure-grade uptime)

  Failure                         Lantern's response
  ------------------------------  -------------------------------------
  LLM unreachable / bad key       fall back to a hand-verified fixture
  Mongo unreachable / no URI      fall back to an in-memory store
  Auth not configured             hide auth UI, no dead buttons/errors
  Blob storage off                recorder not offered; /api/audio 503
  Malformed API input             Zod -> clean 400, never a 500
  Unknown language id             branded not-found page

Five self-checking scripts encode the invariants and are run before deploy: guardrail.check (0 hallucinations, 100% citation), failsoft.check (Contribute never throws), mongo.check, blob.check, firestore.check. The guardrail check is the one that can fail a release. A city's memory cannot have downtime, and it cannot lie; this is how we guarantee both.

10. The build history (how we got here)

  Slice 1   additive auth (Auth.js v5: Google/GitHub/email) + account menu
  PHASE 0   lint green + fail-soft regression test
  Auth      forgot-password + email verification
  Stage 1   de-vibe-code the hero, fix silent TTS
  Stage 2   make the landing "hear it" button actually speak
  Stage 3   FAQ page
  PHASE 4   speaker pronunciation audio on Vercel Blob
  Hero      kill the empty-void first paint; warmth + a loud proof band
  Item 4    the live induction demo (the thing a competitor cannot copy)
  Auth      fail-soft UI when AUTH_SECRET is absent (clean prod degradation)
  a11y      homepage <main> landmark; sequential heading order -> 100s
  Deploy    re-authored under the owner for the production Vercel

The through-line: take a real but rough build, harden it slice by slice, verify every change against the live app and the guardrail, and never ship a regression.

11. Engineering challenges and how we solved them

  • Making an LLM useful on a tiny corpus without letting it invent: solved by inverting the usual prompt into cite-or-discard, enforced by a code-level check rather than a prompt plea.
  • Staying honest and online when the model fails: solved with verified fixtures so Contribute never throws and the demo never breaks.
  • Keeping a 100% citation invariant as the corpus grows: a self-test that fails the release if a single uncited word ever slips through.
  • A production deploy with no environment: solved by making auth, the LLM, and the database all degrade gracefully, so the app is presentable and honest even before a single key is set.

12. Ethics and community data sovereignty

Endangered-language data carries real cultural ownership. Our position: the community owns and governs its corpus, and Lantern is a tool used on that data, never an extraction pipeline. We cite the source of every seed phrase, and we cite every photo of every community on the site. Pronunciation is generated in the browser, so no learner audio is sent to us. Data-sovereignty controls, letting each community decide who can view, download, and contribute to its language, are an active part of the roadmap. For a future city, this is the difference between technology that serves communities and technology that mines them.

13. Tech stack

  Layer            Choice
  ---------------  ------------------------------------------------------
  Framework        Next.js 16 (App Router, RSC, Turbopack)
  Language         TypeScript
  AI               Groq, llama-3.3-70b-versatile (OpenAI-compatible)
  Validation       Zod
  Auth             Auth.js v5, Google, GitHub, email/password (bcrypt)
  User store       Firestore (firebase-admin)
  App data         MongoDB Atlas (M0) + in-memory fallback
  Audio storage    Vercel Blob (public CDN)
  Pronunciation    Web Speech API (in-browser)
  Type / design    Fraunces, IBM Plex Mono, Hanken Grotesk; ember + pounamu
  Hosting          Vercel (push-to-deploy)

14. Verify every claim yourself

  Honesty metrics      GET https://lantern-cyan.vercel.app/api/metrics
  Live app             https://lantern-cyan.vercel.app
  Guardrail invariant  npx tsx src/lib/engine/guardrail.check.ts
  Contribute fail-soft npx tsx scripts/failsoft.check.ts
  Mongo round-trip     npx tsx --env-file=.env.local scripts/mongo.check.ts
  Blob round-trip      npx tsx --env-file=.env.local scripts/blob.check.ts
  Firestore round-trip npx tsx --env-file=.env.local scripts/firestore.check.ts

15. Why this wins FutureHacks, criterion by criterion

  • Innovation and Creativity: the cite-or-reject guardrail is a genuine inversion of how every AI tutor works. The fresh angle is making the AI do LESS on purpose, enforced in code rather than asked for in a prompt. Nobody copies this, because copying it means giving up the gap-filling that other tutors depend on.
  • Adherence to Theme: language is the cultural infrastructure of the future city. Urbanization is the single largest driver of language death on Earth, and a city that forgets the languages of the people who built it is not advanced, it is amnesiac. Lantern is the civic tool that makes remembering as ordinary in tomorrow's city as a library is in today's.
  • Real-world Impact and Usefulness: it works today, on a phone, for real communities (Maori and Cherokee are fully learnable now), with the dignity of never inventing someone's heritage. It is deployed, honest, and verifiable live, not a slideshow.

Lantern is a small app with one very large promise, kept in code: it never teaches a word a real speaker did not say. That is the entire point, and it is verifiable, live, right now.

16. The civic case, why a future city has to remember its languages

It is easy to treat language preservation as nostalgia. It is not. It is urban policy. Here is the chain of facts that puts Lantern squarely inside the future-city theme.

A language goes silent somewhere on Earth roughly every two weeks, and linguists project that a large share of the world's ~7,000 languages will be gone by the end of this century. The single largest accelerant of that loss is urbanization. When a family moves from a rural community into a city for work, safety, or opportunity, the surrounding language becomes the language of school, of jobs, of belonging, and within one or two generations the heritage language stops being passed down. The grandparent still dreams in it. The grandchild was never taught it. Cities are not neutral in this; they are where languages go to die, precisely because cities concentrate the very communities, Indigenous and immigrant, who already carry the least institutional support.

So the future city has a choice that nobody is building software for. It can keep optimizing only the physical layer, becoming a faster, cleaner place that has forgotten who lives in it. Or it can treat its linguistic and cultural memory as public infrastructure, as ordinary and expected as a transit map or a public library, and give every community a tool to keep their own words alive. Lantern is that tool. It is deliberately civic: free, open without a login, runnable on a cheap phone, governed by the community whose words it holds, and honest enough that an elder can trust it with the thing they cannot get back. A city that remembers every voice that built it is not being sentimental. It is being more advanced than one that forgets.

17. The learning engine, in depth

The part residents actually touch is a real course, not a list of words. Three systems make it work.

First, spaced repetition. Flashcards are scheduled with the SM-2 algorithm, the same family that powers serious language apps, so each word returns just before you would forget it. Pronunciation is spoken in the browser through the Web Speech API, so you can hear a word out loud with no audio ever leaving your device.

Second, attestation-gated generation. Lantern does not just teach the raw phrases; it teaches the patterns hidden inside them. For Maori it surfaces how a small particle before the verb shifts past, present, and future, then it builds fresh practice sentences by recombining words the community actually used, and it re-checks every generated sentence against the real vocabulary before showing it. If a single word in a generated sentence was never spoken by a real person, the sentence is deleted. That is the difference between an AI that practices you on the language and an AI that practices you on its own fiction.

Third, the Contribute loop. The corpus is alive. Anyone who remembers one more phrase, say Ka pai ("good"), can add it, and the whole course re-induces itself, richer, in seconds, with every new word still carrying the source it came from. The app ships pre-loaded with eight endangered languages, two of which, Maori and Cherokee, are fully learnable today; the rest are seeds waiting for the first elder to remember out loud.

The endpoint is a living, community-governed digital ark: an entry for every endangered language, each revivable the moment a single person seeds it, a piece of cultural infrastructure as ordinary in tomorrow's city as a library is in today's. We did not just build a hackathon project. We built the first working brick of that infrastructure, and it is online right now at lantern-cyan.vercel.app.

Built With

Share this project:

Updates