Skip to content

feat(backend): add experimental POPPY metadata helper - #10404

Draft
thiskevinwang wants to merge 3 commits into
mainfrom
kevin/aie-1940-poppy-metadata-helper
Draft

thiskevinwang wants to merge 3 commits into
mainfrom
kevin/aie-1940-poppy-metadata-helper

Conversation

@thiskevinwang

@thiskevinwang thiskevinwang commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Description

Add clerkClient.__experimental_getPoppyMetadata() so server routes can fetch the instance's FAPI discovery document and return it on the customer's domain.

The helper defaults to the configured publishable key's FAPI hostname. An explicit proxyUrl option supports instances that use a customer proxy without a FAPI CNAME. The proxy path prefix is retained. Proxy failures do not fall back to a direct request.

Both paths send no credentials, reject redirects, and return parsed JSON as unknown without a local POPPY interface or shape checks. HTTP errors retain their status. Each call fetches fresh metadata. No backend /experimental entry exists, so the method uses the repository's experimental prefix.

import { clerkClient } from '@clerk/nextjs/server';

export async function GET() {
  const client = await clerkClient();
  return Response.json(await client.__experimental_getPoppyMetadata(), {
    headers: { 'Cache-Control': 'no-store' },
  });
}

For a proxy-only instance, pass the configured absolute proxy URL. Resolve relative proxy paths at the caller:

await client.__experimental_getPoppyMetadata({
  proxyUrl: new URL('/__clerk', request.url),
});

The shared backend client also exposes the method through Express, Hono, and TanStack Start. These examples assume configured Clerk SDKs consuming this backend version. They illustrate the proposed API; framework routes have not been run end to end.

Express

import { clerkClient } from '@clerk/express';
import express from 'express';

const app = express();

app.get('/.well-known/poppy.json', async (_req, res, next) => {
  try {
    const metadata = await clerkClient.__experimental_getPoppyMetadata();
    res.set('Cache-Control', 'no-store').json(metadata);
  } catch (error) {
    next(error);
  }
});

Hono

import { clerkMiddleware } from '@clerk/hono';
import { Hono } from 'hono';

const app = new Hono();
app.use('*', clerkMiddleware());

app.get('/.well-known/poppy.json', async c => {
  const metadata = await c.get('clerk').__experimental_getPoppyMetadata();
  return Response.json(metadata, {
    headers: { 'Cache-Control': 'no-store' },
  });
});

TanStack Start

For example, place this route in src/routes/[.]well-known/poppy[.]json.ts. The escaped dots keep the literal discovery path. The handler follows TanStack Start's server route convention.

import { clerkClient } from '@clerk/tanstack-react-start/server';
import { createFileRoute } from '@tanstack/react-router';

export const Route = createFileRoute('/.well-known/poppy.json')({
  server: {
    handlers: {
      GET: async () => {
        const metadata = await clerkClient().__experimental_getPoppyMetadata();
        return Response.json(metadata, {
          headers: { 'Cache-Control': 'no-store' },
        });
      },
    },
  },
});

Part of AIE-1940. Requires the FAPI metadata endpoint. The returned organization domain remains the instance primary domain; selecting another configured customer domain remains separate work.

Checklist

  • pnpm --filter @clerk/backend test passes in Node and Edge runtimes, with 1,712 tests passed in each, including the existing customer proxy request path.
  • pnpm build runs as expected for @clerk/backend and its dependencies.
  • Required public JSDoc describes the credential-free fetch and experimental status.
  • Customer setup documentation updated.

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
clerk-js-sandbox Ready Ready Preview Oct 23, 2026 9:37pm UTC
swingset Ready Ready Preview Oct 23, 2026 9:37pm UTC

Request Review

@changeset-bot

changeset-bot Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7aaa946

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@clerk/backend Minor
@clerk/astro Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/hono Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/swingset Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@10404

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@10404

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@10404

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@10404

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@10404

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@10404

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@10404

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@10404

@clerk/expo-biometrics

npm i https://pkg.pr.new/@clerk/expo-biometrics@10404

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@10404

@clerk/expo-native-components

npm i https://pkg.pr.new/@clerk/expo-native-components@10404

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@10404

@clerk/express

npm i https://pkg.pr.new/@clerk/express@10404

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@10404

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@10404

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@10404

@clerk/mosaic

npm i https://pkg.pr.new/@clerk/mosaic@10404

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@10404

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@10404

@clerk/react

npm i https://pkg.pr.new/@clerk/react@10404

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@10404

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@10404

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@10404

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@10404

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@10404

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@10404

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@10404

commit: 7aaa946

This branch was successfully deployed

2 active deployments
Preview – swingset — 7aaa946a Deployed Oct 23, 2026 by vercel[bot]
Preview – clerk-js-sandbox — 7aaa946a Deployed Oct 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant