<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chaminade Dondah ADJOLOU</title>
    <description>The latest articles on DEV Community by Chaminade Dondah ADJOLOU (@jwzqeygxtonh).</description>
    <link>https://dev.to/jwzqeygxtonh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99mvlsfu5tfj9m7ku25d.png</url>
      <title>DEV Community: Chaminade Dondah ADJOLOU</title>
      <link>https://dev.to/jwzqeygxtonh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jwzqeygxtonh"/>
    <language>en</language>
    <item>
      <title>I vibe-coded a cassette deck for family memory — K7 Mémoire (Sanity Challenge Path 2)</title>
      <dc:creator>Chaminade Dondah ADJOLOU</dc:creator>
      <pubDate>Fri, 02 Oct 2026 15:36:05 +0000</pubDate>
      <link>https://dev.to/jwzqeygxtonh/i-vibe-coded-a-cassette-deck-for-family-memory-k7-memoire-sanity-challenge-path-2-4b3f</link>
      <guid>https://dev.to/jwzqeygxtonh/i-vibe-coded-a-cassette-deck-for-family-memory-k7-memoire-sanity-challenge-path-2-4b3f</guid>
      <description>&lt;h1&gt;
  
  
  I vibe-coded a cassette deck for family memory — K7 Mémoire (Sanity Challenge Path 2)
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Chaminade (Dondah Chamiande Adjolou) · Lomé, Togo&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Challenge:&lt;/strong&gt; &lt;a href="https://www.sanity.io/" rel="noopener noreferrer"&gt;Sanity Challenge&lt;/a&gt; Path 2 — &lt;em&gt;Vibe-code something strange&lt;/em&gt; (Sep 18–Oct 4, 2026 PDT)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Tag:&lt;/strong&gt; &lt;code&gt;#sanitychallenge&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Live deck: &lt;a href="https://k7-memoire.vercel.app" rel="noopener noreferrer"&gt;https://k7-memoire.vercel.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Embedded Studio: &lt;a href="https://k7-memoire.vercel.app/studio" rel="noopener noreferrer"&gt;https://k7-memoire.vercel.app/studio&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sanity project ID:&lt;/strong&gt; &lt;code&gt;nh4vx26w&lt;/code&gt; · &lt;strong&gt;Dataset:&lt;/strong&gt; &lt;code&gt;production&lt;/code&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Why something strange
&lt;/h2&gt;

&lt;p&gt;In Lomé, family history often travels by voice before it travels by page. I did not want another blog layout for that. Path 2 of the Sanity Challenge asks for something strange — so I vibe-coded &lt;strong&gt;K7 Mémoire&lt;/strong&gt;: a Next.js cassette / radio UI that treats Sanity documents as tapes you can tune, filter by mood, and “play.”&lt;/p&gt;

&lt;p&gt;The copy is French, Lomé-flavored. The chrome is a deck: FM dial, mood filters, spinning reels, counter, VU meters, rolling transcript, and a kente stripe. No article list. No card grid. Stories are &lt;strong&gt;bandes&lt;/strong&gt;; narrators are &lt;strong&gt;voix&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This sits next to earlier work I care about — like a family-tree project for Hacktoberfest — but K7 Mémoire is its own object: oral memory as an instrument, not a CMS demo with a pretty skin.&lt;/p&gt;


&lt;h2&gt;
  
  
  The product prompt (and why process matters)
&lt;/h2&gt;

&lt;p&gt;Judges for this challenge weigh &lt;strong&gt;process&lt;/strong&gt; as much as the result. I kept a journal in the repo: &lt;code&gt;PROMPT_LOG.md&lt;/code&gt;. The brief I gave the agent was essentially one product prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An oral archive for Lomé, stored in Sanity, played by a cassette-deck UI, with Studio, seed stories, README, and this log.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From there, the log records what landed and what broke. Scaffolding with &lt;code&gt;create-next-app&lt;/code&gt; (Next.js App Router, TypeScript, Tailwind) into a subdirectory, then moving to the repo root, was more reliable than aiming the CLI at the root. Studio landed at &lt;code&gt;/studio&lt;/code&gt; with &lt;code&gt;next-sanity&lt;/code&gt;, Sanity v6, Vision, and a custom desk (&lt;strong&gt;Bandes&lt;/strong&gt; / &lt;strong&gt;Voix&lt;/strong&gt;). One GROQ string is shared by the live client and by &lt;code&gt;groq-js&lt;/code&gt; over the seed documents — tests assert eight tapes and resolved narrator names.&lt;/p&gt;

&lt;p&gt;Failures were part of the craft: no Sanity credentials in the first environment (so the deck shipped a labeled &lt;strong&gt;demo mode&lt;/strong&gt; using the &lt;em&gt;same&lt;/em&gt; query, not a second content model); Vitest peer friction (switched to &lt;code&gt;tsx --test&lt;/code&gt;); a Turbopack production build that choked on &lt;code&gt;swr&lt;/code&gt;’s &lt;code&gt;react-server&lt;/code&gt; export until &lt;code&gt;swr&lt;/code&gt; was aliased in &lt;code&gt;next.config.ts&lt;/code&gt;; Studio pulled into the RSC graph until the config lived behind a client boundary.&lt;/p&gt;

&lt;p&gt;Left undone on purpose in that early pass: no audio files on demo tapes (&lt;code&gt;audioUrl&lt;/code&gt; optional — Play falls back to the transcript), and no Cursor branding in the public brief.&lt;/p&gt;

&lt;p&gt;That honesty is the submission as much as the UI.&lt;/p&gt;


&lt;h2&gt;
  
  
  Two schemas: tape and voice
&lt;/h2&gt;

&lt;p&gt;Content is not files on the host. Stories stay in Sanity. The model is small on purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Document&lt;/th&gt;
&lt;th&gt;Studio title&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;story&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bande&lt;/td&gt;
&lt;td&gt;A tape: title, slug, narrator ref, place, era, transcript (portable text), optional &lt;code&gt;audioUrl&lt;/code&gt;, tags, mood&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;narrator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Narrateur&lt;/td&gt;
&lt;td&gt;A voice: name, short bio (≤280), optional photo with hotspot&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The narrator’s &lt;strong&gt;name lives on the narrator document&lt;/strong&gt;. The story only holds a reference. That keeps voices reusable across bandes and keeps the deck’s display join honest: &lt;code&gt;narrator-&amp;gt;name&lt;/code&gt; in GROQ, not a duplicated string on every tape.&lt;/p&gt;

&lt;p&gt;Mood is a required string from a shared list (the filters on the dial). Era is approximate text (e.g. « vers 1987 ») and is what we sort on. Transcript is required portable text so the machine always has something to roll when there is no audio file.&lt;/p&gt;


&lt;h2&gt;
  
  
  One GROQ string, two sources
&lt;/h2&gt;

