Author SHA1 Message Date
gurix c6bfd2475b Some vibe written content 2025-10-29 11:15:50 +01:00
gurix 937e6a4ded Updated content 2025-10-28 16:43:31 +01:00
4 changed files with 165 additions and 0 deletions
+6
View File
@@ -12,3 +12,9 @@
// }
// Add your custom styles here
.highlight {
pre {
padding: 1em;
}
}
+1
View File
@@ -13,5 +13,6 @@ description: "Offene, ehrliche und nach Sinnhaftigkeit strebende Entwickler-Pers
- 🧘‍♂️ Offene, ehrliche und nach Sinnhaftigkeit strebende Entwickler-Persönlichkeit.
- 🔬 Erfahrungen im wissenschaftlichen Arbeiten und in der Datenanalyse.
- 👨‍💻 Über 20 Jahre Erfahrung in der Konzeption, Entwicklung und Wartung von Software.
- 🤖 KI-Enthusiast fasziniert vom Paradigmenwechsel der Softwareentwicklung und der Freude am Experimentieren.
</div>
</div>
+1
View File
@@ -13,5 +13,6 @@ description: "Open, honest developer personality striving for meaningfulness."
- 🧘‍♂️ Open, honest developer personality striving for meaningfulness.
- 🔬 Experience in academic work and data analysis.
- 👨‍💻 Over 20 years of experience in the conception, development, and maintenance of software.
- 🤖 AI enthusiast fascinated by the paradigm shift in software development and the joy of experimentation.
</div>
</div>
@@ -0,0 +1,157 @@
---
title: "Building a Website with OpenSpec: The Gap Between Theory and Practice"
date: 2025-10-28
draft: false
description: "A skeptical developer's journey through spec-driven development with OpenSpec. What works, what breaks, and the philosophical questions we'd rather ignore."
tags: ["openspec", "spec-driven-development", "hugo", "devtools"]
---
## The Promise
Spec-driven development promises us a world where we think before we code. Write specifications first, they say. Let the AI implement from your carefully crafted requirements. No more cowboy coding, no more "we'll figure it out as we go." Just beautiful, deliberate, documented software evolution.
So naturally, I decided to rebuild my personal website using [OpenSpec](https://openspec.dev/), a framework for managing technical specifications and change proposals. What could go wrong when you apply enterprise-grade process overhead to a simple static website?
Turns out: quite a bit. But also, surprisingly, some things actually worked.
## Day One: The Honeymoon Phase
The initial setup felt... organized. Almost suspiciously so. I created my first change proposal for `add-minimal-hugo-site` following OpenSpec's three-stage workflow:
1. **Stage 1: Creating Changes** - Draft a proposal with the why, what, and impact
2. **Stage 2: Implementing Changes** - Follow the tasks checklist
3. **Stage 3: Archiving Changes** - Clean up after deployment
The structure forced me to answer questions I usually skip: Why am I doing this? What specifically am I building? What will break? For a greenfield Hugo site, these answers were straightforward. The proposal practically wrote itself:
```markdown
## Why
Converting to Hugo will provide a maintainable template-based structure
that simplifies future content updates.
## What Changes
- Initialize Hugo project structure
- Create base layout template with Bootstrap 5.x
- Set up reusable partials (header, footer, navigation)
```
I scaffolded the change with specs for a new `hugo-site` capability, complete with requirements and scenarios. OpenSpec's CLI validated my formatting. Everything was neat. Everything was documented. I felt like a *professional*.
Then I tried to implement it.
## The First Reality Check: Specs Don't Code Themselves
Here's what they don't tell you about spec-driven development: writing "The system SHALL provide a responsive navigation menu" doesn't magically create a navigation menu. I know, shocking.
The specifications guided the *what*, but Hugo's templating engine didn't care about my beautiful requirements. It cared about whether I understood Go template syntax. The spec said:
```markdown
### Requirement: Template Hierarchy
The Hugo site MUST use a template hierarchy with base layout and partials.
#### Scenario: Base layout renders
- **WHEN** any page is requested
- **THEN** baseof.html provides the HTML structure
```
Reality said: "You forgot to put `{{ block "main" . }}{{ end }}` in your baseof.html, you fool."
But here's the thing: when I *did* get it working, I had documentation of what I'd built. Not comments that would drift out of sync, but actual requirements that explained the *intent*. The AI assistant (Claude, in this case) could read the specs and understand the architecture before suggesting changes.
That's... actually useful?
## The Content Migration: When Git Became Your Enemy
The second change proposal, `migrate-site-content`, exposed a painful truth: OpenSpec assumes you're working with code, not content. My specification carefully documented image asset management and content extraction requirements. The git workflow instructions in `CLAUDE.md` demanded feature branches for everything.
So I created a feature branch. Migrated content. Merged to main. Clean history, right?
Except humans don't work that way. Three commits later:
- "Memorize the git workflow"
- "Make git workflow more prominent as it forget before"
The AI kept forgetting to create feature branches. I kept reminding it. It kept apologizing and creating more commits directly on main. We were caught in a loop of spec-driven shame.
The philosophical question: If your process is too rigorous for an AI with perfect memory, is it too rigorous for humans? Or does this reveal something darker about AI's inability to follow long-term project conventions?
## The Deployment Disaster: A Case Study in Iteration
Here's where it gets interesting. The deployment change proposal started as `add-ftps-deployment`. The spec called for FTPS with lftp for mirroring content. Reasonable, right?
```bash
commit: feat: implement FTPS deployment script
commit: fix: improve lftp mirror command for existing directories
commit: refactor: switch from FTPS/lftp to rsync for deployment
commit: refactor: rename deployment change to simple-deployment
```
Four commits. Three approaches. One working deployment script.
The spec said "SHALL deploy via automated script to production server." It didn't specify FTPS. That was a *design decision*, and I put it in the wrong place. OpenSpec has a `design.md` file for technical decisions, but I'd skipped it because "it's just deployment, how hard can it be?"
Turns out the spec was right all along: I needed automated deployment. The *how* was negotiable. FTPS had issues with existing directories. The fix made it more complex. Eventually, I scrapped it for rsync over SSH—simpler, more reliable, actually worked.
**This is spec-driven development at its best**: the requirement remained stable while the implementation evolved. The spec didn't mandate a solution; it mandated an outcome. When I finally renamed the change to `simple-deployment` and updated all the artifacts, the spec accurately reflected what I'd built, not what I'd initially imagined.
## What Actually Worked
Let me be fair to OpenSpec. Several things genuinely improved my process:
**1. Change proposals forced planning.** Even simple changes like adding Bootstrap customization required me to think through the impact. I caught potential issues before writing code.
**2. The validation CLI prevented garbage specs.** `openspec validate --strict` caught malformed scenarios, missing requirements, and structural errors. Can't be sloppy if the tooling won't let you.
**3. AI collaboration improved dramatically.** When Claude Code could read `openspec/specs/deployment/spec.md` and understand not just *what* the deployment script did, but *why* it existed and what guarantees it provided, suggestions became more contextual. Less "here's some random code" and more "this doesn't meet your requirement for error handling."
**4. The archive pattern is brilliant.** Completed changes moved to `changes/archive/` with timestamps. I have a chronological record of every decision. It's like git history, but organized by *feature* instead of time.
## What Didn't Work
But let's not pretend this was frictionless:
**1. The overhead for tiny changes is real.** Adding a language code change required reading the project context, checking for conflicts, and validating specs. For a two-line config tweak, that's like using a jackhammer to hang a picture frame.
**2. The decision tree is fuzzy.** When should you create a proposal versus just fixing directly? OpenSpec says "bug fixes that restore spec behavior" don't need proposals. But what if the spec was wrong? What if "intended behavior" was never specified? You end up in philosophical debates about the nature of bugs.
**3. Specs drift anyway.** Despite the archiving workflow, I found gaps between what the spec *said* and what the code *did*. Not because of laziness, but because implementation details emerged that weren't worth spec'ing. Should I really create an ADDED requirement for "deployment script uses colored terminal output"?
**4. The AI needed constant reminders.** Even with detailed workflow instructions in `CLAUDE.md` and `AGENTS.md`, the assistant repeatedly forgot to create feature branches, validate specs, or update task checklists. If AI can't maintain process discipline, what hope do we humans have?
## The Philosophical Bit
Here's what bothers me about spec-driven development: it assumes we know what we're building before we build it. But discovery *is* part of development.
I didn't know rsync was better than FTPS until I implemented FTPS and hit edge cases. I didn't know I'd need to handle existing directories until the deployment failed. The spec said "SHALL deploy," but the *learning* happened in the doing.
OpenSpec's change proposal workflow accommodates this—you can modify specs mid-implementation, refactor entire approaches, archive and start fresh. But there's tension between "write specs first" and "learn by building." The framework says "decide, then code." Reality says "code, discover, refactor, then retrospectively document what you learned."
Maybe that's okay. Maybe specs aren't predictions; they're *snapshots*. They document what you *currently* understand, not what you'll understand after wrestling with lftp's mirror command for three hours.
## Lessons Learned
After rebuilding my website with OpenSpec, here's what I'd tell another developer:
**Use it for real features, not trivial changes.** If you can implement it in 15 minutes, skip the spec. If it touches multiple systems, adds new capabilities, or involves trade-offs, write it down.
**Separate requirements from design decisions.** Specs should say *what* and *why*. Design docs should debate *how*. When I mixed them, I got brittle specs that broke when implementation details changed.
**Trust the validation tooling.** `openspec validate --strict` is pedantic, but pedantry catches errors. Malformed scenarios don't just look bad; they break AI comprehension.
**Accept that specs will evolve.** You're not carving commandments in stone. You're creating a living document that reflects your current understanding. Refactor specs like you refactor code.
**Don't fight the AI; teach it.** Claude Code can follow OpenSpec workflows if you put the conventions in CLAUDE.md and AGENTS.md. But you'll still need to remind it. That's not a failure; that's collaboration.
**Keep the archive.** Six months from now, you won't remember why you switched from FTPS to rsync. `changes/archive/2025-10-28-simple-deployment/` will. That's worth the overhead.
## The Verdict
Would I use OpenSpec again? For a personal website? Probably not. The process overhead outweighs the benefits when you're the only developer and the stakes are low.
For a real project with multiple contributors, complex requirements, and AI-assisted development? Absolutely. The structure isn't just documentation theater—it's a shared language for humans and AI to coordinate around.
Spec-driven development won't save you from bad decisions. It won't eliminate bugs. It won't make complex systems simple. But it will make you *think* before you code, document what you've built, and give AI assistants the context they need to actually help instead of just hallucinate.
---
*This article was written with the assistance of Claude Code, which ironically had to read the OpenSpec specifications to help me write about reading OpenSpec specifications. The recursion is intentional.*