chore: groundwork for SEO fixes and tech&vis debt
This commit is contained in:
1 parent
02fb8751fd
commit
9f4ce426a8
11 files changed
+175
-24
No files matched your search
@@ -75,7 +75,7 @@
|
||||
<sc-if value="{{ ep.noFields }}"><span style="color:var(--ui-text-muted)">No request body.</span></sc-if></div>
|
||||
<dc-import name="CodeSnippet" tabs="{{ ep.snips }}" hint-size="100%,200px"></dc-import>
|
||||
<div style="display:flex;flex-direction:column;gap:6px"><span style="font-weight:600;color:var(--ui-text-highlighted)">Errors</span>
|
||||
<sc-for list="{{ ep.errs }}" as="e" hint-placeholder-count="2"><div title="{{ e.cap }}" style="display:flex;align-items:baseline;gap:10px"><span style="width:36px;height:20px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--ui-border-accented);color:var(--ui-text-toned);font:500 11px 'IBM Plex Mono',monospace">{{ e.c }}</span><span style="min-width:0;color:var(--ui-text-toned);text-wrap:pretty">{{ e.cap }}</span></div></sc-for></div>
|
||||
<sc-for list="{{ ep.errs }}" as="e" hint-placeholder-count="2"><div title="{{ e.cap }}" style="display:flex;align-items:baseline;gap:10px"><span style="width:36px;height:20px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--ui-border-accented);color:var(--ui-text-toned);font:500 11px 'IBM Plex Mono',monospace">{{ e.c }}</span><sc-if value="{{ e.plain }}"><span style="min-width:0;color:var(--ui-text-toned);text-wrap:pretty">{{ e.cap }}</span></sc-if><sc-if value="{{ e.code }}"><span style="min-width:0;color:var(--ui-text-toned)"><code>{{ e.cap }}</code></span></sc-if></div></sc-for></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
@@ -104,7 +104,7 @@
|
||||
<span style="color:var(--ui-text-toned);text-wrap:pretty">Every error is a plain-text body with a single sentence. The status code is in the HTTP status line, and the Content-Type is text/plain.</span>
|
||||
<div style="border:1px solid var(--ui-border);background:var(--ui-bg);overflow:hidden">
|
||||
<div style="display:grid;grid-template-columns:{{ errCols }};gap:12px;padding:8px 12px;background:var(--ui-bg-elevated);color:var(--ui-text-muted);font-weight:500"><span>Status</span><span>Meaning</span><sc-if value="{{ desk }}"><span>Typical cause</span></sc-if></div>
|
||||
<sc-for list="{{ errRows }}" as="r" hint-placeholder-count="8"><div style="display:grid;grid-template-columns:{{ errCols }};gap:2px 12px;padding:10px 12px;border-top:1px solid var(--ui-border)"><span style="font:500 13px 'IBM Plex Mono',monospace;color:var(--ui-text-highlighted)">{{ r.c }}</span><span style="font-weight:500;color:var(--ui-text-highlighted)">{{ r.m }}</span><span style="grid-column:{{ errCause }};color:var(--ui-text-toned);text-wrap:pretty">{{ r.w }}</span></div></sc-for>
|
||||
<sc-for list="{{ errRows }}" as="r" hint-placeholder-count="8"><div style="display:grid;grid-template-columns:{{ errCols }};gap:2px 12px;padding:10px 12px;border-top:1px solid var(--ui-border)"><span style="font:500 13px 'IBM Plex Mono',monospace;color:var(--ui-text-highlighted)">{{ r.c }}</span><span style="font-weight:500;color:var(--ui-text-highlighted)">{{ r.m }}</span><span style="grid-column:{{ errCause }};color:var(--ui-text-toned);text-wrap:pretty">{{ r.w }}</span><sc-if value="{{ r.n }}"><span style="grid-column:{{ errNoteCol }};color:var(--ui-text-muted);font-size:12px;line-height:18px;text-wrap:pretty">{{ r.n }}</span></sc-if></div></sc-for>
|
||||
</div>
|
||||
<dc-import name="CodeSnippet" tabs="{{ errSnips }}" hint-size="100%,120px"></dc-import>
|
||||
</section>
|
||||
@@ -189,7 +189,7 @@ class Component extends DCLogic {
|
||||
] },
|
||||
seo: { title: 'Search and sharing', desc: 'RenewCMS doesn\'t render pages or add meta tags. These endpoints give your frontend the resolved SEO data and the list of published URLs.', eps: [
|
||||
A('seo-get', 'GET', '/v1/article/{id}/seo', 'The resolved SEO object for one article: title (with the site template applied), description, canonical URL, robots, Open Graph and Twitter values, image with alt, authors, dates and ready-made Article JSON-LD. Every empty field already holds its fallback. Drafts answer 404 to anonymous callers.', 'Public', 1, [e401, e404], [], { pub: 1, r: j({ title: 'How we price a bathroom renovation | Renew', description: 'A bathroom renovation is priced by room size, plumbing changes and finish level.', canonical_url: 'https://renew.example/how-we-price-a-bathroom-renovation', robots: 'index, follow', og: { type: 'article', title: 'How we price a bathroom renovation | Renew', image: 'https://renew.example/media/north-wall.jpg', image_alt: 'A tiled bathroom wall', site_name: 'Renew' }, twitter: { card: 'summary_large_image' }, authors: [{ name: 'Inès Duarte', url: 'https://ines-duarte.example', same_as: [] }], published_at: '2026-03-12T09:14:00Z', modified_at: '2026-10-15T11:02:00Z', json_ld: { '@type': 'Article' } }) }),
|
||||
A('sitemap', 'GET', '/v1/site/{key}/sitemap', 'Published article URLs for one site, each with its last-modified date and a noindex flag, one page at a time. Use it to build your sitemap.xml. The total is in the X-Total-Count response header.', 'Public', 1, [[400, 'Invalid page or size.'], e401, [404, 'Site not found']], [S('page', 'integer', 'No', '1 or higher. Default 1.'), S('size', 'integer', 'No', 'One of 25, 50, 100 or 500. Default 100.')], { qp: 1, pub: 1, r: j([{ url: 'https://renew.example/how-we-price-a-bathroom-renovation', modified_at: '2026-10-15T11:02:00Z', noindex: false }]) })
|
||||
A('sitemap', 'GET', '/v1/site/{key}/sitemap', 'Published article URLs for one site, each with its last-modified date and a noindex flag, one page at a time. Use it to build your sitemap.xml. The total is in the X-Total-Count response header.', 'Public', 1, [[400, mm], e401, [404, 'site_not_found', true]], [S('page', 'integer', 'No', '1 or higher. Default 1.'), S('size', 'integer', 'No', 'One of 25, 50, 100 or 500. Default 100.')], { qp: 1, pub: 1, r: j([{ url: 'https://renew.example/how-we-price-a-bathroom-renovation', modified_at: '2026-10-15T11:02:00Z', noindex: false }]) })
|
||||
] },
|
||||
media: { title: 'Media', desc: 'The image library. One image can be used in many articles.', eps: [
|
||||
A('med-list', 'GET', '/v1/media/', 'List images.', 'Verified user', 1, [e401], [], { r: j([{ id: 4, filename: 'north-wall.jpg', size: 3900000 }]) }),
|
||||
@@ -239,7 +239,7 @@ class Component extends DCLogic {
|
||||
bodyTitle: e.qp ? 'Query parameters' : e.multi ? 'Request body · multipart/form-data, 1 file field' : e.body ? 'Request body · JSON' : 'Request body', hasFields: e.fields.length > 0, noFields: e.fields.length === 0, fields: e.fields,
|
||||
tabs: ['fetch', 'curl', 'Response'].map(t => { const k = t === 'Response' ? 'response' : t, on = (k === tab) || (t === tab); return { t, on, bd: on ? 'var(--ui-primary)' : 'transparent', fg: on ? 'var(--ui-text-highlighted)' : 'var(--ui-text-toned)', pick: () => this.setState(s => ({ tab: { ...s.tab, [e.id]: k } })) } }),
|
||||
snips: [{ k: 'fetch', label: 'fetch', code: fe }, { k: 'curl', label: 'curl', code: curl }, { k: 'response', label: 'Response', code: e.r }],
|
||||
errs: e.errs.map(([c, cap]) => ({ c, cap })) }
|
||||
errs: e.errs.map(([c, cap, code]) => ({ c, cap, code: !!code, plain: !code })) }
|
||||
}) }
|
||||
})
|
||||
}
|
||||
@@ -267,11 +267,11 @@ class Component extends DCLogic {
|
||||
fCols: mob ? 'minmax(0,1fr) auto auto' : '120px 72px 72px minmax(0,1fr)', ruleCol: mob ? '1 / -1' : 'auto',
|
||||
sessGroups: [sg('System · owner only', [['GET', '/v1/system/update', 'Update status'], ['POST', '/v1/system/update/check', 'Check for update'], ['POST', '/v1/system/update/download', 'Download update'], ['POST', '/v1/system/update/restart', 'Restart']]), sg('Sign in and account', [['POST', '/v1/auth/login', 'Log in'], ['POST', '/v1/auth/logout', 'Log out'], ['POST', '/v1/auth/register', 'Register'], ['POST', '/v1/auth/verify', 'Verify email'], ['POST', '/v1/auth/password-reset', 'Reset password']]), sg('API key management', [['GET', '/v1/api-key', 'List keys'], ['POST', '/v1/api-key', 'Create a key'], ['DELETE', '/v1/api-key/{id}', 'Revoke a key']])],
|
||||
sessCols: mob ? 'none' : '280px minmax(0,1fr) auto', sessGap: mob ? '2px' : '16px', sessPad: mob ? '8px 14px' : '0 14px', chipSelf: mob ? 'flex-start' : 'center',
|
||||
errCols: mob ? '56px minmax(0,1fr)' : '64px 200px minmax(0,1fr)', errCause: mob ? '2' : 'auto',
|
||||
errCols: mob ? '56px minmax(0,1fr)' : '64px 200px minmax(0,1fr)', errCause: mob ? '2' : 'auto', errNoteCol: mob ? '2' : '3',
|
||||
errRows: [
|
||||
{ c: 400, m: 'Bad request', w: '"The request cannot be processed due to a mismatch in the format of the body." or "The expiry must be a date in the future." Image requests answer with a JSON body whose error is "unknown_variant" or "unsupported_parameter".' },
|
||||
{ c: 401, m: 'Unauthorized', w: '"You must be logged in to access this resource." Sent for an invalid, unknown, expired or revoked key, even on public routes, and for a key whose user was deleted or unverified.' },
|
||||
{ c: 403, m: 'Forbidden', w: '"This action needs a real session." (a session-only route called with a key), "Only the owner can do this." (site SEO defaults: title template, default description, site name and default robots are owner only; article SEO fields need only the right to edit the article) or "You must verify your account to access this resource."' },
|
||||
{ c: 403, m: 'Forbidden', n: 'Site SEO defaults are owner only. Article SEO fields need only the right to edit the article.', w: '"This action needs a real session." (a session-only route called with a key), "Only the owner can do this." or "You must verify your account to access this resource."' },
|
||||
{ c: 404, m: 'Not found', w: '"Article not found", "Image not found", "Invite not found" or "API key not found". Drafts answer 404 to anonymous callers.' },
|
||||
{ c: 429, m: 'Too many requests', w: '"Too many requests. Please try again later." A per-key limit of 120 requests per minute also sends a Retry-After header.' },
|
||||
{ c: 500, m: 'Server error', w: '"Internal server error"' }
|
||||
|
||||
Reference in new issue
Block a user