Skip to content

Fix public card URLs pointing to the API host instead of the card host#1

Open
dhve wants to merge 1 commit into
projnanda:mainfrom
dhve:fix/public-card-url-host
Open

Fix public card URLs pointing to the API host instead of the card host#1
dhve wants to merge 1 commit into
projnanda:mainfrom
dhve:fix/public-card-url-host

Conversation

@dhve

@dhve dhve commented Jun 14, 2026

Copy link
Copy Markdown

Problem

Public agent cards are served from agentcards.host39.org, but the dashboard builds the public URL from NEXT_PUBLIC_HOST39_API_URL (host39.org). In production host39.org only proxies /auth, /cards, and /.well-known to the API; every other path (including /personal/<email>/<slug>.json and /<domain>/<slug>.json) is routed to the Next.js app. So the URL a user copies from the dashboard to submit to the NANDA Index returns the Next.js 404 page.

Verified against the live deployment:

  • GET https://host39.org/personal/test@example.com/agent.json -> 404 text/html (Next.js)
  • GET https://agentcards.host39.org/personal/test@example.com/agent.json -> 404 application/json (API)

Separately, the server's PUBLIC_BASE_URL is never set in the prod compose or .env.prod.example, so it falls back to http://localhost:3010. That value is baked into /.well-known/ai-catalog.json entries[].url and each card's _meta.publicUrl, so the Index would ingest localhost URLs.

Changes

  • web: add NEXT_PUBLIC_HOST39_CARDS_URL and use it as the base in getPublicUrl, falling back to the API URL for local dev (where the API serves cards on the same origin). Wired through web/Dockerfile and both compose files.
  • server: set PUBLIC_BASE_URL in docker-compose.prod.yml, docker-compose.yml, and both .env examples (https://agentcards.host39.org in prod).
  • add the required DATABASE_URL to .env.example so the documented non-Docker dev flow (cp ../.env.example .env && npm run migrate) no longer fails on a missing var.
  • run the dev compose as NODE_ENV=development (it was production, which silently accepts the shipped default JWT secret).
  • README: document the new vars and correct the JWT_SECRET minimum length (config enforces 16, the table said 32).

Notes

The web app typechecks clean. Domain card paths on the live agentcards.host39.org currently 301-redirect; the repo Caddyfile.prod regex matches those paths correctly, so the deployed Caddy config may be out of sync with the repo (not changed here).

Public agent cards are served from agentcards.host39.org, but the dashboard
built URLs from NEXT_PUBLIC_HOST39_API_URL (host39.org), which Caddy routes to
the Next.js app, so every copied or submitted card URL 404s. The server's
PUBLIC_BASE_URL was also never set in prod, so /.well-known/ai-catalog.json and
each card's _meta.publicUrl emitted http://localhost:3010.

- web: add NEXT_PUBLIC_HOST39_CARDS_URL and use it as the public-URL base
  (falls back to the API URL for local dev), wired through the web Dockerfile
  and compose build args
- server: set PUBLIC_BASE_URL in the prod and dev compose files plus .env examples
- add the required DATABASE_URL to .env.example (documented non-Docker dev was
  crashing on a missing var)
- run the dev compose as NODE_ENV=development (it was production, silently
  accepting the shipped default JWT secret)
- README: document the new vars and correct the JWT_SECRET minimum length
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