Blog post
Building a Personal AI-first Hub as a Path to AI Software Engineer
Why I am building a single-user modular monolith as both a useful personal product and a deliberate training ground for AI-assisted engineering — and why the goal is practical engineering ability, not chasing AI hype.
Related project: ai-first-hub
I am building anton415-hub for two reasons at the same time. The first one is selfish: I want a single-user web application that handles the things I actually do every day — tasks, finance, automation, reading — without the friction of stitching SaaS products together. The second one is structural: I want every part of that system to be reviewable evidence of engineering work, produced by an AI-assisted workflow that I can defend in a hiring conversation.
The path from “I write code” to “AI Software Engineer” doesn’t run through a course. It runs through a repository that survives contact with production and an authoring workflow that survives contact with real architectural decisions.
The hub is both the product and the learning system
It would have been easier to fork a starter, drop in Copilot, and ship a personal todo app. That path produces something that works. It does not produce something that demonstrates anything — there is no specification, no ADR, no test pinning a real invariant, no boundary that a careless edit would have to argue with.
The hub takes the harder shape on purpose:
- Real auth. Yandex ID OAuth with an email allow-list. No
Basicheader, no skipped login. - Real persistence. PostgreSQL 16 with proper FK and CHECK constraints. Numbered
.up.sql/.down.sqlmigration pairs, applied bygolang-migrateon every deploy. - Real deploys. A multi-stage Dockerfile, GitHub Actions CI, release-triggered deploy to a single Yandex Cloud VM behind Caddy, smoke-checked on
/health. - Real boundaries. Ports-and-adapters per module with the dependency direction
adapters → application → domainenforced by the package graph — a domain file that importspgxdoes not compile.
That structure is the training ground. Every change I want to make has to fit inside a layer, has to land in a small named file, and has to be reviewable in a single PR with an Evidence Link. The discipline isn’t theoretical — it’s the only way the system keeps working as I add modules. See the full picture in the AI-first Hub case study.
The goal is not chasing AI hype
There’s a version of “AI-first” that means talk about AI a lot. A landing page covered in shimmering gradients, a “powered by Claude” badge, a demo that’s really three prompts in a trench coat. I’m not optimizing for that.
What I am optimizing for is a specific transferable skill: working productively with AI tools without losing engineering judgment. That looks like:
- Knowing which kinds of changes are AI-safe (writing a SQL adapter from a clear interface) and which ones aren’t (negotiating the interface in the first place).
- Knowing how to write the kind of specification an agent will actually follow.
- Knowing how to enforce architectural boundaries in CI so an agent — or a tired human — can’t accidentally cross them.
- Knowing when to stop and ask, and when to ship.
None of those are AI features. They are engineering practices that happen to be load-bearing once AI tools are in the loop.
Practical engineering ability around AI-assisted development
Three tools, three roles, one human approval gate:
- ChatGPT — problem analysis, scope drafting, specification writing. It writes the SPEC before any code is written.
- Claude Code — architecture review, ADRs, layer-respecting implementation, codebase navigation. It writes inside the layer the file lives in.
- Codex — visual polish on the frontend, after the routes, content, and architecture are fixed.
- Anton (human) — every PR, sole owner of merges to
main, single Evidence Link per phase.
The boundaries between those roles matter as much as the tools themselves. Claude Code doesn’t write a SPEC; ChatGPT doesn’t touch the codebase; Codex doesn’t move the architecture. The handoffs are explicit because the tools are different and their failure modes are different.
The boundaries that matter inside the code — layer dependencies, public/private isolation, deploy guardrails — are enforced by the build, not by reviewer vigilance. The public site and the private SPA live as separate npm packages so an accidental cross-import doesn’t even compile, and a CI guard blocks the public-site source from referencing the private package by name. Changes under deploy/, migrations/, Dockerfile, docker-compose*.yml, Caddyfile, or .github/workflows/ require explicit per-PR approval. None of those rules live only in a doc.
Why this post is the first one
I want the blog to be a technical narrative tied to real merged work, not a motivational diary. This post exists because the hub itself is the most important context for everything else I’m going to write: the next post on specification-driven development, the Todo case study, the tool-split post, the modular-monolith argument — they all assume you know what hub they’re about and why it exists.
If you want to skip ahead, the place to look is the AI-first Hub case study and the repository at github.com/anton415/anton415-hub. Every claim on the CV links to evidence in the same repo.