Project indexPrivate system

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.

No public source or live link
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.

  • React
  • Vite
  • FastAPI
  • Python
  • PWA
  • Ollama
  • GitHub Actions
Dashboard on a phoneAn illustration of the layout. No real mail, events, or hostnames are shown.

02 · Build

What the system needed.

GhostGrid features and engineering decisions

01

Email

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
02

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
03

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
04

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

Conceptual architecturesanitized / not to scale
  1. 01Installable React PWA
  2. 02FastAPI on homelab
  3. 03Email & iCloud calendar
  4. 04Local Ollama model
This intentionally high-level view communicates system boundaries without exposing infrastructure details.

05 · Outcomes

A stronger operating baseline.

  1. 01

    Email, calendar, and server status are in one place on my phone.

  2. 02

    The assistant can't change my data without my confirmation.

  3. 03

    Next up are more assistant tools and a research page.