Skip to content

feat: Interactive init wizard + Gum UI integration - #2

Merged
devalade merged 22 commits into
devalade:mainfrom
mouwaficbdr:feature/enhanced-interactive-wizard
Jan 27, 2026
Merged

feat: Interactive init wizard + Gum UI integration#2
devalade merged 22 commits into
devalade:mainfrom
mouwaficbdr:feature/enhanced-interactive-wizard

Conversation

@mouwaficbdr

Copy link
Copy Markdown

Interactive Setup Wizard for shipnode init

This PR introduces an interactive setup wizard for shipnode init, featuring framework auto-detection, smart defaults, and strong input validation, with optional Gum-powered UI and graceful fallback.


What’s New

Interactive Wizard

  • Enabled by default via shipnode init
  • Legacy behavior preserved with --non-interactive
  • Framework auto-detection:
    • Express, NestJS, Next.js
    • React, Vue, Svelte, SolidJS, Angular
    • Fastify, Koa, Hapi, Hono
    • Nuxt, Remix
  • Smart defaults inferred from package.json:
    • Application type
    • Port
    • PM2 process name
  • Input validation:
    • IP / hostname
    • Port range
    • Domain format
    • PM2 process name
  • Configuration summary before generating shipnode.conf
  • Optional users.yml generation workflow

Gum Integration

  • Interactive UI powered by charmbracelet/gum when available
  • Automatic installation during shipnode setup:
    • apt, dnf/yum, brew, apk, pacman
  • Graceful fallback to classic prompts when Gum is unavailable
  • TTY detection with automatic fallback in CI/CD environments
  • Gum wrapper helpers with fallback:
    • gum_input
    • gum_choose
    • gum_confirm
    • gum_style

Quality Improvements

  • JSON validation before parsing package.json
  • Improved port detection patterns:
    • PORT=
    • --port
    • localhost:
    • listen()
  • Scoped package name sanitization:
    • Collapses multiple dashes
    • Preserves dots and underscores
  • Gum installation failure logs written to:
    • /tmp/shipnode_gum_install_<PID>.log
  • Added comprehensive function docstrings
  • README troubleshooting section expanded:
    • Gum installation
    • Detection behavior
    • CI/CD
    • SSH environments

Backward Compatibility

  • shipnode init --non-interactive preserves original behavior
  • Fallback prompts ensure functionality:
    • Without Gum
    • In non-TTY or automated environments

Implement comprehensive interactive wizard for `shipnode init` command with smart defaults and validation.

Features:
- Framework auto-detection (Express, NestJS, Fastify, Koa, Hapi, Hono, Next.js, Nuxt, Remix, React, Vue, Svelte, SolidJS, Angular)
- Intelligent app type suggestion (backend vs frontend)
- Port auto-detection from package.json scripts
- Real-time input validation (IP/hostname, port, domain, PM2 name)
- Guided prompts with smart defaults from package.json
- Configuration summary with confirmation
- Backward compatibility via `--non-interactive` flag

Implementation:
- Added `detect_framework()` to parse package.json dependencies
- Added `suggest_app_type()` and `suggest_port()` for smart defaults
- Added 5 validation functions for user inputs
- Added `prompt_with_default()` and `prompt_with_validation()` helpers
- Created `cmd_init_interactive()` with 10-step wizard flow
- Refactored existing `cmd_init()` to `cmd_init_legacy()`
- Updated help command documentation

Testing:
- Validated framework detection with example projects
- Tested backward compatibility with --non-interactive flag
- Verified validation functions with edge cases

Addresses roadmap item mentioned in README.md lines 892-909
- Updated README Quick Start with interactive wizard workflow example
- Added comprehensive CHANGELOG unreleased section
- Documented all new functions and features
- Included backward compatibility notes for --non-interactive flag
Improve user experience by adding contextual help text after each prompt:
- SSH connection section: explain what each field is for
- Deployment path: clarify where files will be deployed
- Backend config: explain port usage and domain purpose
- Frontend config: add note about domain requirement for Caddy
- Better section headers with descriptions

