Context
Boundless Builders (builders.boundlessfi.xyz) is a read-only showcase. It reads ecosystem data (builders, projects, teams) from the shared boundless-nestjs backend and never writes. Every landing-page section depends on a fetch client and a server-state layer, so this issue sets that up first.
This issue blocks all other landing-page issues. Do it first.
What to build
-
Environment variable. The current .env.example holds a bare URL. Replace it with a named var:
# boundless-nestjs backend origin. All routes are served under /api.
NEXT_PUBLIC_API_URL="https://stage-api.boundlessfi.xyz"
-
Typed fetch client — lib/api/client.ts exporting apiFetch<T>(path, init?) that:
- Prefixes requests with
${NEXT_PUBLIC_API_URL}/api (so you call apiFetch('/leaderboard')).
- Sends no auth (all reads are public/anonymous).
- Unwraps the response envelope. List endpoints return
{ data, pagination: { page, limit, total, totalPages, hasNext, hasPrev } } (see ENDPOINTS.md). Confirm the exact envelope against a live response before finalizing.
- Throws a typed error on non-2xx.
-
State management (TanStack Query) — add @tanstack/react-query, create providers/query-provider.tsx, and wire it into providers/index.tsx (this file already exists and holds the theme provider). Set sane defaults: a reasonable staleTime, refetchOnWindowFocus: false, and no retry on 4xx.
-
Shared types — lib/api/types.ts with a Paginated<T> type matching the pagination shape above.
Where files go
lib/api/client.ts, lib/api/types.ts (new lib/api/ folder, mirroring the existing lib/utils.ts / lib/initials.ts).
providers/query-provider.tsx, wired into the existing providers/index.tsx.
.env.example (edit in place).
How Boundless builds this (reference)
The main boundless-platform repo is private, so here is the pattern to mirror: it uses a single typed client under lib/api/ plus TanStack Query, with thin per-feature query hooks that call the client and return data. We copy that pattern minus the auth and OpenAPI-codegen layers, since this app only does public reads. Our providers/index.tsx already follows their provider-tree pattern (the theme provider is in place); add the query provider alongside it.
Design system
No UI in this issue. Follow the code style in CONTRIBUTING.md (single quotes, no em dashes).
Out of scope
No auth, no write methods, no OpenAPI codegen, no React Query hooks for specific screens yet (those come with each section).
Acceptance criteria
References (in this repo)
ENDPOINTS.md — the full read-only API surface and the envelope shape.
providers/index.tsx, providers/theme-provider.tsx — the provider-tree pattern to extend.
lib/utils.ts — existing helper style to match.
Context
Boundless Builders (
builders.boundlessfi.xyz) is a read-only showcase. It reads ecosystem data (builders, projects, teams) from the sharedboundless-nestjsbackend and never writes. Every landing-page section depends on a fetch client and a server-state layer, so this issue sets that up first.What to build
Environment variable. The current
.env.exampleholds a bare URL. Replace it with a named var:Typed fetch client —
lib/api/client.tsexportingapiFetch<T>(path, init?)that:${NEXT_PUBLIC_API_URL}/api(so you callapiFetch('/leaderboard')).{ data, pagination: { page, limit, total, totalPages, hasNext, hasPrev } }(seeENDPOINTS.md). Confirm the exact envelope against a live response before finalizing.State management (TanStack Query) — add
@tanstack/react-query, createproviders/query-provider.tsx, and wire it intoproviders/index.tsx(this file already exists and holds the theme provider). Set sane defaults: a reasonablestaleTime,refetchOnWindowFocus: false, and no retry on 4xx.Shared types —
lib/api/types.tswith aPaginated<T>type matching the pagination shape above.Where files go
lib/api/client.ts,lib/api/types.ts(newlib/api/folder, mirroring the existinglib/utils.ts/lib/initials.ts).providers/query-provider.tsx, wired into the existingproviders/index.tsx..env.example(edit in place).How Boundless builds this (reference)
The main boundless-platform repo is private, so here is the pattern to mirror: it uses a single typed client under
lib/api/plus TanStack Query, with thin per-feature query hooks that call the client and returndata. We copy that pattern minus the auth and OpenAPI-codegen layers, since this app only does public reads. Ourproviders/index.tsxalready follows their provider-tree pattern (the theme provider is in place); add the query provider alongside it.Design system
No UI in this issue. Follow the code style in
CONTRIBUTING.md(single quotes, no em dashes).Out of scope
No auth, no write methods, no OpenAPI codegen, no React Query hooks for specific screens yet (those come with each section).
Acceptance criteria
.env.exampledefinesNEXT_PUBLIC_API_URLwith the staging base URL.apiFetchcompiles, is typed, and unwraps the envelope.QueryProviderwraps the app throughproviders/index.tsx.useQuerycallingGET /api/leaderboardreturns data locally (remove before merge).npm run lintandnpm run buildpass.References (in this repo)
ENDPOINTS.md— the full read-only API surface and the envelope shape.providers/index.tsx,providers/theme-provider.tsx— the provider-tree pattern to extend.lib/utils.ts— existing helper style to match.