Node.js adapter for Astro framework enabling server-side rendering and standalone server deployments
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Handler creation functions for different deployment modes including middleware, standalone, application rendering, and static file serving.
Creates Express/Connect compatible middleware with error handling for integration with existing Node.js servers.
/**
* Creates middleware compatible with Express, Connect, and similar frameworks
* Supports both normal middleware and error middleware patterns
* @param app - NodeApp instance for rendering Astro pages
* @param options - Resolved adapter options including mode and paths
* @returns RequestHandler function compatible with Express middleware
*/
function createMiddleware(app: NodeApp, options: Options): RequestHandler;
type RequestHandler = (
req: IncomingMessage,
res: ServerResponse,
next?: (err?: unknown) => void,
locals?: object
) => void | Promise<void>;Usage Examples:
import express from "express";
import { NodeApp } from "astro/app/node";
import { createExports } from "@astrojs/node/server.js";
const app = express();
const astroApp = new NodeApp(manifest);
const { handler: astroHandler } = createExports(manifest, options);
// Mount Astro as middleware
app.use(astroHandler);
// Other Express routes can be added
app.get("/api/health", (req, res) => {
res.json({ status: "ok" });
});
app.listen(3000);Error Handling Features:
Creates complete request handler for standalone mode combining static file serving with SSR rendering.
/**
* Creates standalone request handler combining static and app handlers
* Validates request URLs and routes to appropriate handler
* @param app - NodeApp instance for SSR rendering
* @param options - Resolved adapter options including client paths
* @returns Complete request handler for http.createServer
*/
function createStandaloneHandler(
app: NodeApp,
options: Options
): (req: http.IncomingMessage, res: http.ServerResponse) => void;Usage Examples:
import http from "http";
import { NodeApp } from "astro/app/node";
import { createExports } from "@astrojs/node/server.js";
const app = new NodeApp(manifest);
const { handler } = createExports(manifest, options);
const server = http.createServer(handler);
server.listen(8080, "localhost");Request Processing:
Creates Node.js request handler specifically for on-demand rendered pages with error tracking and unhandled rejection monitoring.
/**
* Creates handler for on-demand rendered pages with AsyncLocalStorage tracking
* Compatible with http.createServer and Connect middleware
* @param app - NodeApp instance for page rendering
* @param options - Resolved adapter options including error page host
* @returns RequestHandler for SSR page rendering
*/
function createAppHandler(app: NodeApp, options: Options): RequestHandler;Advanced Features:
Usage Examples:
// Note: createAppHandler is not directly exported, use createExports instead
import { createExports } from "@astrojs/node/server.js";
const { handler: appHandler } = createExports(manifest, {
...options,
experimentalErrorPageHost: "https://cdn.example.com"
});
// Use with custom server
const server = http.createServer(appHandler);Error Page Host Configuration:
const prerenderedErrorPageFetch = originUrl
? (url: string) => {
const errorPageUrl = new URL(url);
errorPageUrl.protocol = originUrl.protocol;
errorPageUrl.host = originUrl.host;
return fetch(errorPageUrl);
}
: undefined;Creates handler for static files and prerendered pages with caching, trailing slash handling, and header support.
/**
* Creates handler for static files and prerendered pages
* Handles trailing slash redirects, caching headers, and static header injection
* @param app - NodeApp instance for route matching and base path handling
* @param options - Resolved adapter options including client path and assets
* @returns Static file handler with SSR fallback capability
*/
function createStaticHandler(
app: NodeApp,
options: Options
): (req: IncomingMessage, res: ServerResponse, ssr: () => unknown) => void;Key Features:
trailingSlash option_astro/ directoryindex.html serving for directories.well-known/ files, denies other dotfilesUsage Examples:
// Note: createStaticHandler is not directly exported, it's used internally
// For static file handling, use the standalone handler from createExports:
import { createExports } from "@astrojs/node/server.js";
const { handler } = createExports(manifest, options); // Includes static handling
// The handler automatically handles static files and falls back to SSR
http.createServer(handler).listen(8080);Trailing Slash Behavior:
interface TrailingSlashOptions {
/** Never allow trailing slashes - redirect to remove them */
'never': '301 redirect from /path/ to /path';
/** Always require trailing slashes - redirect to add them */
'always': '301 redirect from /path to /path/';
/** Ignore trailing slashes - serve content for both */
'ignore': 'serve /path/index.html for both /path and /path/';
}Caching Headers:
/_astro/*): Cache-Control: public, max-age=31536000, immutablesend library caching behaviorimport express from "express";
import { createMiddleware } from "@astrojs/node";
const app = express();
// Serve static files from public directory
app.use(express.static("public"));
// Mount Astro middleware
app.use(createMiddleware(astroApp, options));
// API routes after Astro
app.use("/api", apiRouter);
app.listen(3000);import http from "http";
import { createAppHandler, createStaticHandler } from "@astrojs/node";
const appHandler = createAppHandler(app, options);
const staticHandler = createStaticHandler(app, options);
const server = http.createServer((req, res) => {
// Custom logic before handlers
if (req.url.startsWith("/health")) {
res.writeHead(200);
res.end("OK");
return;
}
// Static files first, then SSR
staticHandler(req, res, () => appHandler(req, res));
});import express from "express";
const app = express();
// Request logging
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
// Astro handler
app.use(createMiddleware(astroApp, options));
// Error handling middleware
app.use((err, req, res, next) => {
console.error("Server error:", err);
res.status(500).send("Internal Server Error");
});All handlers include comprehensive error handling:
next(error)send library with appropriate status codes