Skip to main content

Data layer

Two coexisting sources of agent data in fleapo-marketplace:

  1. Generated API clientsrc/api/ (produced by Orval from openapi.json). The path forward.
  2. Static mock datasrc/data/agents.ts. Legacy fallback; still used for staging UI without a running backend.

src/data/agents.ts

Holds the original mock catalog plus the type definitions for Lead / Customer / Vendor (admin mock data).

Agent type (display)

type Agent = {
id: string;
slug: string;
name: string;
tagline: string;
description: string;
iconUrl?: string | null;
rating: number | null; // 1-decimal mean
reviews: number;
installs: number;
pricing: "Free" | "Freemium" | "Paid";
price?: string; // "From $49 /mo"
tags: TagDto[];
featured?: boolean;
new?: boolean;
comingSoon?: boolean;
};

toDisplayAgent(dto, tiers?)

Converts the backend AgentDto plus optional PricingTierDto[] into the display Agent. Pricing label is derived:

Tiers configuredPricing label
All isFree"Free"
Some free + some paid"Freemium"
All paid"Paid"

Price string is built from the lowest-priced paid tier: "From $X /mo".

formatInstalls(n)

Humanizes: 42100 → "42.1K", 1245000 → "1.2M".

defaultsFor(category)

Returns category-level fallback metric and social-proof logos. Always paired with themeFor(category) at render time.

src/api/ (generated)

Orval reads openapi.transformed.json (the same openapi.json with the ApiResponseDto envelope stripped so React Query sees clean DTOs) and emits one file per OpenAPI tag.

src/api/
agents/agents.ts — useAgentsControllerFindAll, useAgentsControllerFindBySlug, ...
pricing/pricing.ts — usePricingControllerFindAll, ...
reviews/reviews.ts
tags/tags.ts
capabilities/...
steps/...
changelog/...
metrics/...
oauth/...
subscriptions/...
installs/...
upload/...

Custom mutator

src/lib/orval-mutator.ts (customFetch) handles:

  • Base URL from VITE_API_BASE_URL (default http://localhost:3000).
  • credentials: 'include' (cookies).
  • Unwrapping the ApiResponseDto envelope so React Query stores data directly.
  • Throwing on non-2xx with error.code propagated.

Custom hooks (src/hooks/)

Hand-rolled wrappers that compose generated client + business logic. Use these in components — the generated hooks are the underlay.

HookWraps
useAgents(limit?)useAgentsControllerFindAll + filter out drafts
useAgentBySlug(slug)useAgentsControllerFindBySlug
useAgent(id)useAgentsControllerFindOne
useTags(limit?)useTagsControllerFindAll
useAgentPricing(agentId?)usePricingControllerFindAll
useAgentMetrics(agentId?)metrics module
useAgentReviews(agentId?, opts?)useReviewsControllerFindAll
useUpsertReview()review POST mutation
useDeleteReview()DELETE mutation
useMe()useAuthControllerMe
useAuth()wraps useMe + signOut
useMySubscriptions()useSubscriptionsControllerListMine
useMySubscriptionForAgent(id?)single-agent variant
useSubscriptionUsage(agentId?)usage module
useCheckout()checkout POST mutation
useWaitlist(agentId?)waitlist GET
useMyWaitlistStatus(agentId?)wraps waitlist + auth
useInteractions()admin interactions list
useQuotaMetrics(agentId?)usage breakdown
useOAuth()OAuth helpers
use-mobile()viewport bool
use-breakpoint()mobile / tablet / desktop

Migration status (mock → live)

The UI is mid-transition. As of this docs site:

  • ✅ Catalog and detail pages use live API.
  • ✅ Pricing tiers, reviews, changelog all live.
  • ⚠️ Admin Leads, Customers, Vendors are still mock arrays in src/data/agents.ts.
  • ⚠️ Some homepage trending strips are commented out pending backend support.

If you're adding a new agent and want to preview the UI before backend is provisioned, push a mock entry into src/data/agents.ts. See Track C.