Alexis Bruneteau b83c7a7d6d
Some checks failed
Build and Deploy to k3s / build-and-deploy (push) Failing after 1m31s
feat(migration): migrate from Angular 20 to Next.js 15
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>
2025-10-17 00:34:43 +02:00

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

  1. Complete Framework Migration: Replace Angular with Next.js 15
  2. Launch UI Integration: Utilize all free Launch UI components (Navbar, Hero, Items, Logos, FAQ, Stats, CTA, Footer)
  3. API Compatibility: Maintain 100% compatibility with existing backend API
  4. Performance Improvement: Achieve better Core Web Vitals through SSR
  5. Developer Experience: Simplify component development with pre-built Launch UI primitives
  6. SEO Enhancement: Leverage Next.js metadata API for better search engine optimization

Non-Goals

  1. Backend API changes (out of scope)
  2. Database schema modifications
  3. Authentication mechanism changes (JWT remains)
  4. Deployment platform changes (Dockerfile-based deployment maintained)
  5. 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 fetch with 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:

  1. Build Next.js version in new repository/branch
  2. Deploy to staging environment
  3. Run parallel production deployment (different subdomain)
  4. Validate functionality and performance
  5. Cutover DNS or reverse proxy routing
  6. 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)

  1. User submits login form
  2. ApiService.post<LoginResponse>('/auth/login', credentials)
  3. Response includes JWT token
  4. Token stored in localStorage
  5. tokenSubject.next(token) updates RxJS state
  6. HTTP Interceptor adds Authorization: Bearer ${token} to all requests
  7. 401 responses trigger logout and redirect

Target (Next.js)

  1. User submits login form (client component)
  2. POST /api/auth/login via fetch wrapper
  3. Response includes JWT token
  4. Token stored in localStorage (client-side)
  5. setAuthToken(token) updates React Context
  6. API client function adds Authorization: Bearer ${token} header
  7. Middleware validates token on protected routes
  8. 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

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:

  1. Revert DNS/routing to Angular version (5 minute rollback)
  2. Investigate issues in Next.js version
  3. Fix and redeploy when stable
  4. 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

  1. 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
  2. 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
  3. 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
  4. 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.ts values to .env.local and .env.production
  5. 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