Project 3: init-wizard
Build an interactive project initializer with prompts, validation, and templates.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Level 2 (Intermediate) |
| Time Estimate | 1 week |
| Language | Go (Alternatives: Rust, Node.js) |
| Prerequisites | CLI basics, file I/O, JSON/YAML |
| Key Topics | TTY input, prompt UX, templating |
1. Learning Objectives
By completing this project, you will:
- Detect interactive vs non-interactive execution reliably.
- Build prompt flows with validation and defaults.
- Generate files using templates and structured inputs.
- Provide a non-interactive flag-based mode for automation.
- Design UX that prevents accidental overwrites.
2. Theoretical Foundation
2.1 Core Concepts
- Interactive vs Non-Interactive: If STDIN is not a TTY, prompts must be disabled to avoid hanging CI or scripts.
- Terminal Modes: Prompt libraries use raw mode to capture arrow keys and selections.
- Input Validation: Validating at entry time prevents broken project output.
- Templating: Structured templates let you build files consistently across projects.
2.2 Why This Matters
Project scaffolding is a recurring workflow in real teams. A strong initializer reduces onboarding time, enforces conventions, and prevents repeated manual setup errors.
2.3 Historical Context / Background
Tools like npm init, cargo new, and rails new proved that interactive CLIs can be both user-friendly and scriptable. Your tool should match that standard.
2.4 Common Misconceptions
- “Prompts are always better”: In automation they are harmful.
- “Validation can wait”: Bad input breaks templates and confuses users.
3. Project Specification
3.1 What You Will Build
A CLI named init-wizard that asks for project details and generates:
- A config file (
config.jsonorconfig.yaml) - A project folder with README, LICENSE, and optional files
3.2 Functional Requirements
- Prompts: Project name, language, license, features.
- Validation: Enforce name rules and required fields.
- Templates: Generate files with variables.
- Non-Interactive Mode: Flags for every prompt.
- Summary: Preview before writing.
3.3 Non-Functional Requirements
- Usability: Clear prompts, sane defaults.
- Safety: No overwrite without confirmation.
- Portability: Linux, macOS, Windows.
3.4 Example Usage / Output
? Project name: sample-app
? Language: Go
? License: MIT
? Features: Docker, CI
3.5 Real World Outcome
After the wizard finishes, the user sees a full scaffold on disk:
$ init-wizard --name sample-app --language go --license MIT
Created sample-app/
Created sample-app/README.md
Created sample-app/LICENSE
Created sample-app/config.json
Created sample-app/.gitignore
Opening sample-app/README.md shows templated content with the chosen name, license, and features. The config file contains normalized values suitable for automation.
4. Solution Architecture
4.1 High-Level Design
+----------------+ +------------------+ +--------------------+
| Prompt Engine | --> | Validation Layer | --> | Template Renderer |
+----------------+ +------------------+ +--------------------+
| | |
+----------------------+------------------------+
Project model
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Prompt UI | Ask questions | Library choice |
| Validator | Enforce rules | Regex vs custom |
| Renderer | Apply templates | Embedded vs external |
| Writer | Create files | Safe overwrite rules |
4.3 Data Structures
type ProjectConfig struct {
Name string
Language string
License string
Features []string
}
4.4 Algorithm Overview
Key Algorithm: Wizard flow
- Detect if STDIN is a TTY.
- If interactive, run prompts with validation.
- If non-interactive, read flags and validate.
- Render templates into a new directory.
- Print summary and exit.
Complexity Analysis:
- Time: O(F) for F generated files
- Space: O(F) for template output
5. Implementation Guide
5.1 Development Environment Setup
brew install go
mkdir init-wizard && cd init-wizard
go mod init init-wizard
5.2 Project Structure
init-wizard/
├── cmd/
│ └── root.go
├── internal/
│ ├── prompts/
│ ├── validate/
│ └── render/
├── templates/
│ ├── README.md.tmpl
│ ├── LICENSE.tmpl
│ └── config.json.tmpl
└── README.md
5.3 The Core Question You Are Answering
“How do I design a CLI that feels interactive and friendly without breaking automation?”
5.4 Concepts You Must Understand First
- TTY detection
- Raw mode behavior
- Template rendering
- File system safety
5.5 Questions to Guide Your Design
- Which prompts must always have flag equivalents?
- Do you embed templates or read them from disk?
- How will you handle existing directories?
5.6 Thinking Exercise
Design a prompt flow: which prompts depend on earlier answers? Draw it as a tree.
5.7 The Interview Questions They Will Ask
- How do you detect interactive mode?
- Why do prompts break in CI?
- How do you prevent template injection?
5.8 Hints in Layers
Hint 1: Start with a single prompt and one generated file.
Hint 2: Add --name and --language flags to bypass prompts.
Hint 3: Add summary confirmation before writing to disk.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| CLI UX | “Command Line Interface Guidelines” | clig.dev |
| Terminal I/O | “Advanced Programming in the UNIX Environment” | Ch. 18 |
5.10 Implementation Phases
Phase 1: Foundation (2-3 days)
Goals:
- Basic prompts
- Generate one file
Checkpoint: Wizard produces a config file.
Phase 2: Core Functionality (2-3 days)
Goals:
- Full prompt flow
- Validation rules
Checkpoint: Invalid input is rejected cleanly.
Phase 3: Polish (1-2 days)
Goals:
- Non-interactive flags
- Summary confirmation
Checkpoint: Flags work without prompts.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| Templates | Embedded vs external | Embedded | Simple distribution |
| Prompt lib | Survey vs custom | Library | Less edge-case handling |
| Validation | Regex vs custom | Custom | Better errors |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Unit Tests | Validators | project name rules |
| Integration Tests | CLI flow | flags-only mode |
| Edge Cases | Existing dir | refuse overwrite |
6.2 Critical Test Cases
- Non-interactive with missing flags should error.
- Invalid project name re-prompts or fails.
- Existing folder blocks or confirms.
6.3 Test Data
Name: "bad name" -> invalid
Name: "my-app" -> valid
7. Common Pitfalls and Debugging
| Pitfall | Symptom | Solution |
|---|---|---|
| Prompts in CI | Command hangs | Detect non-TTY and require flags |
| Template errors | Broken output files | Validate and sanitize inputs |
| Overwrite data | User data loss | Confirm before writing |
8. Extensions and Challenges
8.1 Beginner Extensions
- Add
--dry-runmode - Add
--output-dir
8.2 Intermediate Extensions
- Add language template packs
- Add preset profiles
8.3 Advanced Extensions
- Add plugin-based template loaders
- Add remote template registry
9. Real-World Connections
- Scaffolding tools in dev platforms
- Company-wide template standardization
10. Resources
- clig.dev
text/templatedocs
11. Self-Assessment Checklist
- I can explain interactive vs non-interactive modes
- I can implement template rendering safely
12. Submission / Completion Criteria
Minimum Viable Completion:
- Interactive prompts generate a project folder
Full Completion:
- Validation and non-interactive flags
Excellence (Going Above and Beyond):
- Template packs and dry-run support