DEV Community

Cover image for Buzzword Bingo: An Experiment in Spec-Driven AI Development
Christian Ledermann
Christian Ledermann

Posted on

Buzzword Bingo: An Experiment in Spec-Driven AI Development

DEV Weekend Challenge: Passion Edition Submission

This is a submission for Weekend Challenge: Passion Edition

What I Built

I built Buzzword Bingo, a multiplayer bingo game for conferences, webinars and meetings where players mark off the inevitable buzzwords as they appear.

The application allows someone to create a game, share a link with participants, and let everyone play along on their own unique bingo board. The first player to complete a row, column or diagonal wins.

Under the hood, though, the game itself was almost secondary.

The real goal was to answer a question I had been wondering about for a while:

How far can I push Claude with specification-driven development while still achieving reliable type coverage and maintaining the coding standards I expect from a production Python project?

The project became an experiment in AI-assisted software engineering, strict typing, and how much guidance modern coding agents actually need to produce maintainable software.

Demo

There is no live demo, but you can have a look at the screenshots taken by playwright during testing

Code

Repository:

bsbingo GitHub repository

How I Built It

Specification Driven Development

The project followed a specification-driven approach using Speckit.

Rather than iterating directly in code, I created specifications describing what the system should do and allowed Claude to implement them.

A big accelerator for the project was using scaf for the initial bootstrap. Rather than spending the first few hours wiring together repository structure, CI, containerization, infrastructure, and developer tooling, I started from a production-oriented foundation and focused on shaping it to match my own preferences. Having Kubernetes manifests, Terraform, deployment pipelines, and modern Python tooling available from day one made it much easier to concentrate on the actual experiment: how far specification-driven development and AI coding agents could take the application.

I ended up needing three major specifications:

  1. Project scaffolding
  • Starting from a project generated with scaf.
  • Refining the generated structure to match my personal preferences.
  • Adding all the infrastructure and tooling I typically expect in a modern project.
  1. Backend implementation
  • Django models and business logic.
  • Server-rendered templates.
  • HTMX interactions.
  • Capability URL based authorization.
  1. Frontend implementation
  • Visual styling and user experience.
  • Responsive layouts.
  • End-to-end testing using Playwright.

Django Without the JavaScript Framework

The application uses:

  • Django
  • HTMX
  • Django templates
  • PostgreSQL

HTMX turned out to be an excellent fit for this type of application.

Most interactions consist of:

  • clicking a square,
  • sending a POST request,
  • returning an updated HTML fragment,
  • swapping it into the page.

No client-side state management was required.

Capability URLs

One design decision I particularly liked was using capability URLs instead of authentication.

Each board receives a unique UUID:

/board/5b97b663-1f2f-4e54-8d2f-f45f3272f870/
Enter fullscreen mode Exit fullscreen mode

Possession of the URL grants access to that board.

This removes the need for:

  • user accounts,
  • sessions,
  • authentication,
  • authorization logic.

For a lightweight conference game this felt like the right trade-off.

Going All-In On Type Safety

I care a lot about clean code and strong typing in Python, so I decided to push the type system as far as possible.

Instead of relying on a single type checker, I combined:

This was paired with a strict ruff configuration with almost every rule enabled.

One of the goals of the experiment was to see whether Claude could operate effectively within these constraints.

What Worked

This instruction worked well:

Prefer precise, narrow types (Enum, NewType, TypedDict, dataclasses with Final or Literal fields) over Any, untyped dict or list, or stringly-typed values. Illegal states should be unrepresentable in the type system rather than guarded against only at runtime.

Once Claude had a few examples to follow, it started producing significantly better type annotations and more expressive domain models.

Pre-commit hooks proved to be the first line of defence, catching issues before they ever reached CI. Linters, formatters, and all three type checkers ran automatically on every commit, providing rapid feedback and keeping the codebase consistent throughout the experiment.
To avoid spending time hand-crafting the configuration, I used pc-init to generate a strict .pre-commit-config.yaml tailored for modern Python projects. This ensured that formatting, linting, and type checking became part of the development workflow rather than an afterthought.

What Didn't Work

Claude struggled with this instruction:

All Python code MUST be fully type-annotated; untyped function signatures and untyped module-level values are not permitted.

Instead of fixing missing annotations, it occasionally attempted to disable checks in pyproject.toml.

Some manual intervention and code review were required to steer it back towards the desired standards.

The experience reinforced an observation I've made repeatedly with coding agents:

Agents optimize for making the error disappear, not necessarily for preserving your engineering constraints.

If you care about those constraints, you still need strong feedback loops.

Type Checker Observations

Running all three type checkers together was still faster than a single mypy run.

Interestingly, they complemented each other rather than duplicating effort:

  • ty found some issues the others missed.
  • pyrefly found different classes of problems.
  • zuban felt the closest to mypy and was by far the easiest to configure.

The newer type-checking ecosystem is still catching up with mypy in terms of documentation and examples, so reaching the level of strictness I wanted involved a fair amount of experimentation.

Prize Categories

Not submitting for any specific prize category.

The real prize was finding out how far AI-assisted, specification-driven development can be pushed before human review becomes the limiting factor. 😉️

Top comments (0)