Complete framework migration from Angular to Next.js with full feature parity. ## What Changed - Migrated from Angular 20 to Next.js 15 with App Router - Replaced Angular components with React functional components - Implemented React Context API for state management (replacing RxJS) - Integrated React Hook Form for form handling - Added shadcn/ui component library - Configured Tailwind CSS 4.1 with @tailwindcss/postcss - Implemented JWT authentication with middleware protection ## Core Features Implemented - ✅ User registration and login with validation - ✅ JWT token authentication with localStorage - ✅ Protected dashboard route with middleware - ✅ Portfolio listing with status indicators - ✅ Create portfolio functionality - ✅ ZIP file upload with progress tracking - ✅ Portfolio deployment - ✅ Responsive design with Tailwind CSS ## Technical Stack - Framework: Next.js 15 (App Router) - Language: TypeScript 5.8 - Styling: Tailwind CSS 4.1 - UI Components: shadcn/ui + Lucide icons - State: React Context API + hooks - Forms: React Hook Form - API Client: Native fetch with custom wrapper ## File Structure - /app - Next.js pages (landing, login, register, dashboard) - /components - React components (ui primitives, auth provider) - /lib - API client, types, utilities - /hooks - Custom hooks (useAuth, usePortfolios) - /middleware.ts - Route protection - /angular-backup - Preserved Angular source code ## API Compatibility - All backend endpoints remain unchanged - JWT Bearer token authentication preserved - API response format maintained ## Build Output - Production build: 7 routes compiled successfully - Bundle size: ~102kB shared JS (optimized) - First Load JS: 103-126kB per route ## Documentation - Updated README.md with Next.js setup guide - Created OpenSpec proposal in openspec/changes/migrate-to-nextjs-launchui/ - Added project context in openspec/project.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
17 KiB
Technical Design: Next.js + Launch UI Migration
Context
The hosting-frontend application is currently built with Angular 20, using standalone components, reactive forms, and RxJS for state management. The backend API is a separate service that will remain unchanged during this migration.
Current Architecture
- Framework: Angular 20 with standalone components
- Routing: Angular Router with lazy loading
- State: RxJS BehaviorSubjects for auth token management
- Forms: ReactiveFormsModule with custom validators
- Styling: Tailwind CSS v4 with custom components
- Authentication: JWT tokens in localStorage, HTTP interceptor for Bearer token injection
Target Architecture
- Framework: Next.js 15 with App Router
- Component Library: Launch UI (shadcn/ui + Tailwind CSS 4.0)
- State: React Context API + hooks (useState, useEffect, useContext)
- Forms: React Hook Form (aligns with Launch UI patterns)
- Styling: Tailwind CSS 4.0 (maintained) + Launch UI components
- Authentication: Next.js middleware + API route handlers + React Context
Constraints
- Backend API endpoints must remain unchanged
- JWT authentication pattern must be preserved
- User sessions should be preserved during deployment (stretch goal)
- Deployment infrastructure (Dockerfile) must support Next.js
Goals / Non-Goals
Goals
- Complete Framework Migration: Replace Angular with Next.js 15
- Launch UI Integration: Utilize all free Launch UI components (Navbar, Hero, Items, Logos, FAQ, Stats, CTA, Footer)
- API Compatibility: Maintain 100% compatibility with existing backend API
- Performance Improvement: Achieve better Core Web Vitals through SSR
- Developer Experience: Simplify component development with pre-built Launch UI primitives
- SEO Enhancement: Leverage Next.js metadata API for better search engine optimization
Non-Goals
- Backend API changes (out of scope)
- Database schema modifications
- Authentication mechanism changes (JWT remains)
- Deployment platform changes (Dockerfile-based deployment maintained)
- Pro Launch UI components (keep budget low with free version only)
Decisions
Decision 1: App Router over Pages Router
Choice: Use Next.js App Router (/app directory)
Rationale:
- Launch UI is built for App Router patterns
- Better TypeScript support and DX
- Native React Server Components support
- Future-proof architecture (Pages Router is legacy)
Alternatives Considered:
- Pages Router: Rejected due to legacy status and incompatibility with Launch UI examples
Decision 2: React Hook Form over React Final Form
Choice: Use React Hook Form for form management Rationale:
- Smaller bundle size (9KB vs 20KB+)
- Better TypeScript support
- Native integration with shadcn/ui (Launch UI's foundation)
- More active community and maintenance
Alternatives Considered:
- Formik: Rejected due to larger bundle size and performance overhead
- React Final Form: Good alternative but less community momentum
Decision 3: React Context + Hooks over Redux/Zustand
Choice: Use React Context API with custom hooks for state management Rationale:
- Application state is simple (auth token, user info, portfolio list)
- Avoids unnecessary dependencies and complexity
- Aligns with Next.js best practices for small-to-medium apps
- Easy migration path from RxJS BehaviorSubject patterns
Alternatives Considered:
- Zustand: Good option for scaling, but premature optimization
- Redux Toolkit: Overkill for current state complexity
Decision 4: Fetch API with Custom Wrapper over Axios
Choice: Use native fetch with custom API client wrapper
Rationale:
- Next.js optimizes
fetchwith automatic request deduplication - Smaller bundle size (no axios dependency)
- Better server-side rendering support
- Launch UI examples use fetch patterns
Alternatives Considered:
- Axios: Familiar from Angular HttpClient, but adds bundle size
- SWR/React Query: Considered for later optimization if needed
Decision 5: Parallel Deployment Strategy
Choice: Deploy Next.js version as separate build, then cutover DNS/routing Rationale:
- Minimizes risk of downtime
- Allows A/B testing or gradual rollout
- Easy rollback if issues discovered
Migration Steps:
- Build Next.js version in new repository/branch
- Deploy to staging environment
- Run parallel production deployment (different subdomain)
- Validate functionality and performance
- Cutover DNS or reverse proxy routing
- Monitor for 48 hours before deprecating Angular version
Alternatives Considered:
- Big Bang Deployment: Rejected due to high risk
- Feature Flag Migration: Overly complex for complete framework change
Decision 6: Component Mapping Strategy
| Angular Component | Next.js Equivalent | Launch UI Component |
|---|---|---|
| LandingComponent | /app/page.tsx |
Hero, Items, Logos, FAQ, CTA |
| LoginComponent | /app/login/page.tsx |
Custom form with shadcn/ui inputs |
| RegisterComponent | /app/register/page.tsx |
Custom form with shadcn/ui inputs |
| DashboardComponent | /app/dashboard/page.tsx |
Custom with Stats component integration |
| AppComponent | /app/layout.tsx |
Navbar + Footer from Launch UI |
Decision 7: TypeScript Configuration
Choice: Downgrade from TypeScript 5.8 to TypeScript 5.0 (Launch UI requirement) Rationale:
- Launch UI tested with TypeScript 5.0
- Next.js 15 supports TypeScript 5.0+
- Minimal risk from downgrade (no critical features lost)
Architecture Diagrams
Current Angular Architecture
┌─────────────────────────────────────────┐
│ Angular 20 Application │
├─────────────────────────────────────────┤
│ Components (Standalone) │
│ ├── Landing, Login, Register, Dashboard│
│ └── Angular Router │
├─────────────────────────────────────────┤
│ Services Layer │
│ ├── ApiService (HttpClient) │
│ └── PortfolioService │
├─────────────────────────────────────────┤
│ State Management (RxJS) │
│ └── BehaviorSubject (auth token) │
├─────────────────────────────────────────┤
│ HTTP Interceptor (Auth) │
└─────────────────────────────────────────┘
↓ HTTP Requests
┌─────────────────────────────────────────┐
│ Backend API (Unchanged) │
│ /api/auth/*, /api/portfolios/* │
└─────────────────────────────────────────┘
Target Next.js Architecture
┌─────────────────────────────────────────┐
│ Next.js 15 Application │
├─────────────────────────────────────────┤
│ App Router (RSC + Client Components) │
│ ├── / (page.tsx) - Landing │
│ ├── /login (page.tsx) │
│ ├── /register (page.tsx) │
│ └── /dashboard (page.tsx) │
├─────────────────────────────────────────┤
│ Launch UI Components │
│ ├── Navbar, Hero, Items, Logos │
│ ├── FAQ, Stats, CTA, Footer │
│ └── shadcn/ui primitives │
├─────────────────────────────────────────┤
│ React State Management │
│ ├── AuthContext (Context API) │
│ ├── useAuth() hook │
│ └── useState/useEffect │
├─────────────────────────────────────────┤
│ API Client Layer │
│ ├── /lib/api-client.ts (fetch wrapper) │
│ └── API route handlers (optional) │
├─────────────────────────────────────────┤
│ Middleware (Auth) │
│ └── middleware.ts (JWT validation) │
└─────────────────────────────────────────┘
↓ HTTP Requests
┌─────────────────────────────────────────┐
│ Backend API (Unchanged) │
│ /api/auth/*, /api/portfolios/* │
└─────────────────────────────────────────┘
Data Models (Preserved)
Portfolio Model
// Maintained from Angular version
interface Portfolio {
active: boolean;
id: number;
name: string;
domain: string;
path?: string;
created_at: string;
updated_at: string;
}
API Response Model
// Maintained from Angular version
interface ApiResponse<T = any> {
success: boolean;
data?: T;
message?: string;
errors?: any;
}
Authentication Flow
Current (Angular)
- User submits login form
ApiService.post<LoginResponse>('/auth/login', credentials)- Response includes JWT token
- Token stored in localStorage
tokenSubject.next(token)updates RxJS state- HTTP Interceptor adds
Authorization: Bearer ${token}to all requests - 401 responses trigger logout and redirect
Target (Next.js)
- User submits login form (client component)
POST /api/auth/loginvia fetch wrapper- Response includes JWT token
- Token stored in localStorage (client-side)
setAuthToken(token)updates React Context- API client function adds
Authorization: Bearer ${token}header - Middleware validates token on protected routes
- 401 responses trigger logout and redirect via context hook
File Structure
hosting-frontend/
├── app/
│ ├── layout.tsx # Root layout (Navbar + Footer)
│ ├── page.tsx # Landing page (Launch UI Hero, Items, etc.)
│ ├── login/
│ │ └── page.tsx # Login form
│ ├── register/
│ │ └── page.tsx # Registration form
│ └── dashboard/
│ └── page.tsx # Dashboard (protected)
├── components/
│ ├── launch-ui/ # Launch UI components
│ │ ├── navbar.tsx
│ │ ├── hero.tsx
│ │ ├── items.tsx
│ │ ├── logos.tsx
│ │ ├── faq.tsx
│ │ ├── stats.tsx
│ │ ├── cta.tsx
│ │ └── footer.tsx
│ ├── ui/ # shadcn/ui primitives
│ │ ├── button.tsx
│ │ ├── input.tsx
│ │ ├── card.tsx
│ │ └── ...
│ └── auth/
│ └── auth-provider.tsx # React Context for auth state
├── lib/
│ ├── api-client.ts # Fetch wrapper with auth
│ └── utils.ts # Utility functions
├── hooks/
│ ├── use-auth.ts # Custom auth hook
│ └── use-portfolios.ts # Portfolio data fetching hook
├── middleware.ts # Route protection
├── next.config.js
├── tailwind.config.ts
├── tsconfig.json
└── package.json
Risks / Trade-offs
Risk 1: Complete Codebase Rewrite
- Risk: High chance of bugs, missing features, regression issues
- Mitigation:
- Comprehensive test plan covering all user flows
- Parallel deployment with gradual rollout
- Feature parity checklist before cutover
- Extended QA period in staging environment
Risk 2: Team Learning Curve
- Risk: Developers unfamiliar with Next.js patterns may introduce anti-patterns
- Mitigation:
- Code review process with Next.js best practices checklist
- Reference Launch UI examples as canonical patterns
- Pair programming sessions during initial development
- Documentation of patterns and conventions
Risk 3: SSR Performance Issues
- Risk: Server-side rendering could introduce latency vs. client-side Angular
- Mitigation:
- Use static generation where possible (
generateStaticParams) - Implement proper caching strategies (Next.js cache headers)
- Monitor Core Web Vitals and API response times
- Use React Server Components for data fetching
- Use static generation where possible (
Risk 4: Launch UI Customization Limitations
- Risk: Launch UI components may not match exact design requirements
- Mitigation:
- Evaluate component customizability before full migration
- Budget for custom component development if needed
- Consider Pro version if free components insufficient
- Leverage shadcn/ui flexibility for customization
Risk 5: Session Preservation During Migration
- Risk: Users may lose active sessions during cutover
- Mitigation:
- Deploy during low-traffic window
- Communicate planned maintenance window
- Implement session migration script if feasible
- Provide clear re-authentication flow
Migration Plan
Phase 1: Foundation Setup (Week 1)
- Initialize Next.js 15 project with App Router
- Install Launch UI and shadcn/ui dependencies
- Configure Tailwind CSS 4.0
- Set up TypeScript 5.0 configuration
- Create API client wrapper with auth support
- Implement AuthContext and useAuth hook
Phase 2: Core Pages Migration (Week 2-3)
- Build Landing page with Launch UI components (Hero, Items, Logos, FAQ, CTA)
- Migrate Login component to Next.js with React Hook Form
- Migrate Register component with validation
- Implement authentication flow and middleware
- Add Navbar and Footer from Launch UI
Phase 3: Dashboard & Protected Routes (Week 4)
- Build Dashboard page with portfolio listing
- Implement portfolio upload functionality
- Add portfolio deployment features
- Integrate Stats component for dashboard metrics
- Implement route protection middleware
Phase 4: Testing & Validation (Week 5)
- End-to-end testing of all user flows
- Performance testing and optimization
- Cross-browser compatibility testing
- Mobile responsiveness validation
- API compatibility verification
Phase 5: Deployment & Cutover (Week 6)
- Deploy to staging environment
- Run parallel production deployment
- Conduct UAT with stakeholders
- Perform gradual traffic rollout (10% → 50% → 100%)
- Monitor errors and performance metrics
- Complete cutover and deprecate Angular version
Rollback Plan
If critical issues discovered post-deployment:
- Revert DNS/routing to Angular version (5 minute rollback)
- Investigate issues in Next.js version
- Fix and redeploy when stable
- Retry cutover after validation
Performance Targets
| Metric | Current (Angular) | Target (Next.js) |
|---|---|---|
| First Contentful Paint | ~1.5s | <1.0s |
| Largest Contentful Paint | ~2.0s | <1.5s |
| Time to Interactive | ~2.5s | <2.0s |
| Bundle Size (JS) | ~500KB | <400KB |
| Lighthouse Score | 75-85 | 90+ |
Open Questions
-
Q: Should we use Next.js API routes as a proxy to the backend, or call backend directly from client?
- Recommendation: Call backend directly from client (simpler, maintains current architecture)
- Alternative: Use API routes for sensitive endpoints requiring additional validation
-
Q: Do we need Pro version of Launch UI for advanced components?
- Recommendation: Start with free version, evaluate need based on design requirements
- Budget: Pro version is $99 one-time if needed
-
Q: Should we implement real-time updates for portfolio deployment status?
- Recommendation: Defer to post-migration enhancement (use polling initially)
- Alternative: Integrate WebSocket support if backend provides it
-
Q: How do we handle environment variables in Next.js vs Angular?
- Recommendation: Use Next.js environment variable conventions (
NEXT_PUBLIC_*for client-side) - Migration: Map
environment.tsvalues to.env.localand.env.production
- Recommendation: Use Next.js environment variable conventions (
-
Q: Should we implement server-side session management instead of client-side JWT?
- Recommendation: Maintain client-side JWT pattern for consistency with backend
- Future Enhancement: Consider server-side sessions in future backend refactor