Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

lith: route api.aesthetic.computer + /api + /api-docs to api-docs

On Netlify these were redirect rules in netlify.toml; lith's Express server
never learned about them, so api.aesthetic.computer/, aesthetic.computer/api,
and aesthetic.computer/api-docs were falling through to the prompt piece
instead of the public API reference.

- Host middleware now rewrites api.aesthetic.computer/ and api.prompt.ac/
to /api-docs.
- Direct routes added for /api, /api-docs, /api-docs.json (all serve the
api-docs function, which content-negotiates HTML vs JSON).
- api-docs HTML renderer is now defensive about missing example fields
(curl/js/py/response can be omitted without breaking the page).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+19 -8
+11
lith/server.mjs
··· 172 172 req.url = "/notepat" + (req.url === "/" ? "" : req.url.slice(req.path.length)); 173 173 } 174 174 175 + // api.aesthetic.computer / api.prompt.ac → api-docs function (public API reference) 176 + if (host === "api.aesthetic.computer" || host === "api.prompt.ac") { 177 + if (req.path === "/" || req.path === "") { 178 + req.url = "/api-docs" + (req.url.includes("?") ? req.url.slice(req.url.indexOf("?")) : ""); 179 + } 180 + } 181 + 175 182 next(); 176 183 }); 177 184 ··· 948 955 }); 949 956 950 957 // API functions (matches Netlify redirect rules) 958 + // Bare `/api` serves the public API reference (same function that backs api.aesthetic.computer). 959 + app.all("/api", directFn("api-docs")); 951 960 app.all("/api/:fn", handleFunctionResolved); 952 961 app.all("/api/:fn/*rest", handleFunctionResolved); 953 962 app.all("/.netlify/functions/:fn", handleFunction); ··· 986 995 app.all("/docs", directFn("docs")); 987 996 app.all("/docs.json", directFn("docs")); 988 997 app.all("/docs/*rest", directFn("docs")); 998 + app.all("/api-docs", directFn("api-docs")); 999 + app.all("/api-docs.json", directFn("api-docs")); 989 1000 app.all("/media-collection", directFn("media-collection")); 990 1001 app.all("/media-collection/*rest", directFn("media-collection")); 991 1002 app.all("/device-login", directFn("device-login"));
+8 -8
system/netlify/functions/api-docs.mjs
··· 1097 1097 <p><code class="path">${docs.baseURL}${endpoint.path}</code></p> 1098 1098 <p>${endpoint.description}</p> 1099 1099 1100 - ${endpoint.examples.map((example, exIdx) => ` 1101 - <h3>${example.title}</h3> 1102 - <p>${example.description}</p> 1100 + ${(endpoint.examples || []).map((example, exIdx) => ` 1101 + <h3>${example.title || ''}</h3> 1102 + <p>${example.description || ''}</p> 1103 1103 1104 1104 <div class="tabs" id="tabs-${idx}-${exIdx}"> 1105 1105 <button class="tab active" onclick="showTab(${idx}, ${exIdx}, 'curl')">curl</button> ··· 1108 1108 </div> 1109 1109 1110 1110 <div class="tab-content active" id="content-${idx}-${exIdx}-curl"> 1111 - <pre>${escapeHTML(example.curl)}</pre> 1111 + <pre>${escapeHTML(example.curl || '')}</pre> 1112 1112 </div> 1113 1113 <div class="tab-content" id="content-${idx}-${exIdx}-js"> 1114 - <pre>${escapeHTML(example.javascript)}</pre> 1114 + <pre>${escapeHTML(example.javascript || '')}</pre> 1115 1115 </div> 1116 1116 <div class="tab-content" id="content-${idx}-${exIdx}-py"> 1117 - <pre>${escapeHTML(example.python)}</pre> 1117 + <pre>${escapeHTML(example.python || '')}</pre> 1118 1118 </div> 1119 1119 1120 - <h4>response:</h4> 1121 - <pre><code>${JSON.stringify(example.response.body, null, 2)}</code></pre> 1120 + ${example.response ? `<h4>response:</h4> 1121 + <pre><code>${escapeHTML(JSON.stringify(example.response.body ?? example.response, null, 2))}</code></pre>` : ''} 1122 1122 `).join('')} 1123 1123 </div> 1124 1124 `).join('')}