This makes the wizard more beginner-friendly and self-documenting.
Prevent accidental commits of users.yml which contains sensitive information:
- User email addresses
- Password hashes
- SSH public keys
- System usernames

Only example files (*.example) should be tracked in version control.
Adjust padding to ensure the welcome banner borders are perfectly aligned.
- Security: Replace eval with printf -v to prevent command injection
- Fix: Validate IP octets with base-10 to handle leading zeros correctly
- Improve: Use word boundaries in framework detection regex to avoid false positives
- UX: Display help text before prompts instead of after
- Fix: Handle scoped npm packages (@scope/name) in app_name generation
- Improve: Capture and display jq parsing errors for better debugging
- Restore: Add back users.yml example file (examples are safe, not real credentials)
Clean up app_name extraction by removing trailing dashes that may
result from newline conversion in package.json name field.
Add Gum UI framework integration to enhance the interactive wizard experience
while maintaining full backward compatibility.

Features:
- Gum detection (has_gum() function)
- Automatic fallback to classic bash prompts when Gum is not installed
- Wrapper functions: gum_input(), gum_choose(), gum_confirm(), gum_style()
- Informative tip shown when Gum is available: show_gum_tip()

The wizard continues to work identically without Gum, with enhanced UI when
Gum is installed. This provides progressive enhancement without breaking
changes or new dependencies.

Implementation uses USE_GUM global flag set at script initialization to
determine which UI mode to use throughout the wizard flow.
Enhance the interactive wizard with Gum UI components for better visual
experience while maintaining full backward compatibility.

Changes:
- Welcome banner: Uses gum style with double border, center alignment,
  and custom colors when Gum is available
- App type selection: Interactive gum choose menu with cursor indicators
  instead of numbered list
- Automatic fallback: Both features fall back to classic bash prompts when
  Gum is not installed
- Added show_gum_tip() call to inform users about enhanced mode

The wizard automatically detects Gum and uses enhanced UI when available,
or falls back to the classic experience seamlessly.
Integrate Gum UI components into all wizard prompts for a modern, polished
interactive experience while maintaining full fallback compatibility.

Changes:
- SSH credentials: gum input with placeholders for user, host, and port
- Deployment path: gum input with suggested path
- Backend config: gum input for PM2 name, port, and optional domain
- Frontend config: gum input for required domain with validation
- Configuration summary: gum style with rounded border and clean formatting
- Final confirmation: gum confirm for Yes/No decision
- All inputs maintain validation loops and error messages
- Seamless fallback to classic prompts when Gum is not available

The wizard now provides a significantly enhanced UX with Gum while preserving
100% backward compatibility for users without Gum installed.
Implements automatic installation of the Gum UI tool during the
`shipnode setup` command to provide a better user experience with
the interactive wizard.

New features:
- detect_os(): Detects OS and package manager (apt, yum, dnf, brew,
  apk, pacman)
- install_gum(): Automatically installs Gum via the detected package
  manager
- Multi-platform support: Debian/Ubuntu, RedHat/Fedora, Arch, Alpine,
  macOS
- Non-blocking installation: Wizard continues in classic fallback mode
  if installation fails
- Existing installation detection: Skips if Gum is already installed
- Clear and informative user messages

Changes:
- cmd_setup(): Added Gum installation step after SSH checks
- README.md: Added Gum to features and Quick Start sections
- CHANGELOG.md: Documented the new functionality

Installation is optional and graceful - in case of failure, the wizard
uses classic bash prompts without blocking the workflow.
Add upfront JSON validation in parse_package_json() to catch
malformed package.json files early and provide clear error messages.
This prevents cryptic jq parsing errors downstream.

