At my great-grandmother's memorial, the host passed round her photos and asked what people remembered, and nobody could start, although everyone there had stories. Kinlore gives a family a photo and a question to start from. My grandma has already told stories into it on a real iPhone.

Kinlore is a family's shared memory archive, entered for the Next Gen Award. Anyone in the family tells what they remember about an old photo, out loud or in writing, and the AI gives it structure. The memory attaches to the photo and the people in it, the people and places named in the stories are proposed for the family to confirm, and open questions come back to be asked. One family member subscribes through RevenueCat, and the whole family gets the archive.

Two things set it apart. A name the AI heard is checked blind. The app shows the photograph and asks Who is in this photo?, with its own guess unmarked among the family's names. And telling is never paywalled, because the person who tells is often not the one who pays.

My Inspiration

I'm 16 and in my first year of upper secondary school in Finland. In the summer I went to my great-grandmother's memorial. There were about 20 people, including me. I have no memories of her, but I still went there to learn more about her. The host had brought many photos of her. When he asked what people remembered about them, nobody could really start telling a story. I was confused because I was sure that all of them had stories. That's when it clicked. They needed something to start from. It was time for Kinlore. The first idea was just to ask questions, but as I developed the app, ideas flowed, and soon enough I had the whole app structure in my head.

What it does

Tell. One large button. Talk about a photo (or just a story) for as long as you like, or type instead. The recording is kept in the teller's own voice, beside a readable transcript.

It asks back. The app reads a follow-up question aloud and starts listening by itself. One press ends the answer; the app organises it and asks the next one. If nobody speaks for 25 seconds, it keeps what was said and stops asking. The questions get more personal only as the answers earn it.

AI proposes, a human confirms. Names and places come back as proposals, each with the sentence it was heard in. Nothing enters the family tree until a person says yes, because a wrong relationship is worse than a missing one.

"Who is in this photo?" Later, the app shows a family member the photograph a name was heard in and asks Who is in this photo? over three or four of the family's names. The proposal is unmarked among them, so choosing it means looking at the photo rather than agreeing with a name already on the screen. A different answer is never called wrong, because the app doesn't know who is in the photo either.

Vague dates stay vague. "Sometime in the fifties" is stored as a decade, not as an invented date.

Nothing is thrown away. The original audio and the raw transcript are always kept, because the speaker may not be around to ask again. A misheard name can be corrected from the person's card years later.

The whole family. Members join through an invite link (there is no login screen) and tell into the same archive from their own phones. Paper photos can be photographed straight into the archive, and a photo can be coloured using what the family told about it.

English and Finnish. Right now the app works in Finnish and English, but I am planning to add more languages so everyone can save their memories!

Monetisation with RevenueCat

The person who tells is often not the person who pays. So one member buys, and the whole family gets the archive.

A subscription gives the whole family the full archive, with every story written down and sorted as soon as it is told, follow-up questions that keep coming, as many photos as the family has and colour for any of them. The free tier is enough to try Kinlore, with ten minutes of speech written down a month, 20 photos in all and five colourisations a month, counted on the server. Telling is never paywalled, so when the minutes run out a recording is still kept, but it stays only audio. The app stops asking questions back, and no text, names or places come out of it until the next month. Once someone subscribes, the recordings that were waiting are written down the next time the teller's phone opens Kinlore.

An offer of the paid archive appears after one telling in three once there is someone to share it with (until then, the same place invites a family member), never after a telling that proposed names to confirm and never on a grandparent's phone. When the family hits the photo or transcription limit, the offer appears beside it on every phone, the grandparent's too.

RevenueCat is configured with the family member's id as the app user id, so the webhook can find the family without the app being open. The paywall is RevenueCatUI's own view, designed and priced in the RevenueCat dashboard, at $149.99 a year or $39.99 a month, each for the whole family.

Why does a year cost about 69 % less than twelve months? Kinlore is priced for how a family uses it, in a burst. A box of old photos gets told about in a month or two, and that is when the AI does most of its work. The monthly plan is priced to carry such a month, about 17 hours of recorded speech. The yearly plan, about $12.50 a month for the whole family, is the one the paywall selects by default, because an archive is kept for years. There is no trial period, because the free tier never expires.

The server asks RevenueCat what was bought. POST /entitlement/sync asks RevenueCat's REST API what the customer owns and grants the right to the family. A webhook event makes the Worker ask RevenueCat again and apply the answer, so the family's access follows the purchase without the app being open. A unique index keeps one purchase to one family.

Purchases run on the RevenueCat Test Store, because Kinlore has no App Store release. Judges can try a purchase with the Test Store key in Additional info, using ./scripts/try-it.sh --paywall.

How I built it

iOS. SwiftUI with an XcodeGen project. It is local-first, so the archive lives on the phone and syncs.

Backend. A Cloudflare Worker, with D1 for metadata and R2 for photos and audio.

