Inspiration

Family stories rarely arrive as complete stories. Someone remembers a street they grew up on, a neighbour’s name, or a sound from their childhood. Those details can lead to a much bigger conversation, but they are also easy to lose if nobody asks about them or writes them down.

We wanted to build something that makes those conversations easier to start and easier to return to. Asking someone to “tell us your life story” can feel overwhelming. Answering one small question is a more manageable beginning.

That became the idea behind StoryKeeper: help a family member share memories in short interviews, preserve the original answers, and gradually organise them into a family history. We also wanted the person sharing those memories to remain in control. A family story can be personal, uncertain, or something they are not ready to share. Saving an answer should not automatically make it visible to everyone else.

What it does

StoryKeeper connects two parts of the experience: sharing a memory and discovering it later.

The storyteller answers guided interview questions. Their answers are saved before any extraction or review takes place. Prepared memories and timeline entries can then be reviewed, along with their source information and dates.

The storyteller approves each item separately before it becomes available through family search and the approved timeline.

Our demonstration follows Rosa and Maya, a fictional family used for testing. Rosa remembers growing up beside the old market, around 1974, and a garden gate that squeaked in the evening breeze.

She saves that answer, reviews the resulting memory and timeline entry, checks their source, and approves both. Maya can then search for “garden” and find the approved items.

A few details matter in that sequence:

The original answer remains saved. Source information stays available during review. “Around 1974” remains an approximate date. The memory and timeline entry require separate approvals. Pending items do not appear in Maya’s family search.

The goal is to make memories easier to preserve and find while keeping the storyteller’s decisions visible throughout the process.

How we built it

We built StoryKeeper with a TypeScript backend, a web interface, and an MCP server intended to support an Alexa+ integration.

The backend uses Node.js, SQLite, and Drizzle for the application’s data and persistence. SQLite FTS5 supports keyword search. The MCP layer exposes application operations through tools so a compatible client can interact with the underlying workflow.

We separated saving an interview answer from processing it. An answer can be stored successfully even when extraction is disabled or has not finished. A background extraction workflow prepares items for review, while approval determines whether those items become available to the family.

We used AI coding tools during development to help implement, inspect, and debug the project. We still had to check the resulting behaviour ourselves, particularly where persistence, review states, and family visibility were involved.

For the presentation, we used Remotion to build the animated walkthrough, ElevenLabs for narration, and sound effects aligned with the interactions. The video uses reconstructed interfaces to make the workflow readable without requiring viewers to follow a full desktop recording

Challenges we ran into

One of the harder decisions was defining what should happen between an answer being saved and a memory becoming part of family history.

It would have been simpler to show extracted content immediately in search. We wanted an explicit review step instead. That meant treating a saved answer, a pending memory, and an approved item as different states, then checking that the interface and search respected those differences.

Dates were another concern. A person might remember an event as happening “around 1974.” Turning that into an exact date would make the result look more certain than the original answer. We kept that uncertainty visible.

We also had to distinguish application behaviour from AI behaviour during testing. With the default AI providers disabled, answers saved correctly but extraction stayed queued. Using the existing mock provider allowed us to exercise the extraction worker and continue through review, approval, and discovery without claiming that a live model had produced the content.

The demo itself took several iterations. Reproducing the whole interface made the video harder to read, while adding too much animation distracted from the workflow. We settled on large text, paper-based visual elements, focused interactions, and a continuous story.

Accomplishments that we're proud of

We’re proud of getting the central journey working from start to finish: saving an interview answer, reviewing the resulting items, approving them separately, and finding them from another family member’s view.

One of our most useful checks was simple: Maya’s search for “garden” returned no results before Rosa’s approval and two results afterwards. That gave us concrete evidence that the approval step affected what the family could discover.

We also preserved details that could easily have been lost during processing. The original answer remained saved, the review items included source information, and “around 1974” stayed an approximate date rather than becoming an exact one.

This journey was tested locally with mock-assisted extraction. Live model quality and Alexa voice behaviour still need separate verification, but we established a working foundation for saving, reviewing, and discovering memories.

We’re also pleased with the demo we created. It took several revisions to explain the workflow clearly while keeping the presentation warm and visually engaging.

What we learned

We learned that preserving a memory involves more than saving text or generating a summary. A useful record also needs context: where it came from, how certain its details are, and whether the storyteller wants to share it.

Separating saved answers, pending review items, and approved memories made us think carefully about each step. An answer being saved successfully should not depend on extraction finishing, and extracted content should not automatically become shared family history.

Testing the complete journey taught us more than checking individual operations alone. We needed to see what happened from both Rosa’s and Maya’s perspectives to understand whether approval and discovery worked together.

We also learned to distinguish what we had implemented from what we had verified. Mock extraction helped us test the surrounding workflow consistently, but it could not establish how well a live model would interpret someone’s memories.

Creating the video brought another lesson: showing every part of an interface does not necessarily make a product easier to understand. Focusing on one continuous story helped us explain the decisions that mattered.

What's next for Family Story Keeper

Our first priority is to connect and test live extraction with a wider range of interview answers. We want to check how it handles incomplete memories, uncertain dates, names, and conflicting details while keeping the original answer available for review.

We also need to complete the Alexa+ voice integration and verify the experience through an actual supported setup. Local MCP testing was a useful step, but the intended voice experience still needs to be built and tested.

Another priority is testing with people outside our team, especially the relatives who might share their stories. We want to understand whether the questions are comfortable to answer, whether review feels manageable, and whether it is clear what approval makes visible to the family.

After that, we plan to evaluate the chapter-drafting workflow and improve how approved memories are organised into longer stories. Any generated draft should remain something the storyteller can review and correct.

The goal is to make StoryKeeper useful for more than one successful demonstration: a place families can return to, one conversation at a time.

Built With

Share this project:

Updates

Submission history