Adam Whitely
This is a working portfolio of systems I've built around data, automation, workflow design, and continuous improvement. The projects are different, but the approach behind them is usually the same.
How the system works
Most useful systems start before the tool exists.
The first work is figuring out what is actually happening, what information is missing, what signals already exist, and how those signals can be captured without turning tracking into another chore.
After that, the work changes. The collected data becomes a foundation. Analysis, interventions, automations, dashboards, prompts, scripts, and full projects can branch from it. Some stay connected to the live data. Others use the data once to understand the problem, then become their own separate tools.
The process has two connected halves:
Find the place where better evidence could change the work.
Discovery starts with noticing that a workflow, habit, archive, export, or system contains more useful information than it currently exposes.
The opportunity might be a missing metric, a repeated manual task, a hard-to-explain behavior, a pile of unstructured exports, or a process where people keep making decisions from memory.
Discovery defines the source and the reason it matters.
Understand what is actually happening before deciding what to collect.
Observation is the bridge between a vague idea and a useful data layer. It asks what the real workflow looks like, where the signals come from, what already exists, and what would be noise.
This step is intentionally before capture. If the wrong thing gets collected, every later project inherits that mistake.
Observation decides what is worth turning into a durable record.
Create the reusable evidence layer.
Capture turns scattered signals into something that can be searched, queried, reviewed, joined, summarized, or used by other tools.
Sometimes that means parsing an export once. Sometimes it means adding a logging step to an existing workflow. Sometimes it means syncing live data into a local database. The point is not to collect everything. The point is to create a record that future work can trust.
Capture can create different kinds of foundations:
This is the part that makes future projects cheaper. Once the source is captured well, new ideas can branch from the same foundation.
Make sure the foundation is good enough to build on.
Calibration checks whether the captured data actually represents the thing it claims to represent.
For live systems, calibration may mean adjusting fields, thresholds, categories, logging frequency, or sync rules. For retroactive systems, it may mean checking whether the historical record is complete enough, biased in known ways, or missing sources that should be added later.
Calibration is what turns captured data into a foundation instead of just a pile of records.
Use the foundation to find branches worth building.
Analysis does not have to become a project by itself. Sometimes it becomes a report or dashboard. Sometimes it becomes a prompt, a rule, a script, a UI, a model, a workflow change, or a new product idea.
The useful question is: what can this evidence now support?
Analysis is where one data source can start becoming many projects.
Build the first practical response to what the data shows.
An intervention is any concrete change made because the evidence revealed a better path.
It might be small: a shortcut, a correction rule, a report, a prompt, a better field, a clearer threshold. It might be larger: a dashboard, a workflow tool, a knowledge base, an app, or a new operating process.
Interventions do not all need to stay attached to the data layer. Some do. Some are simply better because the data helped define them.
Connect the branch back to the data when repetition is clear enough.
Automation belongs where the pattern is stable, the action is known, and the system can reduce effort without hiding important judgment.
Sometimes automation means live syncing: the data updates and the product changes with it. Other times automation means generating a periodic report, refreshing a prompt, updating a rule list, or triggering review only when the record crosses a threshold.
Automation should make the branch easier to keep useful. It should not force every project to become a live dashboard.
Improve the foundation, the branches, or both.
Iteration is where the system becomes a portfolio of work instead of a single loop.
The data layer may need better capture, new sources, cleaner labels, or stronger calibration. The branch projects may need new features, simpler interfaces, better rules, more useful outputs, or a different relationship to the source data.
Iteration includes asking:
The goal is not one permanent system. The goal is a useful foundation that can keep producing better projects.
Summary
The portfolio is organized around this pattern:
This can apply to personal systems, AI conversation exports, workflow capture, behavioral logs, domain knowledge, internal tools, and operational improvement work.
Use cases
Each use case starts with a discovery and observation stack, then shows the practical systems and projects that grew from the captured data.
From writing samples to a personal writing intelligence system
This started with a simple discovery: the writing samples already existed.
They were scattered across ChatGPT conversations, AI drafts, personal messages, code sessions, work notes, and long-running project threads. The useful data was not missing. It was just trapped in exports and conversation histories that were technically available but practically hard to use.
Once the export problem was solved, the rest became a practical application of the same process described in the ethos: discover the source, observe what is already there, capture it into a structure, analyze the patterns, intervene with small tools, automate the repeatable parts, then keep iterating as the corpus grows.
Discover
The initial observation was almost embarrassingly useful: ChatGPT, Claude, and the surrounding writing tools already contained years of examples of how I write, how I ask questions, how I revise, where I get stuck, and what kinds of outputs I accept or reject.
The only hard part was knowing how to export it and turn it into something queryable.
Observe
The raw material was messy but rich: conversation exports, message histories, draft responses, code blocks, correction patterns, topic clusters, and repeated phrases. On their own, those sources were not useful enough. Together, they formed a writing corpus.
Capture
The capture step was the unlock. The export was parsed into a local database with stable tables for conversations, messages, tags, topics, extracted text, and code blocks. Writing samples became rows instead of blobs.
That changed the work. Adding a new analyzer no longer meant rebuilding the pipeline. It meant writing a query and deciding what action the result should support.
Calibrate
This one is retroactive, so calibration is lighter than it would be in a live workflow. The main question was not "are we capturing the right behavior going forward?" It was "is this historical corpus representative enough to build from?"
The answer was yes for personal writing patterns, typo patterns, repeated phrases, and voice analysis. The next calibration step is to add more sources: Claude history, email drafts, docs, notes, and any future AI-writing exports.
Analyze
Once captured, the corpus started producing useful systems immediately:
Intervene
The intervention layer is where this stops being "interesting analysis" and becomes practical. The outputs are small tools that change the writing process directly: fix the typo before it ships, suggest the phrase before it gets retyped, make AI drafts sound right on the first pass, and show when writing is drifting into jargon.
Automate
Automation is intentionally selective. The system does not automate all writing. It automates the parts that are obvious, repetitive, and already well evidenced by the corpus.
Iterate
Iteration is the main point. Every new export, draft, message, or AI session can become more training material for the personal system. The project keeps creating new projects.
Spawned projects
Specific tools, software, prompts, dashboards, and project branches that grew from this data foundation.
System-wide custom autocorrect
Need
Built-in autocorrects catch generic typos. They don't catch the ones I actually make.
After three years of writing I had a clear pattern of how I get words wrong. Almost none of it overlapped with the default dictionary. The system was correcting things I never typed and ignoring the ones I always do.
Observed
Three years of personal messages — about 10,000 messages, 1.55 million words — parsed into a SQLite database. Each typo tagged by message, time of day, length, and surrounding context.
The output: 879 confirmed errors, 100+ distinct misspelling patterns. Most are valid English words spelled wrong (like "form" instead of "from") so a generic spellchecker won't flag them at all.
Applied
Personal. An AutoHotkey script watches every keystroke across Windows and replaces any of those 100+ patterns the moment they're typed. Toggle on/off with Ctrl+Shift+F12. The patterns came from my own data — the script doesn't fight me, because it was built FROM me.
Professional. Same approach scales per-employee or per-team. Onboarding tooling that adapts to the writer instead of forcing the writer to adapt to a generic dictionary. Most useful where the words people actually fumble are domain terms — legal, energy, healthcare.
Iterated
The dataset keeps growing as I write. Each new pattern goes back into the script. Next step is auto-detecting new patterns from the rolling corpus instead of adding them by hand.
Spelling correlation analysis
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Error rate per message, correlated to time of day, day of week, message length, classification, and monthly volume
Applied
Personal. Visibility into when typing quality degrades (weekends 2.5× weekday, late night worst)
Professional. Quality signal for written communication channels — flag messages or periods where attention is fragmented. Could feed coaching tools or workload indicators
Iterated
All findings already documented in chatgpt_import/IDEAS.md
Voice-matched prompt library
A distilled style guide pulled out of the personal message corpus, formatted as a single prompt that drops into any AI tool and makes the output sound like the writer.
Lower effort than building a full skill — and provider-agnostic. Same prompt works in ChatGPT, Claude, Gemini, anywhere that takes system instructions.
Per-team or per-brand version is the obvious extension. Customer service replies that stay on-tone. Marketing copy that doesn't read like generic AI output. Internal docs that match the institutional voice without the writer having to think about it.
Snippet expander — declared shortcuts, system-wide
Need
The same phrases get typed over and over — addresses, email signatures, common technical commands, stock replies. Every text expander I tried was either too heavy (TextExpander, $40/yr), or locked to one app, or didn't survive a Windows reinstall.
I wanted shortcut → expansion pairs in plain JSON I owned, with a small UI to add and edit them, and a background listener that just worked.
Observed
A small Tkinter app for adding, editing, and toggling snippet pairs. Storage is plain JSON — copy-pastable, version-controllable, easy to back up. A background keyboard listener watches typed text and swaps matched shortcuts system-wide.
Distinct from the autocorrect work (which fixes mistakes I make without thinking). This expands shortcuts I declare on purpose.
Applied
Personal. Currently use it for addresses, email closing blocks, common commands, and the handful of phrases I type every day.
Professional. Same shape, three obvious team-level applications:
- Legal boilerplate libraries shared across a practice
- Customer service stock replies maintained by team leads, expanded by every agent
- Technical command sequences (kubectl flags, AWS CLI patterns) shared across an ops team
Shared JSON files in a repo means snippets propagate across the team without anyone running an installer. New hire clones the repo, listener picks them up.
Iterated
The next merge is with the predictive-text concept — declared snippets stay always-available, AND the system surfaces likely expansions from n-grams in the writing corpus. Combined with the autocorrect and the write-like-me skill, that's the full personal writing stack.
Write-like-me — voice profile as a skill
Need
Generic AI writing has a tell. Too wordy, too formal, opens with "I hope this finds you well," cushions every direct statement. None of that is how I write. So when I'd ask AI to draft something I'd spend half the time deleting filler and rewriting it to sound like me anyway.
The fix had to be reusable — drop a single instruction in front of any AI conversation and have the output already match.
Observed
Pulled my own voice profile out of the message corpus. From 1.55M words across 10K+ messages, three years of real writing:
- Average sentence length, sentence-length distribution
- Opener phrases I actually use ("lets...", "okay so...", "I want...", never "just following up")
- Punctuation and capitalization patterns (58% of casual messages drop end punctuation)
- Domain vocabulary used naturally (SGIP, NEM, SREC, TPO — never defined)
- Things I push back on consistently ("too wordy", "too formal", "lower the adjective count")
All of that distilled into a single SKILL.md — a Claude skill that gets pulled in automatically whenever I ask for any rewriting.
Applied
Personal. Any rewrite, draft, or polish task I hand to Claude already comes back in my voice. I'm not editing AI output anymore. I'm reading it once and shipping.
Professional. Same approach scales per-team or per-brand. The corpus changes — Slack archive, support tickets, marketing copy, internal docs — but the pipeline is identical:
- Extract voice markers from real writing
- Distill into a system-prompt-shaped instruction
- Drop in front of any AI tool, provider-agnostic
For organizations adopting AI broadly, this is one of the highest-leverage things to build. Without it, every team member's AI output sounds like an AI. With it, the brand voice survives the AI handoff.
Iterated
The skill is at chatgpt_import/write-like-me/SKILL.md. The voice profile gets re-derived as the corpus grows. Next is wiring the same profile into other AI providers (ChatGPT, Gemini) so the voice carries across tools.
Predictive text / phrase completion
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
N-gram frequencies from message corpus
Applied
Personal. System-wide phrase expansion for high-frequency phrases ("virtual power plant" 499×, "give me a list of" 341×)
Professional. Domain-specific text expansion. Particularly valuable for repetitive professional communication (legal, energy program descriptions, customer service)
Iterated
Apostrophe corrections need context-awareness. Pairs with the manual snippet expander already prototyped in 1.6a — the predictive layer would auto-suggest snippets the user hasn't yet defined
Vocabulary growth and readability over time
Need
I knew I was learning new things every year — the energy/solar industry alone reshaped how I write — but I had no way to actually see it. How much new vocabulary was I picking up? Was my writing getting more complex over time, or just longer?
Observed
Monthly rollup against the message corpus. For each month, computed:
- Unique vocabulary count
- Net new words (first appearance that month)
- Type-token ratio (lexical diversity)
- Flesch-Kincaid grade level
- Gunning Fog index
The results across 1.55M words:
- 29,191 unique words total
- 34% used only once — the long tail of writing
- The two-month energy deep-dive added 6,731 new words
Applied
Personal. A clear picture of when my vocabulary was expanding (and which topics drove it) vs. when it was stable. The Flesch-Kincaid trend lets me catch myself drifting into jargon and over-complexity in messages that should stay plain.
Professional. Same metrics applied org-wide answer questions most teams don't even know to ask:
- Is our documentation drifting toward unreadable
- Are two teams converging on a shared vocabulary or diverging into silos
- When a new domain enters the company (a new product, a new regulation, an acquisition), how fast is the vocabulary spreading
- Which writers consistently produce content above the org's reading-level baseline
Iterated
Same source DB as the autocorrect and the write-like-me skill. Adding new metrics is cheap — they're just queries against the existing rollup table.
Personal jargon dictionary
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Domain-specific vocabulary that does not appear in standard dictionaries (SGIP, NEM, SREC, PBSR, NBT, TPO, RGM, IPM, VPP, ADI, RETS, SCE, SDCP, TOU, NYSERDA)
Applied
Personal. Glossary of domain terms with definitions extracted from prior conversations explaining them
Professional. Onboarding accelerator for industry-specific roles. Auto-generated glossaries built from team chat and document history
Iterated
Energy domain has 814 source conversations to draw from
Communication pattern fingerprint
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Question-to-statement ratio, opener pivot patterns, action initiator frequency, list-vs-prose preference
Applied
Personal. Self-knowledge of how communication actually happens vs. how it is perceived
Professional. Identify communication mismatches in teams. Detect when a writer's actual style diverges from their intended persona (e.g., formal channel using casual fingerprint)
Iterated
Could feed style coaching tools
Emotional tone tracker
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Sentiment heuristics over time — frustration markers ("isn't working", repeated punctuation), satisfaction markers ("perfect", "thanks"), confusion markers
Applied
Personal. Identify high-frustration topics or periods, correlate with output quality
Professional. Customer service quality signals. Internal communication health indicators. Burnout precursor detection without requiring surveys
Iterated
Heuristic-based, no LLM cost. Privacy-respecting if scoped to opt-in
Writing evolution timeline
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Monthly cohort analysis of vocabulary, sentence complexity, topic density, question patterns
Applied
Personal. Visualization of three-year trajectory from analyst to energy specialist
Professional. Track skill development of individuals or teams. Demonstrate capability growth in performance reviews with data rather than narrative
Iterated
Trajectory already partially documented in IDEAS.md
Reusable pattern
The professional version is the same shape with a different corpus: team chats, support tickets, documentation, sales notes, product conversations, or company-managed AI logs.
The value is not "AI writes better." The value is that the organization can finally see the language layer of its work: what people ask, what they repeat, what they misunderstand, which terms spread, where tone breaks down, and which writing patterns are worth turning into tools.
From local signals to a personal operating dashboard
The system started with a problem that looked small at first: I had useful signals everywhere, but no shared place for them to land.
DNS queries, device presence, Hue lighting state, Home Assistant entities, focus sessions, tasks, website changes, AI calls, Steam activity, API requests, and automation events were all being generated already. The issue was not that the data was missing. The issue was that every signal lived in a different tool, a different database, or a different one-off script.
The portfolio version of this work is the consolidated story: a modular personal operating dashboard where local signals become visible, queryable, and eventually controllable.
Discover
The discovery was architectural. I did not need one more isolated personal tool. I needed a place where small tools could keep their own boundaries while still feeling like one system.
Before this, every new idea created the same friction: another Flask app, another route structure, another database decision, another UI pattern, another local URL, another place to remember how something worked. A task tracker, focus timer, network monitor, Hue controller, presence detector, Steam viewer, website watcher, and API inspector all made sense on their own. Together, they were turning into tool sprawl.
The useful shift was treating the dashboard as an operating layer instead of a single app. Each module could stay isolated, but the shell, navigation, design tokens, AI routing, auth patterns, and database conventions could become shared infrastructure.
Observe
Once I started looking for signals instead of apps, the sources were everywhere.
The most important observation was that these signals did not need to be merged into one giant database to be useful. They needed to be collected consistently, rendered consistently, and allowed to stay modular.
Capture
The capture layer became a modular Flask dashboard with a strict rule: each feature is an isolated blueprint. Each module owns its routes, templates, static assets, business logic, and data store. Modules do not import from each other.
The architecture is intentionally boring in the places that matter. Shared layout. Shared navigation. Shared design tokens. Shared module registration pattern. Stable directories. Predictable naming. A module can be replaced, removed, or rebuilt without putting the rest of the system at risk.
That is what made the dashboard expandable. New modules no longer require a fresh application decision. They require a module decision.
Calibrate
The calibration mechanism is the written system model. The dashboard has a canonical reference for how modules are supposed to be built, where files belong, how templates should work, how design tokens should be used, and how AI coding sessions should behave.
That matters because a modular system only stays modular if the boundaries are enforced. Without written guardrails, AI-assisted development tends to spread small inconsistencies everywhere: new CSS patterns, new route shapes, duplicate helper functions, cross-module imports, and hidden coupling.
The calibration layer turns AI from a fast but inconsistent contributor into a repeatable builder. Every new module follows the same system contract.
Analyze
Once the capture layer existed, analysis started showing up naturally.
DNS analytics made it obvious which devices were talking to which domains, how often, and when something changed from baseline. A smart bulb beaconing to a questionable ad domain every few minutes was no longer invisible. A kid's tablet hammering YouTube ad endpoints outside the expected content blocks became visible as network behavior, not a parental-control guess.
Focus and task data made personal productivity less vibes-based. Instead of asking whether I had a productive day, the dashboard could show completed focus blocks, abandoned sessions, task completion timing, and recurring patterns.
Website monitoring turned external pages into watched surfaces. Vendor pricing pages, status pages, policy pages, GitHub release notes, terms of service, and other pages that normally change silently became diffable records.
Production tracking showed that small-project issues did not need to live in a separate SaaS tool. Bugs, notes, UAT tasks, and feature requests could live as schema-driven JSON inside the repo and still render like a normal issue board.
The dashboard became less about displaying widgets and more about asking: what signals are already being generated, and what decisions would improve if those signals were easier to see?
Intervene
The intervention layer is where the dashboard becomes a control surface instead of a passive report.
Hue scene engine
The Hue app gives static scenes. I wanted lighting that actually moved: slow color drifts, candle flickers, sunset transitions, focus lighting, and playful effects for the kids.
The scene engine sits on top of the Hue API. A scene is a sequence of keyframes per light, each with a target color, brightness, and transition type. Role assignments mean a scene can address "all kitchen lights" or "the desk lamp" instead of brittle device IDs. The distinctive layer is prompt generation: describe what the room should feel like, let AI generate a structured scene, then let the engine play it.
AI provider abstraction
Every AI provider has its own SDK, response format, model names, failure modes, and pricing. Hardcoding a provider into each module would make the whole dashboard brittle.
The provider abstraction gives modules a stable call pattern. A module asks for completion; the routing layer decides whether the job belongs with Claude, OpenAI, or local Ollama. That makes provider selection a runtime policy instead of a rewrite.
This also makes the professional pattern clearer: cost attribution, fallback routing, prompt libraries, sensitive-data routing, local model fallback, and vendor switching are not separate AI features. They are consequences of having the abstraction in the right place.
DNS analytics
DNS is one of the cleanest observability layers in a home or small-office environment. Every internet-connected device asks for a destination before it connects, and nothing has to be installed on the device itself.
The dashboard logs queries by device, destination, time, category, block status, and trend. That makes it useful for personal visibility, child-device monitoring, smart-home debugging, and professional patterns like shadow IT detection, vendor inventory, and lightweight network observability.
Website change watcher
Some pages matter specifically because they change without telling you. The watcher captures rendered text snapshots, hashes them, ignores noisy selectors or regex patterns, stores history, and produces diffs.
Personally, it is a local changedetection.io-style tool. Professionally, the same pattern works for competitive monitoring, legal/compliance tracking, vendor terms, status pages, regulatory program pages, internal documentation drift, and release-note monitoring.
Production tracking
The production tracker keeps bugs, feature requests, UAT notes, and implementation tasks in JSON files committed to the repo. The dashboard renders those records like a normal issue board, but every status change lives in git.
The important choice is schema. JSON-in-git is only clean if the record types are stable. Schema-driven issue types prevent custom-field drift and make the dashboard reliable over time.
Automate
Automation in this system is structural first and behavioral second.
The structural automation is the module pattern itself. A new data source or utility does not require a new app. It gets scaffolded into the shell, inherits the layout and tokens, follows the route/template/static pattern, and stays isolated from its siblings.
The behavioral automation comes after the signal is trustworthy: lighting follows context, quick actions collapse repeated steps, website changes create alerts, presence can drive ambient state, focus sessions can trigger environment changes, and AI can operate against local context through the same provider layer.
Iterate
The dashboard keeps growing because the marginal cost of a new module is low. That is the point. The system is not valuable because every module is huge. It is valuable because small modules can be added without creating another pile of one-off tools.
Combined module map
This single markdown file replaces the need to explain the dashboard through separate small cards. The modules below are the pieces that now roll up into the parent use case.
| Module | Role in the system | Status |
|---|---|---|
| Modular Flask dashboard architecture | Shared shell, isolated blueprints, strict dependency direction, and repeatable module scaffolding. | Built |
| Database manager | Local analytics surface for CSV/JSON/TSV imports, schema inspection, saved queries, and safe database browsing. | Built |
| Hue scene engine | Prompt-generated dynamic lighting with keyframes, roles, transitions, and mood-based scenes. | Built |
| Home Assistant integration watchdog | Monitors home entities and keeps smart-home state connected to dashboard visibility and control. | Built |
| AI provider abstraction | One AI interface across Anthropic, OpenAI, and local Ollama with routing and fallback patterns. | Built |
| Global AI chat widget | Page-aware AI assistance inside the dashboard, using local context instead of generic chat. | Built |
| Auth manager | Central credential and access pattern so modules do not invent their own auth handling. | Built |
| Design system with tokens | One visual language for all modules, preventing per-module CSS drift. | Built |
| DNS analytics | Per-device DNS logging, blocked-query visibility, destination patterns, and anomaly detection. | Built |
| Focus timer | Pomodoro sessions and completion history as personal activity signal. | Built |
| Network monitor | Device connectivity, latency, uptime, and outage visibility. | Built |
| Presence detection | BLE/Wi-Fi-derived home presence as a trigger for ambient automation. | Built |
| Quick actions | One-click launcher for repeated dashboard and home-control actions. | Built |
| Steam integration | Third-party activity ingestion pattern for entertainment, presence, and scene triggers. | Built |
| Task tracker | Lightweight personal task system integrated with the broader dashboard shell. | Built |
| Usage dashboard | Aggregated application/tool usage patterns without needing invasive monitoring. | Built |
| Voice commands | Hands-free control path for common actions and future local command analysis. | Built |
| Weather/climate | Local environmental context for automation, dashboards, and ambient displays. | Built |
| Widget creator | Composable dashboard surfaces without hand-building every layout. | Built |
| API inspector | Visibility into module endpoints, requests, responses, timings, and failures. | Partial |
| Claude CLI integration | Local AI command/session capture and always-available coding assistance context. | Partial |
| MCP server for Home Assistant | Bridge that exposes Home Assistant entities as AI-operable local tools. | Built |
| Production tracking system | Git-backed issue tracker using schema-driven JSON records and dashboard rendering. | Built |
| Local tools overlay | Radial/chat-style overlay for fast access to local tools without leaving current context. | Partial |
| Website change watcher | Local page monitoring, snapshots, hashes, diffs, and alerts for changed external surfaces. | Partial |
Reusable pattern
The professional version is not "a personal dashboard for work." It is a pattern for building internal operating systems without turning every feature into a monolith.
Four things make the pattern portable:
That pattern applies to personal dashboards, small-team internal tools, compliance trackers, field-ops dashboards, lab environments, local AI tooling, smart buildings, and any environment where many small workflows need to feel like one system without becoming one tangled codebase.
Roadmap
- 25+ dashboard modules organized under one parent use case
- Modular Flask blueprint architecture
- Shared design-token system
- Provider-agnostic AI layer with local Ollama path
- DNS analytics, Hue scenes, production tracking, and website watcher consolidated into the same system story
- Polish module documentation and screenshots for the portfolio version
- Create a module generator such as `python new_module.py NAME`
- Package the dashboard shell so future projects can drop in modules without copying the whole app
Spawned projects
Specific tools, software, prompts, dashboards, and project branches that grew from this data foundation.
Personal dashboard — composition over monolith
Need
I had a bunch of small personal tools — task tracker, focus timer, network monitor, Hue controller, presence detector, Steam library viewer. Each one was its own one-off. Adding a new one meant rebuilding the same scaffolding every time. Switching between them meant a different URL, different look, different login.
Observed
Refactored everything into one Flask app. Kept each tool isolated.
25+ feature modules. Each one is a self-contained Flask blueprint with its own database, routes, business logic, templates, CSS, and JS. Strict dependency direction — modules don't import from each other. Design tokens shared at the top.
Rules documented in SYSTEM_BIBLE.md so I don't violate them as the system grows.
Applied
Personal. Single control surface for everything. New tools take an hour to scaffold instead of a day. They share the same look without the modules knowing about each other. If a module breaks, the rest of the dashboard keeps working — there's no shared state to corrupt.
Professional. The pattern is what's portable. Most internal tools at companies grow into a tangled mess because they're built as one big app from day one. Every new feature gets bolted into the same code, the same templates, the same database. By year three nobody can refactor anything.
This is the alternative. Each feature module is its own self-contained thing that just happens to render in the same shell. Replacing one doesn't risk the others. Adding one doesn't require touching anything that already works.
Iterated
Adding a new module is essentially a code-gen task at this point. Recent drops: the iOS Shortcut indexer, the AI provider router, the MCP bridge for Home Assistant. Each one followed the same template and slotted in without touching what was already there.
Website change watcher — local changedetection.io
Need
A bunch of pages I care about change without telling me. Vendor pricing pages, status pages, terms of service, regulatory program pages, GitHub release notes, the list goes on. Setting up an account on every one of them isn't going to happen.
There are services for this (changedetection.io). I didn't want to subscribe — I wanted the watcher to run on my own machine, log to my own DB, and feed alerts to my own dashboard.
Observed
For each configured URL the watcher captures:
- Full page text snapshot (after JS render, via Playwright if needed)
- SHA-256 hash for fast change detection
- Per-target include/exclude CSS selectors so layout chrome doesn't trigger false positives
- Regex ignores for noisy timestamps and CSRF tokens
- Full history of snapshots and unified diffs
JSON-driven config so adding a target is a one-line add. Notifications via print, webhook, or SMTP. Exit codes designed for cron orchestration.
Applied
Personal. Local equivalent of changedetection.io. Watch arbitrary pages without subscribing to a service. Already catches policy and pricing changes I would have missed.
Professional. Same engine, three different audiences:
- Marketing / sales — competitive monitoring on pricing, product, feature announcements
- Legal / compliance — terms of service and privacy policy changes for every vendor in the contract pile
- Internal ops — drift detection on intranet pages, documentation, status pages
Same codebase, different config files. Could be exposed as a managed service for any team that needs "tell me when X changed."
Iterated
Currently a standalone Python script. Next step is folding it into the dashboard as a feature module, alongside the DNS analytics and API inspector. They cluster naturally as "things that watch external surfaces and tell you when they shift."
DNS analytics — knowing what every device is doing
Need
There are 30+ devices on my network at any time. Phones, kids' tablets, smart bulbs, cameras, the Tesla, random ESP32 boards. They all phone home. To where? To do what? How often?
I didn't know. Almost nobody with a similar setup does.
Observed
Logged every DNS query at the network level. Categorized by device, destination domain, and time of day. Tracked which queries got blocked and which got through. The DB rolls up nightly into a per-device usage trend.
DNS is the right layer for this. Every internet-connected device makes a DNS query before it makes a connection. There's no app that hides from DNS, and nothing has to be installed on the devices themselves.
Applied
Personal. Visibility into what each device is talking to.
- Caught a smart bulb beaconing to a sketchy ad domain every 3 minutes
- Caught one of the kids' tablets hammering YouTube ads outside their content blocks
- Pattern alerts me when a new device starts behaving differently than its baseline
Professional. Internal DNS observability for organizations that don't want to pay for commercial network monitoring software. Same data feeds:
- Shadow IT detection — unsanctioned SaaS tools always show up in DNS queries first
- Bandwidth attribution by team or by tool
- Compliance signal for which third parties are actually being talked to vs. just being on the approved list
Iterated
This is the foundation for the broader DNS-as-control-surface ideas in the concepts section — DNS for kids, DNS for hotels, DNS for businesses. Same data pipeline, different categorization, different downstream actions.
AI provider abstraction layer
Need
I use multiple AI providers — Anthropic, OpenAI, Ollama for local. Each has its own SDK, its own response format, its own quirks. Every tool I'd build had to pick a provider at write-time and hardcode against it. Switching meant rewriting the integration.
That's the wrong primitive. Provider should be a runtime choice, not a compile-time one.
Observed
A provider abstraction layer that sits between any tool that wants AI completion and the actual provider. Modules call ai.complete(prompt, ...) and the layer routes to whichever provider is configured for that workload — Claude for reasoning, GPT for structured output, Ollama for anything sensitive that shouldn't leave the network.
Configurations include credentials, model names, prompt templates, fallback chain (try Claude → fall back to GPT if rate-limited → fall back to local Ollama if both fail).
Applied
Personal. A single interface across providers. I can compare the same prompt across providers in one tool, swap defaults without touching downstream code, and run anything sensitive against local Ollama without rewriting calls.
Professional. This is the right primitive for any organization adopting AI broadly. Real value layers on top:
- Cost attribution — which team, which workload, which provider
- Fallback routing — provider outages don't take down internal tools
- Prompt library — versioned prompts, auditable, swap without redeploys
- Compliance routing — sensitive data goes only to on-prem models, surfaced as a policy not a code change
- Provider switching — no vendor lock-in, swap without rewriting integrations
Most companies that go all-in on one AI vendor end up with this exact pain point eighteen months in. Building the abstraction first costs less than retrofitting it later.
Iterated
Ollama support means the on-prem option is real, not theoretical. Pairs naturally with the org-level conversation aggregation concept in the ideas section — same routing layer, different downstream consumer.
Hue scene engine — multi-keyframe lighting from a prompt
Need
The Hue app gives you static scenes. "Reading", "Concentrate", "Energize" — pick one, lights snap to those colors. That's fine but it's the same thing every time.
I wanted scenes that actually move — slow color drifts, candle flickers, sunset transitions, a strobe for the kids playing tag. None of that exists out of the box.
Observed
A scene engine on top of the Hue API. Scene = a sequence of keyframes per light, each with a target color, brightness, and transition type:
- Linear / ease / step
- Strobe
- Candle (low-amplitude random flicker)
- Colorloop (continuous hue cycling)
Per-light role assignments mean a scene can address "all kitchen lights" or "the desk lamp" by role rather than by ID. Lights can be added or swapped without rewriting scenes.
The interesting layer: scenes can be generated from a text prompt. Describe what you want the room to feel like, AI generates a multi-keyframe scene definition, scene engine plays it.
Applied
Personal. The lighting actually responds to context — a sunset that runs over 20 minutes when I get home, a slow blue drift during deep-focus blocks, hard cut to bright when an alarm fires. None of which I had to manually program scene-by-scene.
Professional. The same pattern is the right primitive for any addressable lighting environment:
- Office lighting that follows time-of-day rather than static schedules
- Retail and hospitality where lighting is supposed to evoke a mood, not just illuminate
- Theatrical / event lighting cues without a dedicated lighting console
- Smart home integrators who want to ship "scenes that move" without writing them by hand
Iterated
Generated scenes from prompts is the distinctive feature. Next is integrating it with the active program tracker so lighting follows what I'm actually doing — not what the calendar says I'm doing.
Issue tracker that lives in git, not Jira
Need
External issue trackers (Jira, Linear, GitHub Issues) keep the work record in a different place than the code. Two systems, two histories, two places to search. Most of the time the actual context for an issue is in the code itself — but the issue is somewhere else.
For a personal project that's just friction. For a small team it's a tax that compounds.
Observed
Bugs, notes, UAT tasks, and feature requests stored as JSON files committed to the repo. Schema-driven — types defined in Production/_schema_types/ so freeform-field drift doesn't happen.
The dashboard renders them as a normal issue board. Filtering, status changes, assignment, comments — same UX as a hosted tracker. The difference is the underlying state: every change is a git commit, with the same author, history, and review surface as the code.
Applied
Personal. Issue tracking that lives alongside the code. Full git history of every change. No external service, no API key, no monthly bill. When I revisit a file, the issues for that file are right there.
Professional. Lightweight tracking for small teams or compliance-heavy contexts:
- Audit trail by default — every status change is a signed commit
- The work record can't drift from the code because they're in the same repo
- Branch-based workflows naturally include issue updates in the same PR as the fix
- No vendor lock-in, no "we lost five years of tickets when we switched providers"
- Schema-driven structure prevents the "everyone made up their own custom field" problem
For organizations with strict compliance requirements (energy regulators, healthcare, anything SOX-adjacent), the audit story alone justifies it.
Iterated
The schema layer is the part most people would skip and regret. Without it, JSON-in-git becomes a mess inside a year. Stable types up front means the dashboard renders consistently and queries stay reliable.
Database manager
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
CSV/JSON/TSV imports, schema inference, query history, saved queries
Applied
Personal. Lightweight analytics environment for any tabular data
Professional. Self-service analytics for non-technical teams. Ingest sandbox for evaluating new data sources before formal integration
Iterated
Read-only SQL editor, capped pagination
Home Assistant integration + watchdog
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
HA entities, automation triggers, error logs, aggregated issues
Applied
Personal. Detect failing devices and broken automations before they become noticeable problems
Professional. Facility monitoring pattern. Anomaly detection on device health rather than fixed thresholds
Iterated
Issue scanner is recent addition
Global AI chat widget with page context
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Conversation history, page context auto-injected per request
Applied
Personal. Context-aware AI on every page of the dashboard
Professional. AI assistance pattern for internal applications — context injection rather than copy-paste
Iterated
Floating overlay component
Auth manager
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
API credentials per service, expiry tracking
Applied
Personal. Single inventory of API keys with rotation reminders
Professional. Lightweight credential inventory for small teams. Pre-onboarding/offboarding checklist source
Iterated
Could surface expiry forecasting
Design system with tokens
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
All visual values (colors, spacing, typography, shadows, transitions) as CSS custom properties
Applied
Personal. Single source of truth for visual design across all modules
Professional. Design token methodology applied to internal tooling. Theme switching, accent variants, no hardcoded values
Iterated
Living token reference page included
Focus timer (Pomodoro)
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Session lengths, completion rates, interruptions
Applied
Personal. Time tracking with focus-block patterns
Professional. Workload signal feeding broader productivity analysis
Iterated
Plan documented in PLAN_22_pomodoro_focus_timer.md
Network monitor
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Device connectivity, latency, outages
Applied
Personal. Detect connectivity issues before users notice
Professional. Internal network observability. Branch office reliability reporting
Iterated
Pairs with DNS analytics
Presence detection
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Presence inference from device signals
Applied
Personal. Trigger for automations and ambient signals
Professional. Hot-desking, meeting room availability, occupancy-driven environment control
Iterated
Underlies many smart home automations
Quick actions
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
User-defined action shortcuts
Applied
Personal. Single-click triggers for common multi-step tasks
Professional. Macro layer for any internal tool. Closes the gap between "I do this often" and "this is automated"
Iterated
Extensible pattern
Steam integration
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Playtime, library, friends online, currently playing
Applied
Personal. Personal entertainment tracking, scene triggering for games
Professional. Pattern example — pulling activity from a third-party authenticated service into a unified view
Iterated
Demonstrates the API-aggregation pattern
Task tracker
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Tasks, completion timing, classifications
Applied
Personal. Lightweight personal task list integrated with the broader dashboard
Professional. Foundation for any "tasks as byproduct of activity" tooling
Iterated
Counter values are showcase-friendly live data
Usage dashboard
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Application usage patterns
Applied
Personal. Where time actually goes
Professional. Productivity analytics without invasive monitoring
Iterated
Aggregated view, not keystroke-level
Voice commands
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Spoken commands, recognition accuracy, command frequency
Applied
Personal. Hands-free control of common actions
Professional. Voice-driven data entry for environments where typing is impractical (warehouse, lab, clinical). Command frequency analysis identifies which actions deserve dedicated UI
Iterated
On-prem speech recognition possible
Weather/climate
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Local weather conditions, climate readings
Applied
Personal. Input for automations and ambient displays
Professional. Environmental input for facility management
Iterated
Likely API-sourced
Widget creator
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Widget definitions, layout, configuration
Applied
Personal. Compose dashboard surfaces without writing layout code each time
Professional. Internal dashboard builder for teams that need bespoke views without engineering involvement
Iterated
Plan in PLAN_10b_widget_creator.md
API inspector
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Requests, responses, headers, timings, endpoint usage
Applied
Personal. Visibility into what own tools are calling and where they fail
Professional. Foundation for the capture browser concept (section 6). Internal API inventory built from observed traffic
Iterated
Recent addition, in unstaged changes. Related precursor: the website watcher (3.25) does change detection on observed pages. Together with the capture browser (6.1), these form a "watch what is happening on the web" toolchain — passive HTTP/network observation, content change tracking, and full DOM/interaction capture
Claude CLI integration
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Commands, sessions, output, files touched
Applied
Personal. Always-available AI assistance with local context
Professional. Standardized local AI tooling. Session capture for knowledge transfer
Iterated
Recent addition
MCP server for Home Assistant
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
HA entity states exposed via MCP protocol
Applied
Personal. AI tools (Claude) can query and control HA directly
Professional. Pattern example — exposing internal systems to AI via MCP rather than building custom integrations per tool
Iterated
Strategic example of MCP exposure concept
Local tools overlay (chat panel, radial dial)
Need
_What gap or annoyance triggered this work? (Rewrite this section in your voice.)_
Observed
Always-on overlay UI components
Applied
Personal. System-wide UI surface for AI chat and quick controls
Professional. Pattern example — bringing tooling to the user rather than requiring context switching
Iterated
Includes radial dial concept from PLAN_DIAL_OVERHAUL.md