Changes:
- Add jq empty check before dependency extraction
- Return early with clear warning for invalid JSON
- Maintain backward compatibility with existing error handling
Replace overly broad regex that could match timestamps or line numbers
with targeted patterns for common port declaration methods.

Changes:
- Add priority-based matching for PORT=, --port, localhost:, listen()
- Add port range validation (1-65535)
- Avoid false positives from timestamps like "eslint:3000"
- Maintain backward compatibility with existing port detection

Tested patterns:
- Environment variables: PORT=3000
- CLI flags: --port=5000, --port 8080
- URLs: localhost:4000, 127.0.0.1:9000
- Code patterns: listen(:3000)
Fix app_name extraction from package.json to handle edge cases and
prevent invalid PM2 process names with multiple consecutive dashes.

Changes:
- Preserve dots and underscores (valid in PM2 names)
- Collapse multiple consecutive dashes into single dash
- Remove leading and trailing dashes
- Handle multiple spaces and special characters correctly
- Maintain scoped package stripping (@company/name → name)

Tested cases:
- Scoped packages: @company/my-app → my-app
- Multiple spaces: "my   app" → "my-app"
- Special characters: my@app!name → my-app-name
- Edge cases: ---my-app--- → my-app
Capture installation output to temporary log file for troubleshooting
when Gum installation fails. Log is preserved on failure and deleted
on success to keep system clean.

Changes:
- Create unique log file with PID: /tmp/shipnode_gum_install_$$.log
- Redirect all package manager output to log file
- Show log path in error message when installation fails
- Auto-cleanup log file on successful installation

This helps users diagnose installation issues without cluttering
the terminal with verbose package manager output during normal use.
Add stdin TTY check (-t 0) to all Gum wrapper functions to automatically
fallback to classic prompts in non-interactive environments like CI/CD
pipelines where stdin is not a terminal.

Changes:
- Check [ -t 0 ] before attempting to use Gum
- Auto-fallback when stdin is piped or redirected
- Prevents Gum errors in automated environments
- No changes needed to calling code

This ensures the wizard works seamlessly in both interactive terminals
and automated environments without requiring explicit flags.
Add detailed documentation comments to complex functions for improved
code maintainability and easier contribution by other developers.

Documented functions:
- parse_package_json: JSON parsing and validation
- detect_framework: Framework detection logic
- suggest_port: Port detection patterns
- validate_ip_or_hostname: Input validation
- gum_input/gum_choose/gum_confirm: UI wrapper behavior

Each docstring includes:
- Purpose description
- Arguments with types and defaults
- Return values and exit codes
- Usage examples or notes
- Fallback behavior where applicable
Document common issues and solutions for interactive wizard and Gum
integration, including installation failures, framework detection,
port detection, CI/CD environments, and SSH connection problems.

Provides actionable next steps and commands for users.
@devalade

Copy link
Copy Markdown
Owner

Can we handle AdonisJS, react router, Tanstack Router and Astro

Extend framework detection and app-type suggestion to cover additional
popular stacks:
- AdonisJS (backend)
- React Router and TanStack Router (frontend)
- Astro (full-stack, treated as backend for reverse proxy)

Update docs:
- CHANGELOG framework list
- README wizard framework examples

Keeps backward compatibility and expands auto-detection coverage.
@mouwaficbdr

Copy link
Copy Markdown
Author

Can we handle AdonisJS, react router, Tanstack Router and Astro

Done ✅.

@devalade
devalade merged commit 17209ce into devalade:main Jan 27, 2026
2 checks passed
devalade pushed a commit that referenced this pull request Feb 21, 2026
Implement shipnode harden for basic server security:
- SSH hardening: optional port change, disable root login, disable password auth
- Firewall (UFW): auto-install if missing, allow SSH/80/443, deny rest
- Fail2ban: optional install with SSH protection config
- All changes are opt-in with clear prompts and rollback hints
- SSH config automatically backed up before changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants