This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend
What I Built
My friends and I are trying to spend less time mindlessly scrolling through social media. We noticed how easily scrolling can become a way to avoid sitting with our feelings, so we encourage each other to write about what we are experiencing.
But writing by hand does not work for everyone. Some friends told me they often turn to ChatGPT to vent about their feelings. I wanted to give them a digital place to journal, with a little help when they cannot find the words or untangle a feeling on their own.
That is why I built Within: a quiet journaling space with gentle reflection questions and mood-based writing prompts, powered by a model running on the user's own computer.
For me, a more ethical approach meant making privacy a concrete design choice: journal entries stay in the browser, and AI requests go to local Ollama rather than a cloud AI service. Within does not upload entries for model training or train a model on them.
The goal is to support the writing habit we are building together, with a place to pause and pay attention to ourselves.
Within offers:
- A distraction-free writing page.
- Reflection questions based on an entry.
- Short writing prompts for anxious, grateful, reflective, or bored moods.
- History saved in the browser, with no account required.
- A local-model selector and connection help.
After a successful save, the writing field clears for the next entry. “Write about this” replaces the previous text with the selected prompt. The app remains usable for writing and saving when AI is unavailable.
This is a writing aid, not therapy or professional support.
Demo
| Write | Ideas | History |
|---|---|---|
![]() |
![]() |
![]() |
To try the AI, open the site on a computer running Ollama. The site is the interface; the model runs on that same computer.
- Install Ollama.
- Download a local model with
ollama pull gemma3:1b. - Allow
https://within-offline-journal.onrender.cominOLLAMA_ORIGINSand restart Ollama. - Allow local network access if your browser asks, then click Reconnect.
The README includes instructions for macOS, Windows, and Linux. On macOS/Linux, with any existing Ollama server stopped, you can run:
OLLAMA_ORIGINS="https://within-offline-journal.onrender.com" OLLAMA_NO_CLOUD=1 ollama serve
The site also opens on mobile for writing and history. The current AI integration is for the same computer: localhost on a phone refers to that phone, not a laptop.
After the app shell is cached and the model is installed, the design supports offline use while local Ollama remains running. Saved entries belong to that browser and site origin; browser storage is not a backup.
Code
Within — My Offline Journal
A private journaling PWA with AI provided by Ollama on the same computer
Plain HTML, CSS and JavaScript, with no build step or cloud AI backend
Entries stay in this browser's localStorage. Reflection questions and mood prompts
are sent directly to http://localhost:11434/api/generate, never through Render.
Features
Write freely and generate reflection questions, find a writing prompt for your mood, and revisit entries saved in your browser.
Setup
- Install Ollama on the computer where you open the app.
- Download a model once in your terminal:
ollama pull gemma3:1b. - Keep Ollama running. Configure the allowed site origin below.
- Open the app and click Reconnect. Choose an installed local model.
The browser never downloads model weights, MediaPipe or WASM. The service worker caches only HTML, CSS, JavaScript, the manifest and icons. Legacy vendor files are unused. On upgrade, old journal shell/model…
The application code is MIT-licensed. Gemma models have their own usage terms.
How I Built It
Within uses plain HTML, CSS, and JavaScript. There is no framework or build step. A service worker caches the small application shell, and localStorage holds journal history.
For AI, I use Google's open-weight Gemma models through Ollama, with gemma3:1b as the preferred installed model. Reflection questions and mood prompts are the core AI features.
The first approach used MediaPipe and WebGPU inside the browser. That meant large model downloads and dependence on browser GPU support. During development, I changed the architecture: Ollama now handles inference, while the browser sends a simple request:
const response = await fetch("http://localhost:11434/api/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: activeModelName,
prompt,
stream: false,
options: { num_predict: 512, temperature: 0.8 }
})
});
Render hosts the static interface. It does not run the model or receive the journal text through the AI request.
The app lists installed models through /api/tags, remembers the selection, excludes recognized cloud-model entries, and reports connection failures. For local-only use, the setup instructions also disable Ollama cloud features.
Two practical lessons stood out:
An updated deployment can still look old. After the migration, the app still displayed “Downloading model.” We found that the usual script URL returned old code while a versioned URL returned the new client. Versioned asset URLs and a new service-worker cache addressed that.
A running local server can still reject the browser. Ollama answered a direct request, but a request carrying the Render origin returned HTTP 403. The configured environment variable had not reached the running server. Restarting with the explicit allowed origin fixed the connection.
Four automated tests cover local model discovery and selection, non-streaming requests, failure handling, and service-worker cache cleanup. The local connection was also verified manually. Most of my initial agent interaction happened in Antigravity; I continued the Ollama migration and refinements in Codex.
A useful troubleshooting reference was Fix CORS before you blame the SDK, which emphasizes checking the server's allowed origin and preflight response.
Why Does Open Innovation Matter?
The reason for using an open-weight model comes directly from the people I built this for. My friends wanted help reflecting on their feelings, and I wanted that help to be available without requiring them to send their writing to a cloud AI service.
For this project, open innovation made local inference and control over the model practical.
I could use an open-weight model on my own computer, choose among installed models, inspect the application's request flow, and change the architecture when browser inference became cumbersome.
A cloud-only API would require sending the writing off the device for inference and keeping an internet connection. With a downloaded local Gemma model, the AI can work without that dependency. The model download still requires internet initially, and inference still depends on the computer's resources.
The tradeoff is setup: users need Ollama and a model installed. I chose to make that requirement visible instead of presenting the AI as something that works on every device automatically.
The aim is a small, understandable tool that gives the writer control over where their words go.
My Agent Session
The project began in Antigravity and continued in Codex. These sessions show the initial browser-inference approach and the later move to local Ollama. Earlier descriptions of WebGPU and phone-based AI refer to the previous architecture, not the current demo.
Antigravity — initial build
Codex — Ollama migration and debugging
This session contains selected, chronological excerpts from our conversation, rather than a complete raw transcript. It covers the migration, stale deployment cache, the Ollama origin rejection, connection recovery, and interface refinements.
Prize Categories
- Best Use of Gemma: Gemma provides the local reflection questions and writing prompts.
- Best Use of Render: Render hosts the deployed static PWA.
AI disclosure: I used Antigravity and Codex during development, and AI assistance to prepare this submission. I am reviewing the draft before publishing.








Top comments (0)