Skip to content

feat(web): /explore federated package browser (Phase D v0)#3

Merged
arwenizEr merged 1 commit into
mainfrom
feat/explore-page
May 21, 2026
Merged

feat(web): /explore federated package browser (Phase D v0)#3
arwenizEr merged 1 commit into
mainfrom
feat/explore-page

Conversation

@arwenizEr
Copy link
Copy Markdown
Collaborator

Summary

First slice of Phase D. Ships a public, no-auth /explore page that mirrors pakx search from the CLI.

  • lib/registry.ts — Server-side TS port of the official-mcp + smithery source clients. Hits the upstream public APIs directly; no pakx backend dependency. Parallel fetch via Promise.allSettled, dedupes by source/id, sorts by name, returns per-source errors so one failing source doesn't blank the page.
  • app/explore/page.tsx — Server component. ?q= drives a GET form, page is force-dynamic. Empty state, error banner, per-package card with source badge and version.
  • components/site-nav.tsx — Shared top nav (pakx / Explore / GitHub / Releases), mounted in the root layout so it shows on every page.

Deferred to follow-ups

  • /p/[owner]/[name] package detail page
  • /dashboard (needs Auth.js + pakx-registry)
  • pakx-registry as a third federated source (needs deployed backend)

Test plan

  • pnpm lint clean
  • pnpm build green (4 pages generated, /explore correctly marked dynamic)
  • Local dev server: GET /explore, GET /explore?q=github, GET / all return 200 with results rendered
  • Vercel preview deploy renders /explore against real upstream APIs

First slice of Phase D. Ships a public, no-auth /explore page that
mirrors `pakx search` from the CLI.

- `lib/registry.ts` — server-side TS port of the official-mcp + smithery
  source clients. Hits the upstream public APIs directly; no pakx
  backend dependency. Parallel fetch via `Promise.allSettled`, dedupes
  by `source/id`, sorts by name, returns per-source errors so a single
  failing source does not blank the page.
- `app/explore/page.tsx` — server component. `?q=` drives a GET form,
  page is `force-dynamic`. Empty state, error banner, per-package card
  with source badge and version.
- `components/site-nav.tsx` — shared top nav (pakx / Explore / GitHub
  / Releases), now mounted in the root layout so it appears on every
  page.

Deferred to follow-up PRs:
- `/p/[owner]/[name]` package detail page
- `/dashboard` (needs Auth.js + pakx-registry)
- pakx-registry as a third federated source (needs deployed backend)
@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pakx-web Ready Ready Preview, Comment May 21, 2026 1:52pm

@arwenizEr arwenizEr merged commit a7e90b6 into main May 21, 2026
2 checks passed
@arwenizEr arwenizEr deleted the feat/explore-page branch May 21, 2026 13:53
arwenizEr added a commit to pakxdev/pakx that referenced this pull request May 21, 2026
* fix(registry-client): accept 2025-12-11 wrapped MCP Registry schema

`registry.modelcontextprotocol.io` switched its list and detail
responses to a new envelope:

    { "server": <core>, "_meta": { ... } }

The flat shape (`core` fields at the top level) is still emitted by
older deployments. Today `pakx search` against the real upstream
returns zero MCP results because every entry hits the existing
`#[derive(Deserialize)]` on the flat-only `ServerRaw` and fails.

Surfaced while writing the TS port of this client for
`pakx-web` `/explore` (pakxdev/pakx-web#3) — both layers needed
the same fix.

- Split `ServerRaw` into:
  - `ServerCore` — the flat field set (unchanged semantics).
  - `ServerRaw` — `#[serde(untagged)]` enum over `Wrapped { server,
    _meta }` and `Flat(ServerCore)`. Decoders try `Wrapped` first;
    legacy flat payloads fall through.
- `into_package` now folds `_meta` (when present) into the
  `install_hints` object so the resolver can read upstream status
  flags without re-parsing.
- Two new wiremock tests cover the wrapped shape on both `search`
  and `fetch`; existing flat-shape tests still pass unchanged.

* fix(registry-client): satisfy clippy::use_self in ServerRaw impl

CI clippy rejected `ServerRaw::Wrapped` / `ServerRaw::Flat` inside
the impl block. Use `Self::*` instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant