A calm place to write long-form, and publish it to the open social web.
skypress.blog/
1/**
2 * Source of truth for reader error-page copy + HTTP status (SP12).
3 *
4 * Pure and dependency-free (no @wordpress, no network) so it can run on the read
5 * path (AGENTS.md #3) and be unit-tested directly. Copy avoids em dashes by house
6 * rule; the eyebrow uses a middle-dot kicker in SkyPress's editorial voice.
7 */
8export type ErrorKind =
9 | 'writer-not-found'
10 | 'publication-not-found'
11 | 'article-not-found'
12 | 'not-found'
13 | 'server-error';
14
15export interface ErrorContext {
16 handle?: string;
17 slug?: string;
18 publicationName?: string;
19}
20
21export interface ErrorSceneCopy {
22 status: number;
23 eyebrow: string;
24 heading: string;
25 subline: string;
26}
27
28export function errorScene(
29 kind: ErrorKind,
30 context: ErrorContext = {}
31): ErrorSceneCopy {
32 switch ( kind ) {
33 case 'writer-not-found':
34 return {
35 status: 404,
36 eyebrow: '404 · no one by that name',
37 heading: `No writer at @${ context.handle ?? '' }`,
38 subline:
39 'Nobody on the network goes by that handle yet. It might have a typo.',
40 };
41 case 'publication-not-found':
42 return {
43 status: 404,
44 eyebrow: '404 · publication not found',
45 heading: 'No publication by that name',
46 subline: `@${ context.handle ?? '' } hasn't published anything under "${ context.slug ?? '' }".`,
47 };
48 case 'article-not-found':
49 return {
50 status: 404,
51 eyebrow: '404 · story not found',
52 heading: 'This story set below the horizon',
53 subline: `It's no longer part of ${ context.publicationName ?? 'this publication' }. It may have been unpublished or moved.`,
54 };
55 case 'server-error':
56 return {
57 status: 500,
58 eyebrow: '500 · overcast',
59 heading: "The sky's a bit cloudy right now",
60 subline:
61 'Something went wrong on our end. Give it a moment, then try again.',
62 };
63 case 'not-found':
64 default:
65 return {
66 status: 404,
67 eyebrow: '404 · off the map',
68 heading: 'This page set below the horizon',
69 subline: "There's nothing to read at this address.",
70 };
71 }
72}