Skip to content

Sprint 2: Fix Test Failures, Add Layout, Unify Stores #3

Description

@ibuzzardo

Sprint 2: Fix Test Failures, Add Layout, Unify Stores

Building on the existing codebase from Sprint 1 (PR #2).

Context

This project was built by Dark Factory in Sprint 1. Two factory passes collided, creating duplicate store systems and mismatched tests. The current state:

  • What works: Pages exist (app/page.tsx, app/build/[id]/page.tsx), launch form, build status client with SSE, two complete API route sets, UI components, Tailwind config, dark theme
  • What's broken: 18 of 19 test files fail. Two incompatible store systems exist (lib/store/build-store.ts and lib/store/in-memory-project-store.ts). Missing app/layout.tsx (Next.js won't render without it). Missing .gitignore. The globals.css was overwritten and lost the glassmorphism utility classes.

Hard Constraints

  • Language: TypeScript with strict: true
  • No regressions: All existing pages and API routes must continue to work
  • Test requirement: ALL tests must pass (npx vitest run exits 0)
  • Preserve file structure: Do not reorganize existing files unless specified below

Changes Required

1. Add missing app/layout.tsx (CRITICAL — app won't render without this)

Create app/layout.tsx with:

  • Import ./globals.css
  • Dark theme (<html lang="en" className="dark">)
  • Font: Space Grotesk from Google Fonts via next/font/google
  • Proper metadata: title "Project Launcher", description "Launch builds instantly"
import type { Metadata } from "next";
import { Space_Grotesk } from "next/font/google";
import "./globals.css";

const font = Space_Grotesk({ subsets: ["latin"], variable: "--font-sans" });

export const metadata: Metadata = {
  title: "Project Launcher",
  description: "Launch builds instantly and monitor them in real time.",
};

export default function RootLayout({ children }: { children: React.ReactNode }): JSX.Element {
  return (
    <html lang="en" className={`dark ${font.variable}`}>
      <body>{children}</body>
    </html>
  );
}

2. Add .gitignore

Create .gitignore with standard Next.js entries:

node_modules/
.next/
out/
dist/
.env
.env.local
*.log
.DS_Store

3. Restore glassmorphism CSS classes in app/globals.css

The current globals.css is missing the glassmorphism utility classes that tests expect. Replace the entire content of app/globals.css with:

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  color-scheme: dark;
  --bg-base: #020617;
  --bg-panel: rgba(15, 23, 42, 0.45);
  --bg-panel-strong: rgba(2, 6, 23, 0.8);
  --border-glass: rgba(51, 65, 85, 0.6);
  --text-primary: #e2e8f0;
  --text-muted: #94a3b8;
  --ring-primary: rgba(56, 189, 248, 0.7);
}

html,
body {
  @apply bg-slate-950 text-slate-100;
}

