Data layer
Two coexisting sources of agent data in fleapo-marketplace:
- Generated API client —
src/api/(produced by Orval fromopenapi.json). The path forward. - Static mock data —
src/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 configured | Pricing 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(defaulthttp://localhost:3000). credentials: 'include'(cookies).- Unwrapping the
ApiResponseDtoenvelope so React Query storesdatadirectly. - Throwing on non-2xx with
error.codepropagated.
Custom hooks (src/hooks/)
Hand-rolled wrappers that compose generated client + business logic. Use these in components — the generated hooks are the underlay.
| Hook | Wraps |
|---|---|
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,Vendorsare still mock arrays insrc/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.