A calm place to write long-form, and publish it to the open social web.
skypress.blog/
1import type { APIRoute } from 'astro';
2import { OAUTH_REDIRECT_PATHS } from '../lib/auth/config';
3
4/**
5 * The atproto OAuth client metadata document (Decision 0004).
6 *
7 * Served by the WORKER (`prerender = false`), not as a static asset — static `.json`
8 * serving on Cloudflare proved unreliable at the deployed origin, and the worker route is
9 * guaranteed to run. Generated from the REQUEST origin so `client_id` always equals the
10 * URL it's fetched from (works on the apex domain, www, or any preview origin), and the
11 * `redirect_uris` cover every OAuth-island route (`/editor/` and `/write/`, canonical
12 * trailing slash — see `OAUTH_REDIRECT_PATHS` and docs/specs/sp7-deploy.md). Both are
13 * registered so signing in from the writing-first `/write` flow returns there, not to
14 * `/editor` (Decision 0020).
15 *
16 * In dev (loopback) the browser client builds its own metadata and never fetches this;
17 * this is the production/hosted client.
18 */
19export const prerender = false;
20
21export const GET: APIRoute = ( { url } ) => {
22 const origin = url.origin;
23 const metadata = {
24 client_id: `${ origin }/client-metadata.json`,
25 client_name: 'SkyPress',
26 client_uri: origin,
27 redirect_uris: OAUTH_REDIRECT_PATHS.map( ( path ) => `${ origin }${ path }` ),
28 scope: 'atproto transition:generic',
29 grant_types: [ 'authorization_code', 'refresh_token' ],
30 response_types: [ 'code' ],
31 token_endpoint_auth_method: 'none',
32 application_type: 'web',
33 dpop_bound_access_tokens: true,
34 };
35 return new Response( JSON.stringify( metadata, null, 2 ), {
36 headers: {
37 'content-type': 'application/json; charset=utf-8',
38 'cache-control': 'public, max-age=300',
39 },
40 } );
41};