
Security News
npm Adopts OIDC for Trusted Publishing in CI/CD Workflows
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
astro-routify
Advanced tools
A high-performance API router for Astro using a Trie-based matcher.
A high-performance API router for Astro built on a Trie matcher.
Define API routes using clean, flat structures — no folders or boilerplate logic.
npm install astro-routify
// src/pages/api/index.ts
import {
defineRoute,
defineRouter,
defineGroup,
HttpMethod,
ok,
} from 'astro-routify';
const userGroup = defineGroup('/users', (group) => {
group.addGet('/:id', ({params}) => ok({id: params.id}));
});
export const GET = defineRouter([
defineRoute(HttpMethod.GET, '/ping', () => ok('pong')),
...userGroup.getRoutes(),
]);
Or to handle everything in a single place:
import {RouterBuilder, ok} from 'astro-routify';
const builder = new RouterBuilder();
builder
.addGet('/ping', () => ok('pong'))
.addPost('/submit', async ({request}) => {
const body = await request.json();
return ok({received: body});
});
export const ALL = builder.build(); // catch-all
You can find an implementation example in the astro-routify-example repository. It showcases a minimal Astro app with API endpoints configured under:
/src/pages/api/[...path].ts
This setup demonstrates how to route requests dynamically using astro-routify, while still leveraging Astro's native endpoint system.
:id
)RouterBuilder
)ok
, created
, etc.)stream()
— raw streaming with backpressure support (e.g. SSE, logs, custom protocols)streamJsonND()
— newline-delimited JSON streaming (NDJSON)streamJsonArray()
— server-side streamed JSON arrays🔄 See CHANGELOG.md for recent updates and improvements.
defineRoute()
Declare a single route:
defineRoute(HttpMethod.GET, "/users/:id", ({params}) => {
return ok({userId: params.id});
});
defineRouter()
Group multiple routes under one HTTP method handler:
export const GET = defineRouter([
defineRoute(HttpMethod.GET, "/health", () => ok("ok"))
]);
🧠
defineRouter()
supports all HTTP methods — but Astro only executes the method you export (GET
,POST
, etc.)
RouterBuilder
(Catch-All & Fluent Builder)Use RouterBuilder
when you want to build routes dynamically, catch all HTTP methods via ALL
, or organize routes more
fluently with helpers.
const builder = new RouterBuilder();
builder
.addGet("/ping", () => ok("pong"))
.addPost("/submit", async ({request}) => {
const body = await request.json();
return ok({received: body});
});
export const ALL = builder.build();
You can also group routes:
const users = defineGroup("/users")
.addGet("/:id", ({params}) => ok({id: params.id}));
builder.addGroup(users);
🔁 While
.register()
is still available, it's deprecated in favor of.addGroup()
and.addRoute()
for better structure and reusability.
Avoid boilerplate new Response(JSON.stringify(...))
:
import {fileResponse} from 'astro-routify';
ok(data); // 200 OK
created(data); // 201 Created
noContent(); // 204
notFound("Missing"); // 404
internalError(err); // 500
fileResponse(content, "application/pdf", "report.pdf"); // sets Content-Type and Content-Disposition
stream('/clock', async ({response}) => {
const timer = setInterval(() => {
response.write(new Date().toISOString());
}, 1000);
setTimeout(() => {
clearInterval(timer);
response.close();
}, 5000);
});
streamJsonND('/updates', async ({response}) => {
response.send({step: 1});
await delay(500);
response.send({step: 2});
response.close();
});
streamJsonArray('/items', async ({response}) => {
for (let i = 0; i < 3; i++) {
response.send({id: i});
}
response.close();
});
Any route param like :id
is extracted into ctx.params
:
const builder = new RouterBuilder();
builder.addGet("/users/:id", ({params}) => ok({userId: params.id}));
//OR
defineRoute(HttpMethod.GET, "/items/:id", ({params}) => {
return ok({itemId: params.id});
});
// src/pages/api/[...slug].ts
export const GET = async ({request}) => {
const url = new URL(request.url);
const path = url.pathname;
if (path.startsWith('/api/users/')) {
// Try to extract ID
const id = path.split('/').pop();
return new Response(JSON.stringify({id}), {
status: 200,
headers: {'Content-Type': 'application/json'},
});
}
if (path === '/api/users') {
return new Response(JSON.stringify([{id: 1}, {id: 2}]), {
status: 200,
headers: {'Content-Type': 'application/json'},
});
}
if (path === '/api/ping') {
return new Response(JSON.stringify({pong: true}), {
status: 200,
headers: {'Content-Type': 'application/json'}
});
}
return new Response('Not Found', {status: 404});
};
src/
├─ pages/
│ ├─ api/
│ │ ├─ users/
│ │ │ ├─ index.ts // GET all users
│ │ │ ├─ [id]/
│ │ │ │ ├─ index.ts // GET / POST / DELETE for a user
│ │ ├─ ping.ts
astro-routify
// src/pages/api/[...slug].ts
const builder = new RouterBuilder();
builder.addGet("/ping", () => ok({pong: true}));
builder.addGet("/users/:id", ({params}) => ok({userId: params.id}));
// OR
export const ALL = defineRouter([
defineRoute(HttpMethod.GET, "/ping", () => ok({pong: true})),
defineRoute(HttpMethod.GET, "/users/:id", ({params}) => ok({id: params.id}))
]);
astro-routify
uses a Trie structure for fast route and method matching.
It’s optimized for real-world route hierarchies, and avoids nested if
chains.
Realistic and synthetic benchmarks using vitest bench
.
Tests ran on a mid-range development setup:
Results may vary slightly on different hardware.
✓ RouteTrie performance - realistic route shapes
· Static route lookup (5000) 1,819,681 req/sec
· Param route: /users/:userId 1,708,264 req/sec
· Nested param route: /users/:id/orders/:oid 1,326,324 req/sec
· Blog route: /blog/:year/:month/:slug 1,220,882 req/sec
· Nonexistent path 1,621,934 req/sec
✓ RouteTrie performance
· Lookup in SMALL (100 routes) 1,948,385 req/sec
· Lookup in MEDIUM (1000 routes) 1,877,248 req/sec
· Lookup in LARGE (10000 routes) 1,908,279 req/sec
· Lookup non-existent route in LARGE 1,962,051 req/sec
⚡ Performance stays consistently fast even with 10k+ routes
While focused on simplicity and speed today, astro-routify
is designed to evolve — enabling more advanced routing
patterns in the future.
MIT — © 2025 Alex Mora
If this project helps you, consider buying me a coffee. Every drop keeps the code flowing!
FAQs
A high-performance API router for Astro using a Trie-based matcher.
We found that astro-routify demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Security News
The CNA Scorecard ranks CVE issuers by data completeness, revealing major gaps in patch info and software identifiers across thousands of vulnerabilities.