Case study · 2026–present
GhostGrid
A personal dashboard I run on my homelab for email triage, my calendar, and server stats, with a local LLM assistant that has to ask before it changes anything.
- 4
- inboxes triaged, read-only
- 146
- backend tests, run in CI on every PR
- Local
- Llama 3.1 8B assistant on my GPU
01 · Overview
- Role
- Specs, design, and review; built AI-assisted with Claude Code
- Status
- Private · in active development
- Privacy
- Private system
From real constraint
to working system.
The challenge
My email is spread across four inboxes, my calendar is in iCloud, and my server's health lives in a handful of admin pages. I wanted one place on my phone that told me what needed attention.
The response
I built GhostGrid as an installable web app backed by FastAPI, running under systemd on my homelab and reached only over Tailscale. I write the specs, Claude Code implements them on branches, and I review and merge every change.
02 · Build
What the system needed.
GhostGrid features and engineering decisions
Triage that catches what slipped
A daily job scores mail across four Gmail and Outlook inboxes. It saves a snapshot after every scan, so the weekly digest can tell "I replied" apart from "this fell through the cracks."
- Read-only by design, because there is no code that writes mail
- Mail content is treated as untrusted, and raw HTML never crosses the API
- Each account reports its status and last successful scan
Calendar
Two-way iCloud sync
Month, week, and day views read and write my iCloud calendar. Edits to recurring events change the parsed event rather than overwriting the raw calendar data, and they ask whether to change this event, future events, or all of them.
- Read/write sync with iCloud
- Recurring edits scoped to this, future, or all
- A safety check before every save
Assistant
A local model that has to ask
The assistant runs Llama 3.1 8B through Ollama on the homelab GPU. Any edit or delete it wants to make becomes a proposal I have to confirm, and the server enforces that, not the model.
- Switched from Mistral 7B after it failed at tool calling
- The model unloads after 60 seconds so the GPU can be shared with media transcoding
- Email scoring uses a hosted model; the assistant is local
Quality
Tests and CI
There are 146 backend tests, mostly covering email and calendar, and GitHub Actions runs them on every pull request along with the frontend build.
- Python unittest suite for email, calendar, and bookmarks
- CI on every PR and every push to main
- Manual deploys with an update script
03 · System
Boundaries before boxes.
Sanitized system architecture
- 01Installable React PWA
- 02FastAPI on homelab
- 03Email & iCloud calendar
- 04Local Ollama model
04 · Views
Designed representations.
Sanitized visual gallery
05 · Outcomes
A stronger operating baseline.
- 01
Email, calendar, and server status are in one place on my phone.
- 02
The assistant can't change my data without my confirmation.
- 03
Next up are more assistant tools and a research page.