## Inspiration

Family history is often built from incomplete memories: one person remembers a year, another remembers a place, and an old photograph suggests something different. Most software tries to resolve these differences into one clean answer.

Memoir Canvas takes the opposite approach. It makes uncertainty visible and gives the final decision back to the family.

Every memory appears as a firefly in a moonlit meadow. Green means the story has been told, orange means sources conflict, and white means there is an empty place waiting for someone to contribute. Opening a memory reveals a book-like page where recollections and evidence remain visible together.

The project was inspired by a simple principle:

An AI must not turn a guess into a fact.

## What I learned

The most important lesson was that trustworthy AI behavior cannot depend only on instructions or prompts. If the system truly must not invent certainty, that rule needs to exist below the model.

Memoir Canvas uses database constraints, PostgreSQL roles, deferred constraint triggers, and a shared command layer to enforce this boundary. An agent can add memories, cite sources, detect conflicts, and propose follow-up questions. It cannot resolve a contradiction by itself.

I also learned that uncertainty can be part of the user experience rather than something hidden in metadata. The open conflict becomes a physical tear in the page, and the book refuses to close until a person resolves it. The interface makes the epistemic state understandable without requiring the user to inspect a database.

## How I built it

Memoir Canvas is a local-first Vite and React application. A real PostgreSQL-compatible database runs inside the browser through PGlite and is persisted in IndexedDB. No application server, account, or runtime API is required.

The architecture has one write door:

  • Human controls and agent tools both call src/domain/commands.ts.
  • Only the command layer writes to the database.
  • Every write and audit event happens in the same transaction.
  • The view renders a read-only projection from the store.
  • WebMCP tools are generated as a pure function of the current UI state.

The app exposes eight WebMCP tools:

read_memory_graph, add_person, add_memory_claim, link_claim_to_source, flag_conflict, propose_followup_question, resolve_claim, and generate_story_card.

The tool list changes depending on what the person is viewing. In particular, resolve_claim only becomes available when a human has opened a specific conflict. Even then, an agent calling it is refused by the database because only a human can provide the confirmation.

The central demonstration follows one family story:

  1. An oral account says Grandma moved to Đà Nẵng around 1972.
  2. A photograph is dated 1974.
  3. The sources are linked as contradictory.
  4. The page tears and cannot turn.
  5. The agent proposes a follow-up question.
  6. A family member opens the conflict and confirms the correct year.
  7. The tear heals and the story card carries the weakest certainty of the claims it contains.

Story cards are bilingual, with Vietnamese and English content, so the archive remains useful to the family while still being understandable to English-speaking judges.

## Challenges

The hardest challenge was preserving the same safety guarantees across both human and agent interaction. It would have been easy to give the agent a separate shortcut, but that would make the human-facing safeguards meaningless. Both paths now use the same command functions and database constraints.

Another challenge was representing conflict visually without making the interface feel like a dashboard. The project moved from a conventional panel layout to a book and meadow metaphor: pages turn by gesture, conflicts split the book, and memories appear as lights in the landscape.

Browser portability was also important. The app must work in embedded webviews where WebGL or WebMCP may be unavailable. The forest has a CSS fallback, the photographs are processed locally through EXIF metadata, and the core interactions remain accessible through keyboard navigation.

The final result is an archive that helps an AI participate in family history without allowing it to decide what the family remembers

Built With

Share this project:

Updates

Submission history