This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend
What I Built
My dad remembers the thing.
He just doesn't always remember where it came from ๐ฅฒ or what he still needed to do about it.
A society payment. An AC offer. A quotation someone sent as a PDF. A document buried somewhere in a family WhatsApp chat.
The information exists.
Finding it again is the problem.
So I built FollowUp for him.
FollowUp turns buried conversations into things you actually need to act on.
FollowUp is a private-first AI memory assistant that turns scattered messages, notes, documents, and screenshots into something you can actually ask questions about.
You can ask things like:
- "When is the society payment due?"
- "Who sent me that AC offer?"
- "Where did I get that quotation?"
- "What payments do I need to make?"
- "What am I forgetting?"
But FollowUp isn't designed to just give you an answer.
It shows you the source behind the answer.
If FollowUp tells you that the society maintenance is โน4,800 and due on 7 October, you can open the result and see the original message, sender, group, and date that the answer came from.
That makes the result traceable instead of just another AI response.
The feature I built specifically for my dad
The most interesting part ended up being "What am I forgetting?"
Instead of requiring my dad to remember the right question, FollowUp looks through imported memories for things that appear actionable:
- payments
- renewals
- requests
- offers
- deadlines
It turns those buried messages into actionable cards.
For example:
SOCIETY MAINTENANCE
โน4,800
PAY BY 7 October 2026
Click it, and FollowUp opens the original message that caused it to appear.
So the loop becomes:
find the thing โ understand why it matters โ verify where it came from
For the public demo, I use synthetic memories rather than uploading my dad's private conversations.
Demo
Live Demo: https://hacktoberfest-followup-peach.vercel.app/
The demo is built around the actual problem rather than a generic chatbot flow.
- Open the demo.
- Click Load demo Dad data.
- Open "What am I forgetting?"
- See payments, requests, and offers surfaced from the imported memories.
- Click an actionable item.
- Inspect the exact original source.
- Ask a natural-language question such as:
- "Who sent me the AC offer?"
- "When is the society payment due?"
- "Where did I get the quotation?"
- Get a grounded answer with the supporting memories.
The public deployment currently starts with an empty browser memory store by design. The demo data is loaded explicitly so nobody's private history is part of the public deployment.
Code
GitHub: https://github.com/maitri-vv/FollowUp
The project is built with:
- Next.js
- React
- Transformers.js
- Gemma 3 270M IT
- browser-side WASM inference
- IndexedDB
- semantic + lexical retrieval
- optional Backboard RAG
The repository contains the ingestion/parsing logic, retrieval pipeline, local Gemma inference, actionable-memory detection, source tracing, and optional Assisted Mode.
How I Built It
The main constraint was simple:
AI shouldn't be a chatbot bolted onto the product. It should be part of how FollowUp works.
The core architecture looks like this:
WhatsApp exports / notes / documents
โ
Local ingestion
โ
Chunking
โ
Embeddings + retrieval
โ
Local open-weight Gemma
โ
Grounded answer + sources
1. Importing memories
FollowUp turns imported information into structured memories containing things such as:
- source
- sender
- group
- date
- category
- original message
WhatsApp exports can be parsed into individual messages so they can be retrieved independently.
The public demo also includes synthetic Dad memories so the entire flow can be tested without using real personal data.
2. Retrieval
FollowUp uses both semantic retrieval and lexical matching.
Semantic retrieval helps when the question and the original message use different words.
Lexical matching helps preserve exact information such as:
- names
- dates
- amounts
- "pay"
- "renewal"
- "quotation"
- "before Friday"
The results are combined before the answer layer sees them.
This matters because personal-memory search isn't just a keyword problem.
If my dad asks:
"Who sent me that AC thing?"
the useful memory might actually say:
"Voltas AC service package at the festival offer price."
Semantic matching helps connect those ideas, while lexical matching protects the exact details.
3. Gemma runs locally
The open-weight model at the core of FollowUp is Gemma 3 270M IT.
I run it through Transformers.js using browser-side WASM inference.
That gives FollowUp a local inference path without requiring a hosted LLM for Private Mode.
The model receives retrieved context and generates an answer from that evidence.
I also added a deterministic grounded-answer layer for common memory tasks such as payments, senders, locations, and actionable items.
That makes common queries faster while still keeping Gemma available as the general language layer.
4. Grounded answers
FollowUp is deliberately conservative.
The retrieval layer provides the evidence.
The answer layer is instructed to answer from that evidence rather than inventing missing details.
If the available memories don't contain enough information, FollowUp should say so.
And when an answer is produced, the user can inspect the underlying memory.
For a personal-memory product, I cared more about:
"Show me why you think that."
than making the assistant sound confident.
5. "What am I forgetting?"
This is where retrieval becomes more than a search box.
FollowUp identifies imported memories containing actionable signals such as:
- payment amounts
- due dates
- renewal dates
- requests
- offers
- deadlines
It extracts the relevant action and date and presents those memories as cards.
For example:
PAYMENT
Society maintenance
โน4,800
PAY BY 7 October 2026
Society Admin ยท Green View Society
The card is clickable, so the user can immediately inspect the evidence behind it.
6. Optional Assisted Mode
FollowUp also has an optional Assisted Mode using Backboard.
In this mode, retrieved memories can be sent to Backboard for hosted RAG assistance.
I deliberately kept this separate from Private Mode.
Private Mode is designed around keeping imported memories in the browser and running the open-weight model locally.
Assisted Mode is an explicit choice to use hosted assistance.
I also added deduplication to the Backboard memory sync so repeatedly syncing the same imported memories doesn't blindly create duplicates.
What I Tested
I tested FollowUp with a synthetic WhatsApp conversation containing realistic examples of the problem:
- a โน4,800 society maintenance payment
- an AC service offer from Rajesh
- a quotation sent as a PDF
- an electricity bill request
- a bank statement sent in a family chat
- an LIC renewal reminder
- repeated references to the same offer and quotation
The import worked, and the main natural-language queries returned the expected information.
The important test wasn't simply whether an AI model could answer a question.
It was whether FollowUp could answer the question and let me trace the answer back to the original memory.
That source trail is the part I wanted to build for my dad.
Why Does Open Innovation Matter?
FollowUp deals with exactly the kind of information people may not want to send to a third-party AI service:
family conversations, reminders, documents, payments, and personal history.
That made the choice of open-weight AI more than a technology preference.
FollowUp's Private Mode can run its language model locally in the browser through Transformers.js.
The basic path is:
Personal memories
โ
Browser
โ
Local retrieval
โ
Local Gemma inference
โ
Answer
A hosted LLM isn't required for that core path.
That gives the product a different privacy boundary from a design where every personal memory has to be sent to a remote model before it can be useful.
It also gives me control over the model layer.
I can experiment with different open models, change the inference setup, change the retrieval strategy, and keep the application architecture under my control.
There is a tradeoff.
Running a model locally in the browser is slower than calling a large hosted model.
But for FollowUp, that tradeoff is meaningful.
If I'm building something whose job is to help remember personal conversations, I don't want uploading an entire history to a closed API to be the default requirement.
Open innovation made the privacy-first version of FollowUp possible.
My Agent Session
I used DevRelay during the submission workflow to inspect the project, verify the live Hacktoberfest Weekend Challenge requirements, and prepare this submission.
The curated agent session is publicly available here:
Prize Categories
Best Use of Gemma
FollowUp uses Gemma 3 270M IT as its open-weight language model, running locally through Transformers.js and WASM.
Gemma is part of the core Private Mode architecture rather than being used only as a separate chatbot feature.
Best Use of Backboard
FollowUp also uses Backboard for its optional Assisted Mode.
Backboard provides the hosted RAG path while FollowUp keeps its local/private path separate.
I built FollowUp for one person because one person's annoying everyday problem was enough.
My dad didn't need another chatbot.
He needed to stop asking:
"Where did I get that?"
So I built something that could help him find it and remember what he needed to do about it.

Top comments (0)