Files
comparaison/docs/api-reference.md

4.4 KiB

ComparAIson — API Reference

Base URL

Development: http://localhost:3000
Production:  https://comparaison.tophermayor.com

Authentication

All authenticated endpoints use Better Auth session cookies.

POST /api/auth/sign-up

Create a new account.

Request:

{
  "name": "Alex Johnson",
  "email": "alex@example.com",
  "password": "securepassword123"
}

Response: 200 OK — Sets session cookie, returns user object

POST /api/auth/sign-in

Sign in to existing account.

Request:

{
  "email": "alex@example.com",
  "password": "securepassword123"
}

Response: 200 OK — Sets session cookie, redirects to callbackUrl

POST /api/auth/sign-out

Sign out, clears session.

Response: 200 OK — Redirects to /


Comparison Endpoints

POST /api/compare

Start a new comparison research. Returns a Server-Sent Events stream.

Authentication: Required

Request:

{
  "query": "for modern web development",
  "items": ["React", "Vue", "Svelte"],
  "dimensions": ["Performance", "Developer Experience"]
}
Field Type Required Description
query string No Context/focus for the comparison
items string[] Yes Items to compare (2-10)
dimensions string[] No Optional dimension hints

Response: 200 OKtext/event-stream

SSE event format:

event: progress
data: {"status":"researching","message":"Analyzing comparison request...","itemsCompleted":0,"totalItems":3,"currentStep":"Analyzing comparison request..."}

event: progress
data: {"status":"researching","message":"Researching React...","itemsCompleted":1,"totalItems":3,"currentStep":"Analyzing React"}

event: progress
data: {"status":"completed","message":"Research complete!","itemsCompleted":3,"totalItems":3,"currentStep":"Done"}

event: done
data: {"id":"clx123abc","slug":"react-vs-vue-vs-svelte-clx123","data":{...full comparison data...}}

Error Response: 400 Bad Request

{ "error": "At least 2 items are required" }

Page Routes

GET /

Landing page. Public. Shows hero, example comparisons, features.

GET /sign-in

Sign in form. Public. Redirects to /compare on success.

GET /sign-up

Sign up form. Public. Redirects to /compare on success.

GET /compare

Comparison creation page. Protected. Shows item input form + streaming progress.

GET /compare/[slug]

Comparison results page. Public (if comparison is public). Shows tabbed visualization layout.

URL format: /compare/react-vs-vue-vs-svelte-clx123a

GET /explore

Public comparisons feed. Public. Grid layout with search + category filter.

GET /profile

User profile page. Protected. Shows user info, stats, and saved comparisons.


TypeScript Types

ComparisonRequest

interface ComparisonRequest {
  query: string;
  items: string[];
  dimensions?: string[];
}

ComparisonResult

interface ComparisonResult {
  items: ItemResearch[];
  dimensions: string[];
  summary: string;
  recommendation: string;
}

ItemResearch

interface ItemResearch {
  name: string;
  description: string;
  overallScore: number;
  dimensions: Record<string, DimensionResult>;
  pros: string[];
  cons: string[];
  sources: { title: string; url: string; snippet: string }[];
}

DimensionResult

interface DimensionResult {
  score: number;       // 1-10
  summary: string;
  details: string;
  pros: string[];
  cons: string[];
}

ResearchProgress (SSE)

type ResearchProgress =
  | { stage: "parsing"; message: string }
  | { stage: "searching"; item: string; results: number }
  | { stage: "researching"; item: string; progress: number }
  | { stage: "synthesizing"; message: string }
  | { stage: "complete"; result: ComparisonResult }
  | { stage: "error"; error: string };

ComparisonData (Frontend)

interface ComparisonData {
  id: string;
  userId: string;
  title: string;
  query: string;
  slug: string;
  status: "researching" | "completed" | "failed";
  summary: string;
  items: {
    name: string;
    description: string;
    overallScore: number;
    dimensions: Record<string, DimensionResult>;
    pros: string[];
    cons: string[];
  }[];
  dimensions: string[];
  tags: string[];
  isPublic: boolean;
  viewCount: number;
  createdAt: string;
  updatedAt: string;
}