diff --git a/ENDPOINTS.md b/ENDPOINTS.md index dd195d63..957a11e2 100644 --- a/ENDPOINTS.md +++ b/ENDPOINTS.md @@ -1,10 +1,14 @@ # Builders App — API Endpoints -This app is **read-only**. It displays builders, projects, and teams that are -created and managed in the main Boundless app. Every read comes from the shared +This app is **read-only**. It displays builders and projects that are created and +managed in the main Boundless app. Every read comes from the shared `boundless-nestjs` backend, so this app and boundless-platform stay consistent (a project or user followed in the platform is read here from the same data). +Profiles, project pages, and organization pages live in the main Boundless app. +This app links out to them rather than rendering them. See +[Main app pages we link to](#main-app-pages-we-link-to). + The public read API was implemented by the backend team. This document mirrors `boundless-nestjs/docs/builders-public-reads.md` and maps each endpoint to the screen that uses it. If the two ever drift, the backend doc is the source of @@ -30,8 +34,6 @@ truth. ## Status legend - **Public**: implemented and public. Use directly. -- **Private-aware**: public, but returns `404` when the target profile is - private. --- @@ -41,10 +43,8 @@ truth. | --- | --- | --- | | `GET /users/top-builders` | Top builders row. Card-ready. Accepts `limit`. | Public | | `GET /projects/featured` | Featured projects row | Public | -| `GET /discover/landing` | Ecosystem feed / counts | Public | -| `GET /discover/recent-winners` | Recent winners highlight | Public | -| `GET /users/directory?limit=N` | Fallback source for a builders strip | Public | -| `GET /leaderboard` | Ranking + reputation (tier, score, stats). Not card-ready. | Public | +| `GET /users/directory?limit=1` | Stats strip count (`pagination.total`) | Public | +| `GET /projects?limit=1` | Stats strip count (`pagination.total`) | Public | > **Top builders:** use `GET /users/top-builders`. It returns a flat array of > card-ready builders in the standard `{ success, message, data, meta }` @@ -57,13 +57,11 @@ truth. > > Map: `name` -> displayName, `image` -> avatarSrc, `location` -> location, > `skills`/`followers`/`projects` straight across. Do **not** map `role` (it is -> the account role, e.g. `"user"`, not a professional title). `GET /leaderboard` -> is kept for ranking/reputation use only; it does **not** carry profile fields -> (role, location, followers, projects), which is why the landing top-builders -> row moved to `GET /users/top-builders`. +> the account role, e.g. `"user"`, not a professional title). > -> A stats strip can derive counts from the `pagination.total` of -> `GET /users/directory`, `GET /projects`, and `GET /organizations`. +> The stats strip derives its Builders and Projects counts from the +> `pagination.total` of `GET /users/directory` and `GET /projects` (each called +> with `limit=1`). --- @@ -76,70 +74,33 @@ truth. > The directory is `GET /users/directory`, **not** `GET /users`. `GET /users` is > Admin-only and is not used by this app. +> +> **Who is listed:** the directory returns only people who qualify as builders: a +> username, an avatar, at least one skill, not a staff account, and at least one +> piece of real work on Boundless (a published project, a hackathon entry, a +> bounty submission, a win, or a grant award). Signing up or creating an +> organization alone does not get someone listed. This app does not filter +> anything itself; the rule lives in the API. --- -## `/builders/[username]` — Builder Profile - -| Endpoint | Purpose | Status | -| --- | --- | --- | -| `GET /users/:username` | Public profile. Embeds orgs, projects, stats, followStats. | Public | -| `GET /users/:username/stats` | Public profile stats + follow counts | Private-aware | -| `GET /users/:username/activity` | Contribution timeline (`limit`, `offset`) | Private-aware | -| `GET /users/:username/organizations` | Teams the builder belongs to, with role | Private-aware | -| `GET /users/:username/followers` · `/following` | Follower / following lists | Public | -| `GET /projects?creatorId=:userId` | The builder's projects | Public | - ---- - -## `/projects` — Projects / Products Directory - -| Endpoint | Purpose | Status | -| --- | --- | --- | -| `GET /projects` | Directory. Filters: `creatorId`, `organizationId`, `tags` (repeatable/CSV), `category`, `publicStatus`, `originType`, `featured`, `search`. Never returns `IDEA` drafts. | Public | -| `GET /projects/search` | Search public projects | Public | -| `GET /projects/filters` | Facets: `categories[]` + `tags[]` (with counts), `publicStatuses[]`, `originTypes[]` | Public | - ---- - -## `/projects/[slug]` — Project Detail - -| Endpoint | Purpose | Status | -| --- | --- | --- | -| `GET /projects/:slug` | Project header and body (PII-scrubbed) | Public | -| `GET /projects/:slug/members` | Contributor roster (from `ProjectMember`). Creator always included as `owner`. Drafts 404. | Public | -| `GET /follows/entity/project/:id/followers` | Project follower list. The generic `entity/:entityType/:entityId/followers` route stays authenticated. | Public | -| `GET /bounties?projectId=` · `GET /grants?projectId=` | Related opportunities | Public | - ---- - -## `/teams` — Teams / Organizations Directory +## Main app pages we link to -| Endpoint | Purpose | Status | -| --- | --- | --- | -| `GET /organizations` | Public directory. `search`, `sortBy` (`createdAt\|name`), `sortOrder`, `page`, `limit`. Counts only, no member PII. | Public | -| `GET /organizations/search` | Search organizations | Public | +This app renders directories only. The detail pages for a builder, a project, +and an organization live in the main Boundless app, and cards link to them there: ---- +| Entity | Main app page | +| --- | --- | +| Builder | `https://boundlessfi.xyz/profile/` | +| Project | `https://boundlessfi.xyz/projects/` | +| Organization | `https://boundlessfi.xyz/organizations/` | +| Projects directory | `https://boundlessfi.xyz/projects` | -## `/teams/[slug]` — Team Detail - -| Endpoint | Purpose | Status | -| --- | --- | --- | -| `GET /organizations/profile/:idOrSlug` | Team profile | Public | -| `GET /organizations/profile/:idOrSlug/funded` | Funded / supported projects | Public | -| `GET /organizations/:id/members` | Public roster (identity fields only, capped, with `total`) | Public | -| `GET /organizations/:id/stats` | Projects / hackathons / bounties / grants / participants / prize pool + followers | Public | +The origin comes from `NEXT_PUBLIC_BOUNDLESS_APP_URL` (fallback +`https://boundlessfi.xyz`). These routes are not built in this app. --- -## Cross-cutting - -| Endpoint | Purpose | Status | -| --- | --- | --- | -| `GET /leaderboard` | Leaderboard widget | Public | -| `GET /follows/:entityType/:entityId/check` | "Am I following" state (only if this app has logged-in sessions) | Auth | - ### Not built here (boundary) `POST` / `DELETE /follows/:entityType/:entityId` and every other write stay in @@ -154,9 +115,6 @@ From migration `20260725000000_builders_public_reads`: - `BuilderStatus` enum (`AVAILABLE`, `OPEN_TO_WORK`, `BUSY`, `UNAVAILABLE`) and indexed `UserProfile.country` / `UserProfile.status` back the directory filters and facets. -- `ProjectMember` model (`projectId`, `userId`, `role`, `joinedAt`) is the - first-class replacement for the untyped `Project.teamMembers` JSON and backs - `GET /projects/:slug/members`. ## Shared data diff --git a/README.md b/README.md index 01e3bca6..666e8995 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ### Boundless Builders -The public showcase for the builders, projects, and teams shipping on Boundless. +The public showcase for the builders and projects shipping on Boundless. @@ -28,10 +28,11 @@ The public showcase for the builders, projects, and teams shipping on Boundless. **Boundless Builders** is a display-only sub-app of the Boundless platform, served at `builders.boundlessfi.xyz`. It presents the people and work of the ecosystem: -builders, their projects and products, and development teams. +builders and their projects and products. Builder, project, and organization +detail pages live in the main Boundless app; this app links out to them. -This app **only displays** data. Creating, editing, and uploading builders, -projects, and teams all happen in the main Boundless app +This app **only displays** data. Creating, editing, and uploading builders and +projects all happen in the main Boundless app ([boundlessfi.xyz](https://boundlessfi.xyz)). This showcase reads that data and renders it, so expect mostly read (`GET`) flows and no creation forms here. diff --git a/app/about/page.tsx b/app/about/page.tsx index d9231069..5e18ed61 100644 --- a/app/about/page.tsx +++ b/app/about/page.tsx @@ -14,7 +14,7 @@ import { import { siteConfig } from '@/lib/seo/site'; const ABOUT_DESCRIPTION = - 'Learn why Boundless Builders exists and what you will find here: the builders, projects, and teams shipping on Stellar through Boundless.'; + 'Learn why Boundless Builders exists and what you will find here: the builders and projects shipping on Stellar through Boundless.'; export const metadata = buildPageMetadata({ title: 'About', diff --git a/app/layout.tsx b/app/layout.tsx index e68f626a..48be8cfb 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -39,7 +39,6 @@ export const metadata: Metadata = { 'web3 projects', 'Boundless', 'developers', - 'teams', ], openGraph: { ...sharedOpenGraph, diff --git a/app/page.tsx b/app/page.tsx index d157b9b3..ac760eb0 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -46,9 +46,8 @@ export default function Home() { Stellar

- Explore the projects, teams, and creators building across the - Boundless ecosystem. This app showcases the work. Creating and - uploading happens in the main Boundless app. + Explore the projects and creators building across the Boundless + ecosystem.

diff --git a/app/sitemap.ts b/app/sitemap.ts index de344c3c..c756f88d 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -11,6 +11,3 @@ export default function sitemap(): MetadataRoute.Sitemap { priority: route.priority, })); } - -// TODO: When builder and project detail pages ship, extend this with generateSitemaps -// to include dynamic routes. See issue #380 for context. diff --git a/components/about/about-hero.tsx b/components/about/about-hero.tsx index be7c8d03..1b9084b9 100644 --- a/components/about/about-hero.tsx +++ b/components/about/about-hero.tsx @@ -15,7 +15,7 @@ export function AboutHero() {

Boundless Builders is a living showcase of the developers, designers, and - teams shipping across the ecosystem. See who is building, follow their + makers shipping across the ecosystem. See who is building, follow their work, and watch ideas become real.

diff --git a/components/about/what-youll-find.tsx b/components/about/what-youll-find.tsx index 199f66cb..f9196fa0 100644 --- a/components/about/what-youll-find.tsx +++ b/components/about/what-youll-find.tsx @@ -11,15 +11,10 @@ const ITEMS = [ description: 'The products being built, launched, and funded on Boundless, with the teams behind them.', }, - { - title: 'Teams', - description: - 'The organizations turning ideas into shipped work, and the people who make them up.', - }, ]; /** - * About-page section introducing the three things you can explore. Uses the + * About-page section introducing the two things you can explore. Uses the * two-column feature-list layout (purple eyebrow + heading on the left, a * dash-separated list on the right), mirroring the boundless-platform About * mission section. diff --git a/components/landing/stats-strip.tsx b/components/landing/stats-strip.tsx index b3df3339..51ca8b47 100644 --- a/components/landing/stats-strip.tsx +++ b/components/landing/stats-strip.tsx @@ -20,11 +20,6 @@ const STATS = [ path: '/projects?limit=1', queryKey: ['ecosystem-stats', 'projects'], }, - { - label: 'Teams', - path: '/organizations?limit=1', - queryKey: ['ecosystem-stats', 'teams'], - }, ] as const; function NumberSkeleton({ mobile = false }: { mobile?: boolean }) { @@ -39,8 +34,7 @@ function NumberSkeleton({ mobile = false }: { mobile?: boolean }) { /** Every list the strip counts documents the same `pagination` block. */ type CountedList = | Schemas['BuildersDirectoryResponseDto'] - | Schemas['PublicProjectListDto'] - | Schemas['PublicOrganizationListDto']; + | Schemas['PublicProjectListDto']; async function fetchTotal(path: string) { const response = await apiFetch(path); diff --git a/lib/seo/site.ts b/lib/seo/site.ts index 2608ed03..30e6fde4 100644 --- a/lib/seo/site.ts +++ b/lib/seo/site.ts @@ -21,7 +21,7 @@ export const siteConfig = { 'https://builders.boundlessfi.xyz' ), description: - 'Discover the builders, projects, and teams shipping on Stellar through Boundless. A public showcase of the people and products of the ecosystem.', + 'Discover the builders and projects shipping on Stellar through Boundless. A public showcase of the people and products of the ecosystem.', twitterHandle: '@boundless_fi', locale: 'en_US', /** The main Boundless app, where builders sign up and create. */