Pages and routing
Create a static endpoint
Return JSON, text, XML, or another response from a .js or .ts route file.
A route doesn’t have to return HTML. Put a .ts or .js file under src/pages/ and export a function named after an HTTP method. That’s an endpoint. It returns a Response object, and you decide what goes in it.
Here is src/pages/api/status.ts:
export function GET() {
return new Response(JSON.stringify({ ok: true }), {
headers: { 'Content-Type': 'application/json' }
})
}
Open /api/status in the dev server and you get {"ok":true}. The Response is the standard Web API one, the same you’d use in a service worker or in a Cloudflare Worker. No Astro-specific class to learn.
What a static build does with it
In a static project, Astro runs the GET handler once during npm run build. It writes the response body to a file, here dist/api/status. If you want the file to have an extension, put it in the route name: src/pages/api/status.json.ts becomes /api/status.json.
This is how you generate an RSS feed, a sitemap.xml, or a JSON file a script consumes. Build once, serve as a static file.
The limits of static
A static response is the same for every visitor. It can’t read a cookie or a query string, because there is no request when it runs. And it can’t handle a POST after deployment. There is nothing listening.
For that you need an on-demand endpoint. It runs for each incoming request, can read headers and the body, validate input, and return current data. It also needs an adapter and a server runtime. Same file shape, different moment of execution.
Get the response right
Return accurate headers and status codes. JSON needs a JSON content type, or some clients refuse to parse it. A record that doesn’t exist should return a 404, not a 200 with {"error":"not found"} in the body. Status codes are how the rest of the web understands your response.
Nothing is trusted by default
Being inside an Astro endpoint gives you no authentication and no validation. Route parameters, headers, and request bodies come from the client. Check them as you would in any server code.
Try this on your project: create the endpoint above, build, and open dist/api/status. Then change ok: true to ok: false and open the file again without rebuilding. It still says true. Static means static, until the next build.
Lesson completed