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:

  1. Detect interactive vs non-interactive execution reliably.
  2. Build prompt flows with validation and defaults.
  3. Generate files using templates and structured inputs.
  4. Provide a non-interactive flag-based mode for automation.
  5. 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.json or config.yaml)
  • A project folder with README, LICENSE, and optional files

3.2 Functional Requirements

  1. Prompts: Project name, language, license, features.
  2. Validation: Enforce name rules and required fields.
  3. Templates: Generate files with variables.
  4. Non-Interactive Mode: Flags for every prompt.
  5. 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

  1. Detect if STDIN is a TTY.
  2. If interactive, run prompts with validation.
  3. If non-interactive, read flags and validate.
  4. Render templates into a new directory.
  5. 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

  1. TTY detection
  2. Raw mode behavior
  3. Template rendering
  4. File system safety

5.5 Questions to Guide Your Design

  1. Which prompts must always have flag equivalents?
  2. Do you embed templates or read them from disk?
  3. 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

  1. How do you detect interactive mode?
  2. Why do prompts break in CI?
  3. 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

  1. Non-interactive with missing flags should error.
  2. Invalid project name re-prompts or fails.
  3. 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-run mode
  • 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/template docs

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