body {
  @apply min-h-screen font-sans antialiased;
  background-image:
    radial-gradient(circle at 15% 20%, rgba(14, 165, 233, 0.18), transparent 40%),
    radial-gradient(circle at 85% 10%, rgba(45, 212, 191, 0.14), transparent 36%),
    linear-gradient(to bottom, #020617, #020617);
  background-attachment: fixed;
}

@layer components {
  .glass-card {
    @apply rounded-2xl border border-slate-700/50 bg-slate-900/45 p-4 shadow-[0_12px_40px_rgba(2,6,23,0.45)] backdrop-blur-xl md:p-6 xl:p-8;
  }

  .glass-panel {
    @apply rounded-2xl border border-slate-700/60 bg-slate-950/80 p-3 backdrop-blur-lg md:p-4;
  }

  .log-stream-panel {
    @apply rounded-2xl border border-slate-700/60 bg-slate-950/80 p-3 backdrop-blur-lg md:p-4 h-[320px] md:h-[420px] overflow-y-auto font-mono text-xs leading-5 text-slate-200 shadow-inner shadow-slate-950/60;
  }
}

4. Unify the two store systems

There are currently TWO stores:

  • lib/store/build-store.ts — uses globalThis.__projectLauncherStore, deterministic IDs (bld_000001), separate createBuild/updateBuildStatus/appendLog/subscribeToBuild functions
  • lib/store/in-memory-project-store.ts — uses globalThis.__projectStore, UUID IDs, class-based with InMemoryProjectStore

The pages and /api/projects routes use in-memory-project-store.ts. The /api/builds routes and tests/lib/build-store.test.ts use build-store.ts.

Keep BOTH stores as-is. Do not merge them. Each API route set uses its own store and that's fine. The fix is in the tests — make sure each test imports the correct store for the route it tests.

5. Fix ALL 18 failing test files

The test failures fall into these categories:

A. Config tests expect old values (tests/config/config-files.test.ts):

  • package.json test expects next: "14.2.24" but actual is "14.2.15" — update test to match actual
  • tsconfig.json test expects noImplicitAny: true — verify tsconfig actually has this, fix test or tsconfig
  • tailwind.config.ts test expects darkMode: ["class"] and specific colors — verify actual config, fix test
  • globals.css test expects .glass-card, .glass-panel, .log-stream-panel — fixed by change Sprint 2: Fix Test Failures, Add Layout, Unify Stores #3 above

B. tests/api/ tests import from build-store.ts but routes now use different patterns:

  • tests/api/build-id-route.test.ts — imports GET from app/api/builds/[id]/route.ts which uses build-store.ts. Make sure imports resolve correctly.
  • tests/api/build-logs-route.test.ts — tests SSE streaming. Make sure the SSE route handler signature matches what tests expect.
  • tests/api/builds-route.test.ts — tests POST/GET on /api/builds. Make sure build-store.ts exports match test imports.

C. __tests__/ files test the project store system:

  • __tests__/in-memory-project-store.test.ts — tests inMemoryProjectStore class methods
  • __tests__/projects-api.integration.test.ts — tests /api/projects routes
  • __tests__/projects-routes.unit.test.ts — tests project route handlers
  • __tests__/project-schema.test.ts — tests createProjectSchema and projectIdSchema
  • __tests__/api-client.test.ts — tests lib/api/client.ts
  • __tests__/error-response.test.ts — tests lib/server/error-response.ts
  • __tests__/sse.test.ts — tests lib/server/sse.ts
  • __tests__/log-stream.test.tsx — tests log stream component
  • __tests__/utils.test.ts — tests utility functions

For each failing test file: read the test, read the source file it tests, and fix whichever side has the bug. Prefer fixing tests to match actual code if the code is correct.

6. Fix Tailwind config color mismatch

In tailwind.config.ts, the extended colors define light-theme values (background: "#F8FAFC", foreground: "#0F172A") which conflict with the dark theme. Update these to dark-theme values:

  • background: "#020617" (slate-950)
  • foreground: "#e2e8f0" (slate-200)

Existing Code Reference

Current file: lib/store/build-store.ts

This file is the original Sprint 1 build store. It exports: createBuild, listBuilds, getBuild, updateBuildStatus, appendLog, subscribeToBuild. Uses globalThis.__projectLauncherStore. Keep it as-is.

Current file: lib/store/in-memory-project-store.ts

This is the Sprint 1.5 project store class. Exports inMemoryProjectStore singleton. Uses globalThis.__projectStore. Keep it as-is.

Current file: tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["dom", "dom.iterable", "es2022"],
    "allowJs": false,
    "skipLibCheck": true,
    "strict": true,
    "noImplicitAny": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

Current file: package.json (scripts + deps)

{
  "name": "project-launcher",
  "version": "1.0.0",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test": "vitest run"
  },
  "dependencies": {
    "next": "14.2.15",
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "zod": "^3.23.8",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.1.1",
    "lucide-react": "^0.453.0",
    "tailwind-merge": "^2.5.4",
    "@radix-ui/react-dialog": "^1.1.2",
    "@radix-ui/react-select": "^2.1.2",
    "@radix-ui/react-slot": "^1.1.0"
  },
  "devDependencies": {
    "typescript": "^5.6.3",
    "vitest": "^2.1.3",
    "tailwindcss": "^3.4.14",
    "postcss": "^8.4.47",
    "autoprefixer": "^10.4.20",
    "@types/node": "^22.8.1",
    "@types/react": "^18.3.12",
    "@types/react-dom": "^18.3.1"
  }
}

Acceptance Criteria

  • app/layout.tsx exists and renders all pages with dark theme
  • .gitignore exists and excludes node_modules/, .next/, .env*, *.log
  • app/globals.css contains .glass-card, .glass-panel, .log-stream-panel utility classes
  • tailwind.config.ts colors use dark-theme values
  • ALL tests pass: npx vitest run exits with 0 failures
  • No new TypeScript errors (npx tsc --noEmit passes)
  • Both /api/builds and /api/projects route sets continue to work
  • Both pages render correctly (/ and /build/[id])

What NOT to Change

  • lib/store/build-store.ts — leave as-is
  • lib/store/in-memory-project-store.ts — leave as-is
  • components/project-launcher/launch-form.tsx — leave as-is
  • components/project-launcher/build-status-client.tsx — leave as-is
  • components/ui/button.tsx, components/ui/card.tsx, components/ui/input.tsx, components/ui/progress.tsx — leave as-is
  • app/page.tsx — leave as-is
  • app/build/[id]/page.tsx — leave as-is
  • app/api/projects/ routes — leave as-is
  • app/api/builds/ routes — leave as-is
  • lib/build-simulator.ts — leave as-is

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions