A modern, accessible, and production-ready booking wizard for space tourism built with Next.js 16, TypeScript, and Tailwind CSS.
🤖 AI-Assisted Development: This project was built with the assistance of AI tools including Augment VSCode Plugin and ChatGPT to accelerate development while maintaining high code quality and best practices.
- Features
- Installation & Setup
- Project Structure
- Key Design Decisions
- Development Approach
- Feedback on Assignment
- Multi-step wizard flow: Destination selection → Travelers → Review → Confirmation
- State persistence: Wizard state survives page refresh using sessionStorage
- URL-based navigation: Each step has its own URL for bookmarking and back button support
- Comprehensive validation: Client-side and server-side validation with helpful error messages
- Accessibility first: WCAG compliant with keyboard navigation, focus management, and ARIA labels
- Responsive design: Mobile-first approach with adaptive layouts
- Type-safe: Full TypeScript coverage with discriminated unions and branded types
- Production-ready: Error boundaries, loading states, and monitoring hooks
- Node.js: Version 20.9.0 or higher
- npm, yarn, pnpm, or bun
-
Clone the repository
git clone git@github.com:dhwrwm/intergalactic-booking-wizard.git cd intergalactic-booking-wizard -
Install dependencies
npm install # or yarn install # or pnpm install
-
Run the development server
npm run dev # or yarn dev # or pnpm dev
-
Open your browser
Navigate to http://localhost:3000
npm run build
npm run startnpm run lintintergalactic-booking-wizard/
├── app/ # Next.js App Router
│ ├── api/ # API routes
│ │ ├── bookings/ # Booking submission endpoint
│ │ └── destinations/ # Destinations data endpoint
│ ├── booking/ # Booking wizard pages
│ │ ├── BookingWizard.tsx # Main wizard orchestrator
│ │ ├── BookingWizardContext.tsx # State management
│ │ ├── StepProgressIndicator.tsx # Progress UI
│ │ ├── layout.tsx # Wizard layout with provider
│ │ ├── page.tsx # Wizard entry point
│ │ ├── error.tsx # Error boundary
│ │ └── loading.tsx # Loading state
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Landing page
│ └── globals.css # Global styles
├── components/
│ ├── atoms/ # Basic building blocks
│ │ ├── Card.tsx
│ │ ├── Input.tsx
│ │ ├── Label.tsx
│ │ ├── ErrorMessage.tsx
│ │ ├── Heading.tsx
│ │ └── Text.tsx
│ ├── molecules/ # Composite components
│ │ ├── DestinationCard.tsx
│ │ ├── TravelerCard.tsx
│ │ └── FormField.tsx
│ ├── booking/ # Wizard step components
│ │ ├── DestinationStep.tsx
│ │ ├── TravelersStep.tsx
│ │ ├── ReviewStep.tsx
│ │ └── ConfirmationStep.tsx
│ └── ui/ # Shared UI components
│ ├── button.tsx
│ ├── calendar.tsx
│ ├── date-picker.tsx
│ └── popover.tsx
├── hooks/ # Custom React hooks
│ ├── useDestinations.ts # Fetch destinations
│ └── useA11yAnnounce.ts # Accessibility utilities
├── lib/ # Business logic & utilities
│ ├── booking.ts # Wizard state management
│ ├── constants.ts # App-wide constants
│ ├── monitoring.ts # Logging & analytics
│ └── utils.ts # Utility functions
└── types/ # TypeScript definitions
└── booking.ts # Domain types
Used React Context with useReducer instead of Redux/Zustand because:
- State is scoped to booking flow only
- Reducer pattern provides predictable, action-based updates
- Discriminated union of actions ensures type safety
- No external dependencies needed
Organized components into atoms → molecules → organisms for:
- Reusability: Atoms (Button, Input) compose into molecules (FormField)
- Consistency: Shared design system
- Maintainability: Clear component location and purpose
Used query parameters (?step=destination) for:
- Shareable URLs and bookmarking
- Browser back button support
- Step validation and redirects
Chose sessionStorage over localStorage because:
- Session-scoped (clears when tab closes)
- Better privacy for booking data
- Instant state restoration on refresh
Built-in from the start:
- ✅ Keyboard navigation (Tab, Enter, Space, Arrow keys)
- ✅ Focus management on step transitions
- ✅ ARIA labels and semantic HTML
- ✅ Screen reader announcements
- Planning → Analyzed requirements, sketched component hierarchy
- Foundation → Set up Next.js 16 + TypeScript + Tailwind, built atomic components
- Features → Implemented wizard steps, state management, API routes
- Polish → Added accessibility, error handling, type safety improvements
- Production → Error boundaries, monitoring hooks, session persistence
- Next.js 16 - App Router, API routes, SSR
- TypeScript - Type safety and better refactoring
- Tailwind CSS 4 - Utility-first styling
- Radix UI - Accessible component primitives
- date-fns - Lightweight date manipulation
- react-day-picker - Accessible calendar component
- Clear evaluation criteria defining "production-ready"
- Creative space tourism theme
- Real-world complexity (multi-step wizard, validation, accessibility)
This assignment provided valuable hands-on experience with:
- Discriminated unions for type-safe action creators
- WCAG-compliant keyboard navigation with custom accessibility hooks
- Designing a scalable reducer pattern with Context API for complex wizard flows with state persistence
- Testing: Unit (Vitest), integration (Testing Library), E2E (Playwright)
- CI/CD: GitHub Actions for automated testing and deployment
- Monitoring: Sentry for errors, analytics for performance