DEV Community

Cover image for What if your journal could understand you? So I built DayBook
Jesus Chetia
Jesus Chetia

Posted on AI-assisted

What if your journal could understand you? So I built DayBook

Hacktoberfest Weekend Challenge: Build for a Friend Submission 🤝

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend

This is a team submission
Teammate - @piyushnextgen

What We Built

Daybook began with a simple problem: a friend of ours who was already journaling, but most of the time, the entries just stayed there.

He could write about a stressful day, a productive week, a bad habit, or something that kept coming up, but noticing those patterns across dozens of entries was almost impossible manually.

So we built Daybook for him.

Daybook is a private AI journal that reads your entries locally and helps surface patterns in your habits, mood, routines, and thoughts over time. Instead of just storing what you write, it helps you understand what keeps showing up.

The important part is where this happens.

Your journal never needs to leave your device. Daybook uses a local LLM, so the AI can work with your personal entries without sending them to a cloud AI service.

We wanted to build something that was genuinely useful to one person, while also answering a question we kept coming back to:

Can AI be helpful with something as personal as journaling without requiring you to give away your data?

Daybook is our attempt at an answer.

Demo

DayBook UI Demo

Note: Local AI features are not available in the deployed demo because DayBook runs AI locally using Ollama. The backend requires a running Ollama instance on port 11434.

Video Demo

Code

GitHub logo greenbugx / Daybook

A private AI journal that learns your habits, finds patterns, and helps you improve, powered by a local LLM with your data staying on-device.

DayBook logo

A local-first AI journal that learns your habits, finds recurring patterns, and helps you reflect on what you could improve

Everything happens on your own machine. Your writing never leaves your computer, and the AI that reads it runs locally through Ollama, so there is no account to create, no key to paste, and no company holding a copy of your thoughts.

Table of Contents

Screenshots














Home Journal Spread
Home screen Journal spread














Analytics Goals
Analytics Goals














Calendar Library
Calendar Library

What DayBook Does

DayBook is built around a few simple habits that turn into something useful over time.

Write a page a day. Each date has one journal entry with a topic…




How We Built It

We wanted Daybook to be useful with genuinely personal data, which made the usual "send it to an AI API" approach feel wrong for this project.

So we built it local-first from the beginning.

At the core is Gemma 3 4B, an open-weight model running locally through Ollama. There is no OpenAI API, Gemini API, or hosted AI service sitting between the journal and the model.

The whole stack lives on the user's machine:

flowchart LR
    U["You, in a browser"] -->|"localhost:5173"| V["Vite dev server"]
    V -->|"React app"| U
    V -->|"proxies /api to 3001"| B["Fastify backend"]
    B -->|"SQL, WAL mode"| D[("SQLite<br/>data/daybook.db")]
    B -->|"local HTTP"| O["Ollama"]
    O --> G["Gemma 3 4B"]

The frontend is built with React 19 and TypeScript, while the local backend handles application logic and communication with Ollama. Journal data and personal memories are stored locally using SQLite.

That separation was intentional. The application can use an LLM for things like identifying recurring habits, finding patterns across entries, and pointing out areas for reflection, while the actual data stays on the same machine.

When a user asks Daybook to analyze their journal, the request stays within that local stack:

Journal → Backend → Ollama → Gemma → Analysis → Daybook

That's what allows Daybook to look for recurring habits, patterns, wins, struggles, and areas for improvement without requiring a cloud AI API.

To run Daybook, we only need three local processes:

  • React + TypeScript for the interface
  • Local backend for application logic
  • Ollama + Gemma 3 4B for AI analysis

No API key required

What Daybook Can Actually Do

  • Daily entries with topic, mood, weather, location, and a rich text editor
  • Goals tied to a date, so you can see what you meant to do next to what you wrote about
  • A reflection chat where you ask in plain language and get an answer grounded in your actual entries
  • Per entry observations the AI generates after you save
  • Memory suggestions you approve or dismiss, so nothing is remembered without your say so
  • A streak that counts unbroken days honestly
  • One image per entry, stored as a real file on your disk
  • Saved quotes collected in a Library
  • A profile built through onboarding that shapes how reflections are written

The AI is grounded, not creative

This was the part we spent the most time on. A journal AI that invents things is worse than useless, because you cannot trust what it tells you about your own life.

The system prompt carries 18 explicit rules. The model is told that its only source of truth is the context handed to it, that it must never invent entries, dates, goals, or statistics, that it must separate a one time observation from a recurring pattern, and that it must say plainly when there is not enough evidence. It is also told to avoid diagnosing anything about mental or physical health, and to respect a thingsToAvoidAssuming list the user fills in during onboarding.

Eight reflection intents decide how the model reads the context:

Intent Looks for
RECURRING_PATTERNS The same thing showing up again
MOOD_EMOTIONAL Mood and emotional tone
STRUGGLES What keeps getting in the way
WINS_PROGRESS Wins, progress, momentum
GOALS Goal follow through
HABITS_ROUTINES Routines and timing
CHANGE_OVER_TIME How things shifted over time
SELF_UNDERSTANDING What Daybook knows about you

Questions that never reach the model

We route every question before it costs anything.

If a question can be answered from the database, Daybook answers it with SQL and skips the model entirely. Ask how many entries you have written, or what your goals are, and you get an exact answer instantly. Only questions that genuinely need interpretation go to Gemma.

flowchart TD
    Q["Your question"] --> ROUTE["classifyAiIntent"]
    ROUTE -->|"quote"| DQ["Return today's quote"]
    ROUTE -->|"streak"| DS["Return the streak"]
    ROUTE -->|"goals"| DG["Read goals from SQL"]
    ROUTE -->|"journal"| DJ["Read entries from SQL"]
    ROUTE -->|"reflection, or anything else"| LLM["Ask Gemma"]
    LLM --> INTENT["classifyReflectionIntent"]
    INTENT --> CTX["buildAiContext<br/>entries, goals, profile,<br/>stats, memories, observations"]
    CTX --> PROMPT["buildAiSystemPrompt<br/>18 grounding rules plus context"]
    PROMPT --> RUN["Ollama generates the answer"]
    RUN --> OUT["Answer with its intent label"]

This keeps answers exact where exactness matters, and spends model time only where interpretation is actually needed.

The streak is not AI

The streak is plain arithmetic over your entry dates. It converts dates to day numbers, ignores the future, returns zero unless you wrote today, then counts backwards while days are unbroken. If you skip a day, it ends there. No model, no guessing, no being generous with dates.

High-Level System Architecture

flowchart TB
subgraph USER["User Machine - 100% Local"]
  BROWSER["Browser<br/>localhost:5173"]
  subgraph FRONTEND["Frontend - React 19 + TS + Vite + Tailwind 4"]
    APP["App.tsx<br/>Routing and shared state"]
    VIEWS["Views<br/>InteractiveBook / JournalBook<br/>Calendar / Goals / Library<br/>AnalyticsAI / Settings / Onboarding"]
    APICLIENT["lib/api.ts<br/>Typed fetch wrapper for /api/*"]
  end
  subgraph BACKEND["Backend - Fastify :3001"]
    ROUTES["REST API<br/>users / journals / goals<br/>quotes / memories / ai/*"]
    ZOD["Zod Validation"]
    CONTEXT["buildAiContext()<br/>entries + goals + memories + profile"]
    AILOGIC["Intent routing and<br/>grounded prompt building"]
  end
  subgraph DATA["Data Layer"]
    DRIZZLE["Drizzle ORM"]
    SQLITE["SQLite<br/>better-sqlite3<br/>data/daybook.db<br/>WAL + foreign keys ON"]
    FILES["data/media/<userId>/<date>/<id>.png"]
  end
  subgraph AI["AI Layer - Ollama :11434"]
    OLLAMA_SDK["ollama npm SDK<br/>format json, temp 0.4"]
    GEMMA["Gemma 3:4b"]
  end
end
BROWSER --> APP --> VIEWS --> APICLIENT
APICLIENT -- "/api/* via Vite proxy" --> ROUTES
ROUTES --> ZOD --> DRIZZLE --> SQLITE
ROUTES --> CONTEXT --> AILOGIC --> OLLAMA_SDK --> GEMMA
ROUTES --> FILES

Using an open-weight model also meant we weren't locked into one AI provider. The model can be changed, experimented with, or eventually customized without redesigning the entire product around a proprietary API.

For a journal, where the data can be deeply personal, local inference isn't just a technical choice. It is part of the product itself.

Data model

Twelve tables, with foreign keys turned on so deleting an entry cleans up its goals, media rows, and observations in one step.

erDiagram
    users ||--o| user_profiles : has
    users ||--o{ local_sessions : opens
    users ||--o{ journal_entries : writes
    journal_entries ||--o{ journal_goals : contains
    journal_entries ||--o| journal_media : illustrated_by
    journal_entries ||--o{ journal_observations : analysed_by
    journal_entries ||--o{ memories : may_seed
    quotes ||--o{ saved_quotes : saved_as

Details we are proud of

Ownership is decided on the server, every time. No endpoint accepts a user id, an entry id, or a file path from the client. Each request resolves the active local session, finds that user's entry for the requested date, then works only with the media and goals hanging off it.

Images are safe by construction. Files are named with a server generated UUID, so your original filename never reaches the filesystem. Every path is built from your user id and the date you asked for, and any path resolving outside the media folder is refused. We tested a ../../../../etc/passwd payload and it landed on a UUID filename inside the media root like any other upload.

A photo failure never costs you your writing. The journal text is saved first. If the image fails afterwards, your text stays saved, your preview stays visible, and you get a clear error instead of a false success.

Date changes cannot leak content. Opening a date fires four requests in parallel, each carrying an AbortController. Switch to October 5 while October 4 is still loading and the stale reply is discarded, so October 4 can never appear on October 5.

Tech Stack

Layer Technology Port / Location
Frontend React 19, TypeScript, Vite 8, Tailwind CSS 4, shadcn/ui, Lucide :5173 · src/
Backend Fastify 5, Zod 4, Drizzle ORM, tsx :3001 · server/src/index.ts
Database better-sqlite3, Drizzle Kit data/daybook.db
AI Ollama, Gemma 3 4B, Ollama npm package :11434
Development pnpm, Ollama Local

Running Daybook

Ollama → Backend (:3001) → Frontend (:5173)
  ↓
Gemma 3 4B

ollama serve
ollama pull gemma3:4b

cd server
pnpm dev

# In another terminal
pnpm dev
Enter fullscreen mode Exit fullscreen mode

Requires Node.js 26 or newer, pnpm, and Ollama.

Why Does Open Innovation Matter?

For Daybook, open innovation wasn't just about using a different AI model. It changed what we were comfortable building in the first place.

A journal is full of things you probably wouldn't want sitting on someone else's servers. Thoughts, bad days, habits, goals, personal memories. We wanted Daybook to actually analyze that information without making the user choose between useful AI and privacy.

Using an open-weight model like Gemma 3 4B made that possible.

Using Gemma 3 4B through Ollama gave us a way to do that. The model runs locally, so in our setup, the journal and its AI analysis can stay on the user's machine without requiring a third-party AI API or API key.

And that's where open models became more interesting to us than just being a cheaper alternative.

We can run the model locally through Ollama, keep the journal and its analysis on the user's machine, and build around the model without depending on a third-party AI API or API key.

It also gives us something a closed API doesn't: control.

We have control over what runs, where it runs, and how we build around it. We can experiment with different models, swap them out, run the system offline, and eventually customize the model for the kind of reflection Daybook needs.

For us, that control matters because of the kind of data we're working with.

It's that we could build an AI product around data we don't want to send anywhere in the first place.

For us, that's the real promise of open innovation: it lets developers decide where AI runs, what it sees, and how the system is built around it.

That's what it meant for Daybook.

My Agent Session

DayBook: Making the Beautiful UI for people's journal
You

Implement the FIRST-TIME PERSONAL ONBOARDING UI for DayBook. The goal is to create a beautiful, calm, journal-like onboarding experience when an existing local user has onboardingCompleted === false. The onboarding should collect personal information DayBook will later use to personalize journal analysis and AI responses. Follow the existing DayBook theme (calm, personal, warm, minimal, editorial, journal-inspired).

Agent

Created OnboardingView.tsx with a 7-step calm, editorial questionnaire reflecting DayBook's visual identity:
- Steps for current focus, personal bio, habits/motivators, known struggles, ideal day, reflection style (Gentle, Balanced, Direct), and things to avoid assuming.
- Integrated seamlessly with FirstRunRegistration and InteractiveBook flow so first-time users see it prior to opening the journal spread.
- Data structured for profile update with zero local storage hacks or database schema alterations.

You

Some fix in Journal: the Bold, Italic, and Underline tool is not working properly. Check it out and fix it.

Agent

Investigated the contenteditable formatting mechanism in OpenJournalSpread.tsx:
- Added proper selection restoration and inline style dispatching (journal-style-sync).
- Ensured bold, italic, and underline commands toggle reliably across selected ranges and update toolbar highlight states.

You

The GOALS and Observations 'Daybook noticed' overlaps when Daybook noticed has many things to show. Can you fix that, make both of them cleanly scrollable and not overlapping each other?

Agent

Updated the left page layout in OpenJournalSpread.tsx:
- Configured Today's Goals and DayBook Noticed containers with flex-1 min-h-0 overflow-hidden and inner overflow-y-auto scrollbar-none.
- Added subtle section dividing borders and bounded max heights so neither section pushes or overlaps the other.

You

Collapse this mood selections to a drop down selection, so goals and Daybook Noticed gets good space.

Agent

Collapsed the 14-button mood selection grid into an inline dropdown menu in OpenJournalSpread.tsx:
- Added dropdown trigger displaying the active mood emoji, title, and chevron.
- Implemented floating popover menu with 2-column layout and click-outside dismissal.
- Freed up vertical space, providing ample room for Goals and DayBook Noticed.

DayBook: Core Backend Architecture, Local AI Reflections, and Persistence
You

Review the DayBook codebase and implement the next persistence phase: Journal Goals. The goals need a dedicated SQLite table with foreign keys to journal entries, REST endpoints for CRUD operations, and full UI integration.

Agent

Implemented Journal Goals persistence end-to-end:
- Created journal_goals schema in Drizzle ORM with foreign key cascades to journal_entries.
- Added REST API routes for listing, creating, toggling completion, and deleting goals.
- Integrated goals state and optimistic UI updates into the journal view.

You

Implement real journal streak calculation in DayBook. Streaks should be computed from actual journal entry dates in SQLite without relying on client-side mocks.

Agent

Implemented SQLite-backed consecutive streak counting:
- Added date normalization and consecutive day algorithm spanning back from today or yesterday.
- Created GET /api/journal/streak endpoint returning current and longest streak.
- Updated UI header badge to display live database streak count.

You

Implement DayBook core local AI reflection system. It must run locally using Ollama, ground reflections in SQLite journal context, and provide thoughtful journal insights without leaking user data.

Agent

Integrated local AI reflection engine:
- Connected to Ollama local instance running Gemma.
- Implemented deterministic retrieval of recent entries, mood trends, and active goals to construct the reflection prompt context.
- Added streaming reflection generation with fallback handling.

You

Implement smart AI queries and deterministic data retrieval. Factual queries (like goal counts, mood history, dates) should be answered directly from SQLite, while reflective prompts use the local LLM.

Agent

Built hybrid query router:
- Intent classification routes factual questions directly to SQL aggregations.
- Reflective and emotional questions are enriched with retrieved SQLite context and passed to the local LLM.
- Drastically reduced LLM latency and eliminated hallucinations for historical journal facts.

You

Implement DayBook Quote System and Persistent Library: daily quotes, quote catalog, and SQLite-backed saving/unsaving of favorite quotes.

Agent

Created persistent Quote & Library system:
- Added quotes and saved_quotes tables in SQLite.
- Built deterministic daily quote selection based on date hashing.
- Added endpoints for favoriting quotes and browsing saved quotes in the Library view.

You

Implement per-entry AI observations (DayBook Noticed). When an entry is written, the system should generate concise categorized observations (patterns, achievements, emotions).

Agent

Implemented Per-Entry AI Observations (DayBook Noticed):
- Added journal_observations schema with observation types (habit, emotion, milestone).
- Extracted structured observations upon saving journal entries.
- Rendered categorized observation tags in the left page margin of the journal spread.

You

Implement AI Memory Suggestion with explicit user confirmation. DayBook should detect long-term facts or habits from reflections, propose them to the user, and only persist them to user memory upon approval.

Agent

Implemented AI Memory Suggestions with human-in-the-loop confirmation:
- Added suggested_memories table with status tracking (pending, confirmed, dismissed).
- Built memory suggestion extraction prompted from recent journal reflections.
- Provided confirmation controls in the UI so users retain complete authority over stored memories.

You

Implement deep personalization, context-aware AI reflections, and the knowledge endpoint showing what DayBook knows about the user.

Agent

Implemented Deep Personalization & Knowledge Surface:
- Added GET /api/ai/knowledge endpoint aggregating profile facts, confirmed memories, recurring themes, and reflection preferences.
- Dynamically tuned AI reflection tone according to user style (Gentle, Balanced, Direct).
- Ensured all personalization remains strictly local on device.

Prize Categories

Gemma - Daybook uses Gemma 3 4B as its core AI model, running locally through Ollama to analyze journal entries while keeping personal data on-device.

Render - Used to deploy the parts of Daybook that need to be accessible beyond the local development environment.

GitHub - Used for open-source development, CI/CD, collaboration, version control, and sharing Daybook's code with the community.

Top comments (2)

Collapse
 
rahul_9bbd8de34ff84838754 profile image
Rahul •

This honestly makes me want to pick journaling back up again. I’ve always loved the idea of documenting my life, but having something that can quietly notice the thoughts, patterns, and things I keep coming back to makes it feel so much more meaningful. The AI aspect is such a beautiful finishing touch too.

I genuinely feel like this is the kind of thing I’ve been looking for without even realizing it. Somewhere to put my thoughts, look back on my life, understand myself a little better, and hopefully grow along the way.

Thank you for making something that feels this thoughtful and useful. I can already see myself coming back to it a lot, and I’m genuinely excited to start using it.

Collapse
 
0xna profile image
Jesus Chetia •

Bro, this genuinely made my day. 😭❤️

I really wanted DayBook to feel like something you’d actually keep coming back to, rather than just a project I built for a challenge. Hearing you say that it makes you want to journal again and that you can see yourself using it honestly means a lot.

And yeah, I finally submitted it! 😭 Thank you for taking the time to write this.
Seriously 🫶