Feature: Unified dev-template with Registry Browsing (Phase A)
IMPLEMENTATION RULES: Before implementing this plan, read and follow:
- WORKFLOW.md - The implementation process
- PLANS.md - Plan structure and best practices
Status: Completed​
Completed: 2026-04-04
Goal: Merge dev-template.sh and dev-template-ai.sh into one unified dev-template command that uses template-registry.json for browsing and supports install_type routing (app/overlay).
Last Updated: 2026-04-04
Investigation: helpers-no/dev-templates -> INVESTIGATE-unified-template-system.md (all three contributors confirmed)
Depends on: TMP Phase 1 -- template-registry.json published on live Docusaurus site
No UIS dependency -- this phase works without UIS. Phase B (separate plan) adds service integration.
Overview​
Replace two scripts with one. Replace sparse-checkout-for-browsing with curl-a-small-JSON-file. Route installation by install_type field instead of by which script is running.
Before:
dev-template-- app templates only, sparse-checkouts entiretemplates/folderdev-template-ai-- AI templates only, sparse-checkouts entireai-templates/folder- Two commands, two scripts, hardcoded category routing
After:
dev-template-- all DCT templates (app, AI, doc, rules), browses from registry JSONdev-template-ai-- removed (symlink todev-templatewith--context aior just removed)- One command, one script,
install_typeroutes to handlers
Flow:
curlregistry JSON from TMP Docusaurus site (small file, instant)- Filter by
context: dct, build two-level menu withjq - User picks category -> template -> details -> confirm
- Sparse-checkout only the selected template's folder
- Read
template-info.yamlforinstall_type,tools,readme - Route to handler:
apporoverlay - Install tools, replace placeholders, show completion
Phase 1: Fetch and parse registry JSON​
Tasks​
- 1.1 Add
fetch_registry()totemplate-common.sh:- Primary:
curl -sL "https://tmp.sovereignsky.no/data/template-registry.json" - Fallback:
curl -sL "https://raw.githubusercontent.com/helpers-no/dev-templates/main/website/src/data/template-registry.json" - Save to
$TEMP_DIR/registry.json - Error handling: clear message if both URLs fail
- Primary:
- 1.2 Add
parse_registry_categories()-- extract DCT categories usingjq:- Filter by
context: dct - Build
CAT_IDS[],CAT_NAMES[],CAT_EMOJIS[],CAT_COUNTS[]from JSON
- Filter by
- 1.3 Add
parse_registry_templates()-- extract templates per category:- Build
TEMPLATE_DIRS[],TEMPLATE_NAMES[],TEMPLATE_DESCRIPTIONS[]etc. from JSON - Populate
CAT_TEMPLATES[]with indices per category
- Build
- 1.4 Remove
load_template_categories()(was sourcing bashTEMPLATE_CATEGORIES) - 1.5 Replace
scan_templates()with registry-based parsing (no directory scanning)
Validation​
Menu builds from registry JSON. No git operations for browsing.
Phase 2: Download only the selected template​
Tasks​
- 2.1 After user confirms selection, sparse-checkout only that template's folder:
- Read
folderfield from registry:jq -r '.templates[] | select(.id == "...") | .folder' git sparse-checkout set "$folder"
- Read
- 2.2 Read
template-info.yamlfrom the downloaded template (replaces bashTEMPLATE_INFO)- Parse with a simple YAML-to-variable approach (or rely on registry JSON which already has all fields)
- 2.3 Copy
template-info.yamlto project root for all install types (Decision #12) - 2.4 Remove full-folder sparse-checkout (was downloading everything upfront)
Validation​
Only the selected template folder is downloaded. template-info.yaml copied to project.
Phase 3: install_type routing​
Tasks​
- 3.1 Add
install_typehandler dispatch intemplate-common.sh:case "$install_type" in
app) install_app_template ;;
overlay) install_overlay_template ;;
esac - 3.2 Move
dev-template.shapp-specific logic intoinstall_app_template():verify_template()-- check manifests/deployment.yamlcopy_template_files()-- copy to rootsetup_github_workflows()-- copy .github/merge_gitignore()-- merge .gitignoreprocess_template_files()-- replace{{GITHUB_USERNAME}}and{{REPO_NAME}}in YAML
- 3.3 Move
dev-template-ai.shoverlay-specific logic intoinstall_overlay_template():verify_template()-- check template/ subdirectorycopy_template_files()-- copy template/ preserving paths, safe re-runhandle_claude_md()-- CLAUDE.md conflict handlingrename_project_template()-- rename project-TEMPLATE.mdprocess_template_files()-- replace{{REPO_NAME}}in .md files
- 3.4 Both handlers call shared:
install_template_tools(), show completion with README
Validation​
App templates and overlay templates both work through the unified command.
Phase 4: Merge into one script​
Tasks​
- 4.1 Create unified
dev-template.shwith:fetch_registry()instead ofdownload_template_repo()+scan_templates()select_template()using registry-based two-level menuinstall_typedispatch after selection- Both
detect_and_validate_repo_info()variants (app needs GIT_ORG, overlay only needs GIT_REPO) - Both
cleanup_and_complete()variants (app vs overlay completion messages)
- 4.2 Remove
dev-template-ai.sh - 4.3 Remove
dev-template-aisymlink from Dockerfile - 4.4 Update
--helptext to show all template types - 4.5 Keep backward compatibility:
dev-template plan-based-workflow(direct selection by name still works across all template types)
Validation​
One dev-template command handles all DCT template types.
Phase 5: Testing​
Tasks​
- 5.1 Test
dev-templateinteractive -- two-level menu shows all DCT categories (app + AI) - 5.2 Test
dev-template python-basic-webserver-- direct selection, app install_type - 5.3 Test
dev-template plan-based-workflow-- direct selection, overlay install_type - 5.4 Test
dev-template jalla-- error lists all available templates - 5.5 Test ESC navigation at all levels
- 5.6 Test tool install (TEMPLATE_TOOLS) works for both types
- 5.7 Test TEMPLATE_README shows in completion for both types
- 5.8 Test CLAUDE.md conflict handling (overlay type)
- 5.9 Test
--helpshows unified help - 5.10 Verify
dev-template-aicommand no longer exists - 5.11 Test registry fallback URL when primary fails
Validation​
All tests pass. One command replaces two. No regression.
Acceptance Criteria​
- Single
dev-templatecommand handles app and overlay templates - Registry JSON fetched via curl -- no git operations for browsing
- Only selected template downloaded via sparse-checkout
-
install_type: approutes to app handler (manifests, workflows, gitignore) -
install_type: overlayroutes to overlay handler (template/ copy, CLAUDE.md, safe re-run) -
template-info.yamlcopied to project root for all types - Direct selection by name works across all template types
- Tool install and README display work for both types
-
dev-template-airemoved -
--helpupdated - Backward compatible -- existing templates work unchanged
Implementation Notes (issues encountered)​
1. Bash read collapses empty TSV fields​
jq @tsv output with empty fields (e.g., tools is "") produces consecutive tabs. Bash IFS=$'\t' read collapses these, causing all subsequent fields to shift left. The folder field got the install_type value, etc.
Fix: Used a jq nonempty function to replace empty/null values with "-" sentinel, then replaced back to empty after reading.
2. MDX breaks on curly braces in plan files​
Docusaurus treats {{GITHUB_USERNAME}} in markdown as a JSX expression and fails with ReferenceError: GITHUB_USERNAME is not defined.
Fix: Escaped curly braces with HTML entities: {{GITHUB_USERNAME}}. This is a recurring issue — any plan file with template placeholder syntax needs escaping.
3. Broken links when plans move from backlog/active to completed​
Relative links like ../backlog/INVESTIGATE-foo.md break when both the plan and the investigation move to completed/ (becomes a same-directory link). This happened twice during this project.
Fix: Updated the link path after move. Future plans should use absolute paths or avoid cross-referencing files that may move.
4. Registry primary URL not yet deployed​
The Docusaurus site URL (tmp.sovereignsky.no/data/template-registry.json) returned 404 because TMP's CI hadn't deployed yet. The GitHub raw fallback worked.
Fix: The fallback mechanism worked as designed. Both URLs should be checked in order.
Files Modified​
.devcontainer/manage/lib/template-common.sh-- complete rewrite: registry parsing withjq, category/template arrays, two-level menu, sentinel handling for empty TSV fields.devcontainer/manage/dev-template.sh-- unified script withinstall_typerouting (app/overlayhandlers).devcontainer/manage/dev-template-ai.sh-- deletedimage/Dockerfile-- removeddev-template-aisymlink