8.3 KiB
CLAUDE.md — Vibed Mono-Repo
Repository Structure
This is a mono-repo of self-contained HTTP web services. Each service lives in its own top-level folder and is an independent Rust crate (no Cargo workspace). There is no cross-service communication — each service is a standalone application.
vibed/
├── CLAUDE.md
├── README.md # repo-wide overview with descriptions of each project
├── LICENSE-APACHE
├── LICENSE-MIT
├── flake.nix # base Nix flake — all services inherit or extend this
├── flake.lock
├── common/ # shared library crate (types, utilities, etc.)
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── <service>/
│ ├── Cargo.toml
│ ├── src/
│ │ ├── main.rs
│ │ └── tests.rs # unit tests module
│ ├── tests/ # integration tests
│ ├── docs/
│ │ ├── PLANNING.md # development phases and work logs
│ │ └── ARCHITECTURE.md # component overview and interactions
│ ├── infra/ # OpenTofu infrastructure
│ │ └── main.tf
│ ├── flake.nix # service-specific flake (inherits base)
│ └── README.md # what, how, run, test, license, disclaimer
└── ...
Tech Stack
Language & Tooling
- Language: Rust (all software)
- Local development: Nix with Nix Flakes for dependency management
- Infrastructure: OpenTofu with the Cloudflare provider (stored in each service's
infra/subfolder) - Formatting: Default
rustfmtconventions (no customrustfmt.toml)
Backend
- Framework: Tower + Axum
- Runtime: Tokio
- Target: Cloudflare Workers via workers-rs
- Deployment: OpenTofu with the Cloudflare provider (prefer over wrangler for infrastructure management)
- API format: JSON-encoded request and response payloads
- API spec: Each backend service must have an auto-generated OpenAPI spec. TODO: choose tooling crate.
Frontend
- Framework: Yew (Rust compiled to Wasm)
- Build tool: Trunk (
trunk servefor local dev) - Compile target:
wasm32-unknown-unknown(included in the Nix dev shell via rust-overlay) - Hosting: Cloudflare Pages
Data
- Production database: Cloudflare D1 (SQLite-compatible)
- Local database: Turso (file-backed SQLite)
- Query layer: SQLx
Shared Code
The common/ crate is a shared library for types, utilities, and definitions reused across services. Individual services depend on it via a path dependency in their Cargo.toml:
[dependencies]
common = { path = "../common" }
Chosen Crates
When a crate is chosen to solve a problem, it becomes the standard for that purpose across all services. Add new entries here as decisions are made.
| Purpose | Crate | Notes |
|---|---|---|
This table is intentionally empty. Populate it as crate decisions are made during development.
Secrets & Configuration
- Local:
.envfiles for local secrets. Never commit.envfiles to the repository. - Production: Wrangler secrets (
wrangler secret put <KEY>). - Add
.envto.gitignoreat both the repo root and service level.
Running Services Locally
# Backend service (from the service directory)
cargo run
# Frontend service (from the service directory)
trunk serve
Validation
Run these commands in order from the service directory before committing changes:
cargo fmt # 1. consistent formatting
cargo check # 2. code is syntactically correct
cargo clippy # 3. code follows best practices
cargo test # 4. code is logically valid
Git Conventions
This repository follows Conventional Commits.
Commit messages must use the format:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Common types: feat, fix, docs, style, refactor, test, chore, ci, build.
Use the service name as the scope when the change is scoped to a single service (e.g., feat(my-service): add user endpoint).
License
All code in this repository is dual-licensed under:
This follows standard Rust ecosystem convention. Each service README should reference this dual license.
Code Style & Documentation
Rust
- All public functions, structs, enums, and modules must have rustdoc comments describing how they work.
- Include doc-examples where applicable — these double as doctests.
- Unit tests live in a
testsmodule (tests.rsfile) within the crate's root module or relevant submodules. - Each service has a
tests/directory for integration-style tests.
Infrastructure
- Every OpenTofu
resourceanddatablock must have a comment explaining its purpose.
Release Builds
Release builds must be compiled with settings to minimize binary size. Add this to each service's Cargo.toml:
[profile.release]
opt-level = "z"
lto = true
strip = true
codegen-units = 1
Testing
Structure
- Unit tests:
src/tests.rsmodule (or submodule-localtestsmodules) - Integration tests:
tests/directory at the service root
Coverage
- Target 80%+ code coverage; higher is better.
- TODO: determine coverage tooling (e.g.,
cargo-tarpaulin,cargo-llvm-cov).
Project Documentation
Each service must maintain the following:
README.md
Covers:
- What the project is
- How it works
- How to run it
- How to test it
- License (Apache-2.0 + MIT dual license)
- Disclaimer that the software was written with Claude Code (include the specific model used)
docs/PLANNING.md
- Development phases
- Work logs
- Kept up to date as work progresses
docs/ARCHITECTURE.md
- Component overview
- How components interact
Task Tracking
Tasks are tracked with Beads. The markdown docs (PLANNING, ARCHITECTURE) are for human-readable documentation only — not task management.
Repo-Wide Files
| File | Purpose |
|---|---|
CLAUDE.md |
This file — conventions and instructions for Claude Code |
README.md |
Repo overview with a description of each service |
LICENSE-APACHE |
Apache 2.0 license text |
LICENSE-MIT |
MIT license text |
flake.nix |
Base Nix flake — all service flakes inherit or extend this |
common/ |
Shared library crate for cross-service types and utilities |
Nix
- All local development uses Nix.
- Dependencies are managed with Nix Flakes.
- The repo root has a base
flake.nixthat services should either use directly or inherit and extend with their ownflake.nix.
Task Tracking with nbd
nbd is a CLI tool for managing work tickets, designed for agent workflows.
Initialisation
nbd init
Run once in the project root. Creates .nbd/tickets/. Safe to run multiple times.
Core commands
# Create a new ticket (use --ftype md for a human-readable body)
nbd create --title "Add OAuth login" --type feature --priority 7 --ftype md --json
# List all open tickets (sorted by priority)
nbd list --json
# Read a specific ticket
nbd read <id> --json
# Update a ticket
nbd update <id> --status in_progress --json
nbd update <id> --status done --json
Finding what to work on
# All tickets that are unblocked and ready to start
nbd ready --json
# The single highest-priority unblocked ticket
nbd next --json
Workflow
- Before starting — create a ticket:
nbd create --title "..." --ftype md --json - When starting — mark it in progress:
nbd update <id> --status in_progress --json - When done — mark it complete:
nbd update <id> --status done --json
Guidelines
- Always pass
--jsonto every command for structured, unambiguous output. - Always pass
--ftype mdwhen creating tickets — markdown format keeps the body human-readable. - Use
jqto parse and transform JSON output when needed. - Priority scale 0–10: use 7–9 for bugs, 5 for normal tasks, 3 for nice-to-haves.
--typechoices:project,feature,task,bug.- Use
--deps id1,id2to express blockers — tickets that must be done first. - Create tickets before starting non-trivial tasks, not after.