AI. The models are called only from the Worker through OpenRouter, so no API key ships in the app. Gemini 3.6 Flash transcribes and extracts the structure, with GPT-4o-mini as the extraction fallback, and a Gemini image model colours photos. Every request sets data_collection: "deny", so the family's memories don't train a model.

One data model. A single subject table covers photos, people, places and events, and a memory attaches to any of them. "Tell us about this photo" and "tell us what grandmother was like" are the same screen and the same code path.

Privacy. Memory text, transcripts, titles, photos and audio are sealed on the phone before they sync, and the key never reaches the server. It is not end-to-end, because place coordinates, member and family names, dates and the shape of the tree are not sealed. A recording has to reach a model to be written down, and the app says so before anyone starts.

Accessibility. Every screen is built to work at the largest text size and with VoiceOver, and colours are measured for contrast. There are 406 UI tests, and 127 of them are accessibility sweeps that audit a screen at the default and the largest text size, where body text is about three times its default size.

Challenges I ran into

Finnish speech recognition. Before building the app I measured five speech engines on synthesised Finnish speech. The best got only about two Finnish proper nouns in three right (65–68 % against my own 80 % bar). On 1 October I measured it again on the same synthesised speech, through the app's own server and prompt. This time 89 % of the names came out right in clean speech, 72 % with room noise, and 28 % when the voice was also quiet and muffled, where the model wrote a fluent, different story instead. I kept the concept because the app is built around that weakness. The audio is always playable, the raw transcript is kept, the teller checks names right after telling, and any name can be corrected later.

"Done" that wasn't. Several features looked finished and weren't. There was a transcription waiting for text nothing was sending, a deletion the client never sent, a rate limit that existed only in the docs, and an accessibility audit that measured the wrong screen and passed. In every case the app looked as if it worked. Now each of those promises has a script that checks it, and ./scripts/verify.sh runs them all.

Cutting scope. I built a guessing game, where the family guesses who a story is about, and cut it to protect the core. Its best idea came back as the blind Who is in this photo? card.

Time. I built the hardest part, turning a spoken story into structure, in the last two weeks of the summer holiday, and the rest alongside starting upper secondary school.

Accomplishments that I'm proud of

A real teller. My grandma spoke into the production build on a real iPhone. At first she couldn't believe I had built this :D Then she started testing it, and I was so happy that she was able to tell cool stories that I could also listen to any time. One thing she asked was "How do I know it's saved?", so now the app says so while it waits. She also asked what she should say, which is what the photo and the questions are for. I asked her to speak louder, but as far as I could tell, the app still usually caught everything she said. Still, I wanted it to be clear, so now the Tell screen says "Talk at your own pace, and speak up" before the button is pressed.

The blind confirmation. It is the one confirmation that can't be tapped through without reading, and a test walks every element on the card to check that nothing gives the answer away, the photo's VoiceOver label included.

The largest text size. On the result screen at the largest accessibility size, nothing is clipped or truncated; the screen gets longer instead.

A purchase verified end to end. On a Test Store key, a test purchase reached the family's entitlement, and an authenticated RevenueCat webhook reached the deployed Worker.

Proud that I didn't give up through the ups and downs.

I am really proud of the demo video. None of its app screens is a mock-up. They are recordings of the real app in the iOS Simulator, and the transcripts, the follow-up question, the story and the colours come from its real AI pipeline, with the waits shortened. Its voices and photographs are synthetic stand-ins, because a real family's recordings and photos are private, and I chose not to publish my own voice. My grandma's own test was on a real iPhone.

What I learned

  • From my last app. Before Kinlore, a couple of others and I built Taitoiza, an app that turns a photo of a textbook page into flashcards and quizzes. At Uskalla Yrittää, Finland's national Junior Achievement company final, in April 2026, it won the Tulevaisuuden ratkaisija (Future Solver) award but not the main prize. What I took from it is that testing with real users matters more than anything else, and that an app people agree is good but don't keep using has still failed. So I tested Kinlore with my grandma, and I kept telling effortless for the person doing it, with no login, one button, questions asked out loud so there is nothing to operate, and never a paywall in front of telling.
  • Sleep. While building Taitoiza, I was in my last year of middle school. I wanted to get into a good upper secondary school, and at the same time I wanted to build the app all the time, so I was really tired by the time the summer holiday started. That's why I learned to prioritise sleep more.
  • To measure before believing, and to write down the numbers that came out badly.
  • When the payer and the user are different people, the monetisation has to follow the family, not the buyer.

What's next for Kinlore

  • A one-tap thank-you a reader sends the teller, so whoever told a story knows it was heard. No counts and no badges.
  • Reporting and blocking, which the App Store requires of apps where people share content, and then an App Store release when possible.
  • An Android app. The archive syncs through the server, so the iPhone app is only its first client.
  • Optional account recovery for paying members with Sign in with Apple, never as a login wall.

Built With

Share this project:

Updates

Submission history