Adr 006 Drop Local Namespace
Status: Proposed
Date: 2026-01-02
Decision Makers: DocBuilder Core Team
Technical Story: Simplify content structure for preview and build commands
Context and Problem Statement
The preview and build commands are designed for single-project documentation scenarios. Currently, both commands create content with a “local” namespace, resulting in a path structure like:
This namespace adds unnecessary complexity for local, single-project use cases where there’s no need for repository organization. In contrast, multi-repository builds properly use repository names for organization:
The “local” namespace creates:
- Cognitive overhead: Users see “local” paths that serve no organizational purpose
- Menu navigation clutter: Navigation generated from directory structure includes unnecessary nesting
- Navigation links: Links in generated HTML reference
/local/pathcreating the appearance of namespace pollution - Inconsistency: Single-project builds shouldn’t behave differently from how multi-repo builds would without namespace
Decision
We will drop repository namespacing for single-repository builds, producing cleaner content structures:
This simplification will be achieved by detecting single-repository builds and skipping namespace generation, rather than relying on magic strings.
Implementation Details
Solution: Detect Single-Repository Builds
Instead of using “local” as a magic string, detect when there’s only one repository in the entire build:
The isSingleRepo flag is computed at discovery time:
Why This Approach
Pros:
- ✅ No magic strings or special cases
- ✅ Works for ANY single-repository scenario (not just “local”)
- ✅ Semantically correct (namespace exists only when needed for disambiguation)
- ✅ User can have a config with one repository and get clean paths
- ✅ No conflict with “local” forge type
- ✅ Future-proof for single-repo configs
Cons:
- ⚠️ Requires passing context (
isSingleRepo) through discovery pipeline - ⚠️ Slightly more complex than string comparison
Previous “local” Magic String Approach (Rejected)
Initial proposal was to check if df.Repository != "local", but this is problematic because:
- “local” is a forge type (
ForgeLocal), not a repository naming convention- Defined in
internal/config/forge.goasForgeLocal ForgeType = "local" - Has dedicated client:
internal/forge/local.go(LocalClient) - Used for development environments where docs are in current working directory
- Defined in
- Conflates concepts: Forge type vs. repository name are different architectural layers
- Fragile: What if user names their actual repository “local”?
- Arbitrary: Preview/build commands hardcode
Name: "local"with no semantic reason- See
cmd/docbuilder/commands/preview.go:88andbuild.go:306
- See
- Doesn’t generalize: Won’t help users with single-repo configs using other names
Using single-repository detection is architecturally sound and works for all cases.
Impact Analysis
Files affected:
internal/docs/discovery.go: GetHugoPath() signature change (addisSingleRepo boolparameter)internal/docs/discoverer.go: ComputeisSingleRepoflag during discovery- Integration golden tests: Content structure paths change (auto-regenerated)
- No changes to command-line interfaces or configuration format
Repositories affected:
- Preview command: Single repo → no namespace
- Build command (local mode): Single repo → no namespace
- Single-repo configs: No namespace
- Multi-repository builds: Namespaced (unchanged)
Tests updated:
- Golden tests regenerated to expect new path structure
- Unit test added to verify single-repo path generation
Consequences
Benefits
- Cleaner navigation: Users see flatter, more logical menu structures
- Simplified URLs: Links and hrefs no longer include unnecessary “/local/” segments
- Better UX: Single-project scenarios feel native, not namespace-polluted
- Future-proof: Establishes pattern for other single-project features
Risks and Mitigation
- Breaking change for users with custom Hugo templates: Low risk since preview/build are primarily for development
- Mitigation: Document in release notes
- API signature change: GetHugoPath() gains parameter
- Mitigation: Internal API only, no external consumers
- Test maintenance: Golden files need regeneration
- Mitigation: Automated via
go test -update-golden
- Mitigation: Automated via
Testing Strategy
-
Unit Test: Verify GetHugoPath() behavior with single/multi repo flag
-
Integration Tests: Golden tests auto-regenerated
-
Manual Verification:
Related Decisions
- ADR-001: Forge Integration and Daemon Mode — establishes multi-repo support where namespacing is essential
- This ADR reinforces that single-project and multi-project scenarios have different organizational needs
References
- GetHugoPath Implementation:
internal/docs/discovery.go - Preview Command:
cmd/docbuilder/commands/preview.go - Build Command:
cmd/docbuilder/commands/build.go - Golden Test Framework:
test/integration/helpers.go
[adr-006-drop-local-namespace](https://docs.home.luguber.info/_uid/971ae5a9-db88-47b9-8ca3-62406912b554/)