{"slug": "from-template-to-production-shaped-an-ai-native-dev-flow-for-go-side-projects", "title": "From Template to Production-Shaped: An AI-Native Dev Flow for Go Side Projects", "summary": "A developer built a production-grade QR code generator as a Go side project using a structured AI workflow called \"qrspi\" (question, research, structure, plan, implement) to avoid the typical scaffolding overhead. The project, available on GitHub at linkc0829/go-qrcode-generator, features hexagonal architecture with strict dependency enforcement through depguard rules that prevent domain code from importing infrastructure packages. The developer documented explicit deviations from the original system design specification, including replacing deterministic token generation with crypto/rand-based base64url tokens to eliminate leak surfaces.", "body_md": "I wanted my next side project to *look* like the kind of code I'd ship at work — hexagonal architecture, sqlc, depguard, integration tests — without the usual side-project tax of spending three evenings on scaffolding before writing the first line of domain logic. So I built it twice. First, I forked a Go backend template I'd been hardening for months. Then I drove every feature on top of it through a structured AI workflow I call **qrspi**: *question → research → structure → plan → implement*.\n\nThe product itself is unremarkable on purpose: a QR code generator. Paste a URL, get back a scannable PNG and a `/r/:token`\n\nredirect, with per-link scan counts and a soft-delete kill switch. The interesting part — the part I'd want a reviewer to look at — is the *process* that produced it.\n\nRepo: [linkc0829/go-qrcode-generator](https://github.com/linkc0829/go-qrcode-generator). Every artifact mentioned in this post is committed there.\n\nStep zero was actually choosing what to build on. I shortlisted several Go backend templates, walked through each one with Claude to pressure-test the architecture, and landed on the one I'd been hardening for a while: [linkc0829/go-backend-template](https://github.com/linkc0829/go-backend-template).\n\nThe template is a feature-first hexagonal Go backend. Each feature lives in a single package under `internal/<feature>/`\n\n, and inside that package, `domain.go`\n\n, `service.go`\n\n, `ports.go`\n\n, and the adapters sit side-by-side as separate files. The Go package boundary *is* the hexagon edge.\n\nWhat makes it stick is `depguard`\n\nin `.golangci.yml`\n\n. The build fails if:\n\n`domain.go`\n\nimports anything beyond stdlib and shared value objects`service.go`\n\nreaches for a driver or web framework`handler_*.go`\n\ntouches a repo or cache directlyThat last rule is the one that pays the most rent. Cross-feature dependencies are forced through **capability ports** — feature A defines an interface named after the capability it needs, and the composition root in `internal/bootstrap/wire.go`\n\ninjects feature B's service to satisfy it. The features never know about each other.\n\nThis was the first decision I had to actually live with. The template ships with demo `user`\n\n, `order`\n\n, and `payment`\n\nslices. My project has no orders and no payments. The rule is: don't leave dead code as \"future scaffolding.\" Delete the whole slice — the package, the wire block, the SQL queries, the migration tables, the OpenAPI paths, the depguard block. `make lint && make test`\n\nafter each removal flushes out dangling references. By the time I started writing QR code logic, the repo only knew about things that existed.\n\nThe functional spec came from a system-design exercise I'd worked through separately:\n\nThe high-level design called out the load shape — read-heavy, one write to thousands of reads — and the levers that fall out of it: stateless API behind a gateway, cache `qr_token → image_url`\n\n, CDN the PNGs, index on `qr_token`\n\n. Tokens were originally specified as `base62(SHA-256(url + user_secret))`\n\n.\n\nFor the local build, I wrote down explicit **deviations** from the spec rather than pretending they didn't exist:\n\n`crypto/rand`\n\n→ `base64url`\n\n. Loses idempotency for repeated (user, url) pairs but avoids the deterministic-token leak surface.`download`\n\nbucket policy. Same architectural shape as S3+CloudFront, minus the edge cache.Writing the deviations down up front is the part that makes the design honest. It's also the part that makes a portfolio reviewer's job easier — they can see *what was traded and why*, not just what got built.\n\nThe workflow idea started from [Research-Plan-Implement](https://github.com/humanlayer/advanced-context-engineering-for-coding-agents) (RPI). QRSPI is an 8-phase extension of it that I picked up from community discussions and adapted for this project.\n\nOnce the spec was on paper, every feature went through the same eight phases. Each phase is a slash command backed by a skill, and each one writes its artifact to `thoughts/qrspi/<date>-<slug>/`\n\n:\n\n`/qrspi:1_question`\n\n`/qrspi:2_research`\n\n`/qrspi:3_design`\n\n`/qrspi:4_structure`\n\n`/qrspi:5_plan`\n\n`/qrspi:6_worktree`\n\n`/qrspi:7_implement`\n\n`/qrspi:8_pr`\n\nThe MinIO feature shows the whole thing on disk: a `ticket.md`\n\npulled from the Notion source via MCP, then `questions.md`\n\n, `research.md`\n\n, `design.md`\n\n, `structure.md`\n\n, and `plan.md`\n\n. Each one builds on the last. By the time implementation starts, the agent isn't guessing — it's executing a plan I already agreed with.\n\nThe follow-up Redis redirect cache shipped the same way. The plan called out the read-heavy shape, picked a write-behind click-count buffer to avoid hammering Postgres on every scan, and named the cache invariants explicitly. The implementation was almost mechanical because the design phase had already resolved the interesting questions.\n\nThe cost is real: each feature carries five or six markdown files of design artifacts. For a single-developer side project, that's overhead I wouldn't tolerate in a freeform sketch.\n\nWhat it buys:\n\n`design.md`\n\n, in `plan.md`\n\n— keeps the next session grounded.The template is on GitHub; the qrspi artifacts are committed alongside the code. If you want to see how a single feature flows from ticket to PR, [the MinIO slice](https://github.com/linkc0829/go-qrcode-generator/tree/main/thoughts/qrspi/2026-05-15-minio-local-object-storage) is the cleanest example. The architecture ADRs in `docs/adr/`\n\ncover the two foundational decisions: feature-first hexagonal, and sqlc over an ORM.\n\nNext up: a metrics slice (Prometheus + a Grafana dashboard for redirect latency), and a proper deletion follow-up so the spec's full CRUD surface lands. Both will go through qrspi. That's the point.", "url": "https://wpnews.pro/news/from-template-to-production-shaped-an-ai-native-dev-flow-for-go-side-projects", "canonical_source": "https://dev.to/kanchen_lin_331136af621d/from-template-to-production-shaped-an-ai-native-dev-flow-for-go-side-projects-245g", "published_at": "2026-05-26 02:07:42+00:00", "updated_at": "2026-05-26 02:33:39.732502+00:00", "lang": "en", "topics": ["ai-tools", "ai-products", "generative-ai", "artificial-intelligence", "large-language-models"], "entities": ["Claude", "linkc0829", "go-backend-template", "go-qrcode-generator"], "alternates": {"html": "https://wpnews.pro/news/from-template-to-production-shaped-an-ai-native-dev-flow-for-go-side-projects", "markdown": "https://wpnews.pro/news/from-template-to-production-shaped-an-ai-native-dev-flow-for-go-side-projects.md", "text": "https://wpnews.pro/news/from-template-to-production-shaped-an-ai-native-dev-flow-for-go-side-projects.txt", "jsonld": "https://wpnews.pro/news/from-template-to-production-shaped-an-ai-native-dev-flow-for-go-side-projects.jsonld"}}