&lt;p&gt;Whether the deck reads the Content Lake or the local seed drawer, the projection is the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*[_type == "story"] | order(era asc) {
  _id,
  title,
  "slug": slug.current,
  place,
  era,
  mood,
  tags,
  audioUrl,
  transcript,
  "narratorName": narrator-&amp;gt;name,
  "narratorBio": narrator-&amp;gt;bio,
  "narratorPhoto": narrator-&amp;gt;photo.asset-&amp;gt;url
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That single string is the contract between Studio editors and the strange front end. An empty lake shows an open tray, not a crash. A failed query shows the error and no tapes. Demo mode is labeled — same query shape, seed documents in &lt;code&gt;src/sanity/seed/documents.ts&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Studio at &lt;code&gt;/studio&lt;/code&gt;, then the Lake
&lt;/h2&gt;

&lt;p&gt;Studio is embedded in the Next app at &lt;code&gt;/studio&lt;/code&gt; (Bandes / Voix desk + Vision). The path from vibe-coded demo to a real Content Lake was deliberate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create project + public &lt;code&gt;production&lt;/code&gt; dataset in Sanity Manage.
&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;NEXT_PUBLIC_SANITY_PROJECT_ID&lt;/code&gt; / &lt;code&gt;NEXT_PUBLIC_SANITY_DATASET&lt;/code&gt; (defaults already point at &lt;strong&gt;&lt;code&gt;nh4vx26w&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;production&lt;/code&gt;&lt;/strong&gt;).
&lt;/li&gt;
&lt;li&gt;Editor write token only for seed — never committed.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run seed&lt;/code&gt; → &lt;code&gt;createOrReplace&lt;/code&gt; &lt;strong&gt;4 narrators&lt;/strong&gt; and &lt;strong&gt;8 stories&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Add CORS origins (local + &lt;code&gt;https://k7-memoire.vercel.app&lt;/code&gt;), deploy, open Studio.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Public project ID and dataset are intentional: the deck can read without a token (watch Sanity’s public ACL: &lt;code&gt;path("*")&lt;/code&gt; only matches IDs without dots — our seed uses hyphen IDs like &lt;code&gt;story-radio-agoe&lt;/code&gt;). Write stays server-side for seed only.&lt;/p&gt;




&lt;h2&gt;
  
  
  What “strange” looks like on screen
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fk7-memoire.vercel.app" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fk7-memoire.vercel.app" alt="K7 Mémoire live deck" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Screenshots: seeded deck on live — open the app for the full FM dial + kente chrome.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You do not scroll a feed. You tune. Mood filters narrow the drawer. Play spins the reels and advances a counter while the transcript rolls — or audio plays when &lt;code&gt;audioUrl&lt;/code&gt; is set. The on-screen service manual even prints the GROQ, so the “machine” explains how it listens to the Lake.&lt;/p&gt;

&lt;p&gt;Stack in short: Next.js (App Router) + TypeScript + Tailwind + Sanity Studio (&lt;code&gt;next-sanity&lt;/code&gt;, Sanity v6) on Vercel.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links for judges and readers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Live app&lt;/td&gt;
&lt;td&gt;&lt;a href="https://k7-memoire.vercel.app" rel="noopener noreferrer"&gt;k7-memoire.vercel.app&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Studio&lt;/td&gt;
&lt;td&gt;&lt;a href="https://k7-memoire.vercel.app/studio" rel="noopener noreferrer"&gt;k7-memoire.vercel.app/studio&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sanity project ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nh4vx26w&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dataset&lt;/td&gt;
&lt;td&gt;&lt;code&gt;production&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seeded content&lt;/td&gt;
&lt;td&gt;4 narrators · 8 stories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Origin source of truth&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://cursor.com/codebase/donchaminade/k7-memoire" rel="noopener noreferrer"&gt;cursor.com/codebase/donchaminade/k7-memoire&lt;/a&gt; (private)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Process log&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;PROMPT_LOG.md&lt;/code&gt; in that repo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/Donchaminade" rel="noopener noreferrer"&gt;Donchaminade&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LinkedIn&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.linkedin.com/in/chaminadeadjolou" rel="noopener noreferrer"&gt;chaminadeadjolou&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I’d vibe next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Real family recordings behind optional &lt;code&gt;audioUrl&lt;/code&gt; (consent and quiet UX first).
&lt;/li&gt;
&lt;li&gt;More Lomé places and eras as the Lake grows — still one GROQ contract.
&lt;/li&gt;
&lt;li&gt;A small “donate a tape” flow that creates a draft &lt;code&gt;story&lt;/code&gt; in Studio without breaking the deck metaphor.
&lt;/li&gt;
&lt;li&gt;Vision-assisted queries from the service manual for editors learning GROQ beside the reels.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Strange does not mean unserious. A cassette deck is a joke until it is how your aunt’s voice finds the next generation. Sanity’s schemas, Studio, and Content Lake made that joke into something I can seed, ship, and keep editing from Lomé.&lt;/p&gt;

&lt;p&gt;Thanks to the Sanity Challenge for Path 2 — and to everyone who still presses Play on memory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#sanitychallenge&lt;/code&gt; · nextjs · sanity · africa&lt;/p&gt;

</description>
      <category>sanitychallenge</category>
      <category>nextjs</category>
      <category>sanity</category>
      <category>africa</category>
    </item>
    <item>
      <title>Lignée — A Family Tree Built for Someone I Love (and Generations I'll Never Meet)</title>
      <dc:creator>Chaminade Dondah ADJOLOU</dc:creator>
      <pubDate>Fri, 02 Oct 2026 09:27:11 +0000</pubDate>
      <link>https://dev.to/jwzqeygxtonh/lignee-a-family-tree-built-for-someone-i-love-and-generations-ill-never-meet-23kd</link>
      <guid>https://dev.to/jwzqeygxtonh/lignee-a-family-tree-built-for-someone-i-love-and-generations-ill-never-meet-23kd</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyhz2y0nkt62ywygkhsol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyhz2y0nkt62ywygkhsol.png" alt="Cover" width="799" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Lignée — A Family Tree Built for Someone I Love (and Generations I'll Never Meet)
&lt;/h1&gt;

&lt;p&gt;I did not build this for a portfolio. I built it for my family.&lt;/p&gt;

&lt;p&gt;For the Adjolou and Chamiande lineage — for the people who raised me in Lomé, Togo, and for the children who will one day ask &lt;em&gt;who came before us?&lt;/em&gt; This is my Hacktoberfest Weekend Challenge submission under &lt;strong&gt;Build for a Friend&lt;/strong&gt;. The "friend" is not a stranger on the internet. It is someone I love: my family, including future generations I may never meet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lignée&lt;/strong&gt; (French for &lt;em&gt;lineage&lt;/em&gt;) is an open-source family tree that turns oral family stories into durable digital memory — with open-source AI at the core, a mind-map you can edit on your phone, and a promise that our kinship will not vanish when the last elder who remembers stops speaking.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who it's for
&lt;/h2&gt;

&lt;p&gt;Someone I love is not a single person. In West African extended kinship, "family" is wider than a nuclear unit: grandparents, aunts, uncles, cousins, marriages that braid two names together, in-laws who become &lt;em&gt;our&lt;/em&gt; people.&lt;/p&gt;

&lt;p&gt;I am &lt;strong&gt;Dondah Chamiande Adjolou&lt;/strong&gt;, from Lomé, Togo. Like many families in the diaspora — and many still at home — we carry our history in conversations: around a table, on a phone call, in a funeral speech, in a name whispered to a newborn. That memory is rich. It is also fragile.&lt;/p&gt;

&lt;p&gt;Lignée is for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Elders&lt;/strong&gt; whose stories deserve more than a fading recollection
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parents&lt;/strong&gt; who want their children to know the tree they grew from
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cousins scattered across cities and continents&lt;/strong&gt; who still share one lineage
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future generations&lt;/strong&gt; who will open a phone and see faces and names instead of silence
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a generic genealogy product. It is a gift I intend to hand over — to my family first, and then to anyone who needs the same thing for theirs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem: oral memory is fading
&lt;/h2&gt;

&lt;p&gt;In many African families, lineage is oral. That is beautiful — and it is at risk.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elders pass away, and with them go the precise links: who married whom, which child belonged to which house, how two surnames became one story.
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;diaspora&lt;/strong&gt; stretches kinship across borders. A cousin in Europe and a cousin in Lomé may share blood and still not share a shared map of the family.
&lt;/li&gt;
&lt;li&gt;Young people grow up knowing &lt;em&gt;that&lt;/em&gt; they come from somewhere, without knowing &lt;em&gt;how&lt;/em&gt; the branches connect.
&lt;/li&gt;
&lt;li&gt;Paper notebooks get lost. WhatsApp threads scroll away. A Facebook album is not a tree.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we do nothing, the next generation inherits love without structure — affection without ancestry they can navigate. I did not want my family's story to depend on whoever happens to remember next Sunday.&lt;/p&gt;

&lt;p&gt;I wanted something &lt;strong&gt;durable&lt;/strong&gt;, &lt;strong&gt;editable&lt;/strong&gt;, &lt;strong&gt;installable on a phone&lt;/strong&gt;, and &lt;strong&gt;honest about privacy&lt;/strong&gt; — because family data is not the kind of data you casually hand to a closed cloud.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Lignée does
&lt;/h2&gt;

&lt;p&gt;Lignée is a web app (and a &lt;strong&gt;PWA&lt;/strong&gt; you can install on your phone) that lets a family build and explore its tree as a living mind-map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fti6oi7i9hq4gi46k8q3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fti6oi7i9hq4gi46k8q3p.png" alt="Tree mind-map" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A mind-map of kinship, not a stiff chart
&lt;/h3&gt;

&lt;p&gt;Using &lt;strong&gt;React Flow&lt;/strong&gt;, the tree is a visual graph you can pan, zoom, and rearrange. People are nodes. Marriages, parent–child links, cousins, and in-laws are edges. It feels like thinking on a whiteboard — not like filling a bureaucratic form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Click-to-edit, rich people cards
&lt;/h3&gt;

&lt;p&gt;Tap a person. Open their card. Add or correct a name, dates, notes, relationships. No ceremony — if Auntie remembers a detail at dinner, you fix it in thirty seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwn53i23149pcy4j90k5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwn53i23149pcy4j90k5h.png" alt="Person card" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Relationships that match how we actually live
&lt;/h3&gt;

&lt;p&gt;Nuclear-only trees fail African (and many diaspora) families. Lignée models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Marriages&lt;/strong&gt; and unions that connect two branches
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cousins&lt;/strong&gt; and extended kinship, not only parents and children
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-laws&lt;/strong&gt; — the people who become family by bond, not only by blood
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install it on your phone (PWA)
&lt;/h3&gt;

&lt;p&gt;Family conversations happen on phones. Lignée is a Progressive Web App: install it to the home screen, open it like a native app, and keep the tree close when someone starts telling a story.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fapmwuzckktni7ns32phe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fapmwuzckktni7ns32phe.png" alt="PWA phone" width="799" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Story import — from &lt;em&gt;récit familial&lt;/em&gt; to nodes
&lt;/h3&gt;

&lt;p&gt;This is the heart of the project. You paste (or type) a family story — a &lt;em&gt;récit familial&lt;/em&gt; — and open-source AI helps turn narrative into structured people and relationships. Then you review, correct, and own the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii78urciuvkykjvkz365.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii78urciuvkykjvkz365.png" alt="Story import" width="670" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Home view, shown before opening the tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc7rvph3cr3jk0iziiso2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc7rvph3cr3jk0iziiso2.png" alt="Home screen" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Demo walkthrough (screenshots above):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the tree — see the Adjolou/Chamiande mind-map.
&lt;/li&gt;
&lt;li&gt;Tap a person — edit their card.
&lt;/li&gt;
&lt;li&gt;Paste a short family story — run story import.
&lt;/li&gt;
&lt;li&gt;Review suggested nodes and links — accept what is right, fix what is not.
&lt;/li&gt;
&lt;li&gt;Install the PWA on your phone — take the tree with you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://story-lineage.vercel.app" rel="noopener noreferrer"&gt;https://story-lineage.vercel.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Source (primary public link):&lt;/strong&gt; &lt;a href="https://github.com/Donchaminade/story-lineage" rel="noopener noreferrer"&gt;https://github.com/Donchaminade/story-lineage&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Origin mirror (optional):&lt;/strong&gt; &lt;a href="https://cursor.com/codebase/donchaminade/story-lineage" rel="noopener noreferrer"&gt;https://cursor.com/codebase/donchaminade/story-lineage&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Demo note:&lt;/strong&gt; The Vercel serverless deployment uses ephemeral storage, so demo seed data may reload on cold instances; edits made on a prior instance may not persist.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Open-source AI at the core
&lt;/h2&gt;

&lt;p&gt;I refuse to build a family memory tool that only works if a closed vendor stays friendly, cheap, and online.&lt;/p&gt;

&lt;h3&gt;
  
  
  How story import works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You provide a natural-language family story (French or English — the language of the telling).
&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;open AI&lt;/strong&gt; pipeline (designed for &lt;strong&gt;Ollama&lt;/strong&gt; and local inference, with a &lt;strong&gt;local fallback&lt;/strong&gt;) extracts candidate people, generations, and relationships.
&lt;/li&gt;
&lt;li&gt;The app proposes &lt;strong&gt;nodes and edges&lt;/strong&gt; on the tree.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A human always reviews.&lt;/strong&gt; AI suggests; the family decides.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No magic black box that silently rewrites your lineage. Suggestion, then consent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why open matters for family data
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;Why open-source AI helps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Family names, dates, and stories are intimate. Local inference (e.g. Ollama) keeps data on machines you control.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;No vendor lock-in&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Models and providers can be swapped. Your tree is not hostage to one API's pricing or terms.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local option&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;When the network is weak — or trust is low — local fallback still lets story import run.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inspectability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open models and open code mean the community can audit how narrative becomes structure.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Closed AI might be convenient. For &lt;em&gt;family lineage&lt;/em&gt;, convenience is not enough. &lt;strong&gt;Sovereignty over memory&lt;/strong&gt; is the feature.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I built it (honest technical notes)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; — app framework, routing, and a clean path to a PWA
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — simple, portable persistence; easy to back up; no heavy ops tax for a family project
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Flow&lt;/strong&gt; — interactive mind-map UX (pan, zoom, nodes, edges)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PWA&lt;/strong&gt; — installable on Android/iOS home screens for real family use
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open AI / Ollama + local fallback&lt;/strong&gt; — story import without requiring a single proprietary cloud
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What went well&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React Flow made "kinship as a graph" feel natural quickly — marriages and cousins are just edges with meaning.
&lt;/li&gt;
&lt;li&gt;SQLite kept the data model honest and movable: a family's tree should be something you can copy, backup, and keep.
&lt;/li&gt;
&lt;li&gt;Designing for &lt;strong&gt;phone-first&lt;/strong&gt; editing forced clarity: click-to-edit beats multi-step wizards when an elder is mid-story.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What was hard (and still is)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modeling &lt;strong&gt;extended kinship&lt;/strong&gt; without drowning the UI — African families are dense graphs; the UX has to stay readable.
&lt;/li&gt;
&lt;li&gt;Story import is only as good as the review loop. Hallucinated cousins are worse than missing ones — so the product bias is: &lt;em&gt;suggest carefully, confirm always&lt;/em&gt;.
&lt;/li&gt;
&lt;li&gt;Bilingual reality (French oral culture, English for this challenge write-up and global open source) — the product must respect the language of the &lt;em&gt;récit&lt;/em&gt;, not only the language of the README.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I would improve next&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Richer media on person cards (photos, voice notes of elders telling the story)
&lt;/li&gt;
&lt;li&gt;Stronger conflict resolution when two relatives disagree on a link
&lt;/li&gt;
&lt;li&gt;Export/import formats for long-term archival beyond one app
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was a weekend challenge build with a long-horizon intention. The code is a starting lineage of its own: it will grow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Handing it over — what it means for future generations
&lt;/h2&gt;

&lt;p&gt;When I imagine a child in twenty years opening Lignée, I do not imagine a product demo. I imagine them tapping a great-grandparent's card and reading a note that someone bothered to write down — a marriage that joined Chamiande and Adjolou, a cousin who left and came back, a name that explains their own.&lt;/p&gt;

&lt;p&gt;Oral memory gave us warmth. Digital lineage can give us &lt;strong&gt;continuity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I am handing this to my family as a living gift: editable, installable, private by design, open in its AI so we are not tenants on someone else's memory server. If other families fork it for their own surnames and stories, that is the point of open source — &lt;strong&gt;lineage that multiplies without being owned&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For Hacktoberfest, this is my weekend challenge. For my family, this is unfinished on purpose: trees grow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Overall only.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(This submission does not claim partner tool categories such as Copilot, Cloudflare, Docker, etc., unless those tools were genuinely central to the build. The core stack here is Next.js, SQLite, React Flow, PWA, and open-source AI / Ollama with local fallback.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Demo:&lt;/strong&gt; &lt;a href="https://story-lineage.vercel.app" rel="noopener noreferrer"&gt;https://story-lineage.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository (primary public link):&lt;/strong&gt; &lt;a href="https://github.com/Donchaminade/story-lineage" rel="noopener noreferrer"&gt;https://github.com/Donchaminade/story-lineage&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin mirror (optional):&lt;/strong&gt; &lt;a href="https://cursor.com/codebase/donchaminade/story-lineage" rel="noopener noreferrer"&gt;https://cursor.com/codebase/donchaminade/story-lineage&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Challenge tags (for DEV.to)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;#devchallenge&lt;/code&gt; &lt;code&gt;#weekendchallenge&lt;/code&gt; &lt;code&gt;#hf26challenge&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with care in Lomé's wider story — for the Adjolou/Chamiande lineage, and for anyone who refuses to let family memory evaporate.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
