C
CanxJS
v1.6.2
  • Learn
  • Blog
  • Showcase
C
CanxJS

Ultra-fast async MVC backend framework for Bun. Build production-ready APIs with elegance and speed.

Resources

  • Documentation
  • Learn
  • Blog
  • Showcase

Documentation

  • Introduction
  • Installation
  • Core Concepts
  • CLI Commands
  • API Reference

Legal

  • Privacy Policy
  • Terms of Service

© 2026 CanxJS. All rights reserved.

Built with ❤️ for Candra Kirana

  • Routing
  • Controllers
  • API Resources
  • Dependency Injection
  • Service Providers
  • Middleware
  • Request & Response
  • Authentication
  • Validation
  • Session
  • I18n
  • Utilities
Core Concepts

Routing

Define and manage application routes with CanxJS's powerful, intuitive API. Built on a Radix Tree for ultra-fast route matching with support for parameters, wildcards, and route groups.

Radix Tree Based

Ultra-fast route matching with O(k) complexity where k is the path length

Route Parameters

Capture dynamic values from URLs with :paramName syntax

Wildcard Routes

Match multiple path segments with *wildcard syntax

Route Groups

Organize routes with prefixes and shared middleware

Basic Routes

Define routes using HTTP method helpers like app.get(),app.post(),app.put(), andapp.delete(). Each method takes a path and a handler function.

app.ts
1import { createApp } from "canxjs";
2
3const app = createApp({ port: 3000 });
4
5// GET request
6app.get("/", (req, res) => {
7 return res.json({ message: "Hello CanxJS!" });
8});
9
10// POST request
11app.post("/users", async (req, res) => {
12 const userData = await req.body();
13 return res.status(201).json({ created: userData });
14});
15
16// PUT request
17app.put("/users/:id", async (req, res) => {
18 const { id } = req.params;
19 const userData = await req.body();
20 return res.json({ updated: { id, ...userData } });
21});
22
23// DELETE request
24app.delete("/users/:id", (req, res) => {
25 const { id } = req.params;
26 return res.json({ deleted: id });
27});
28
29app.listen();

Dynamic Parameters

Capture dynamic values from URLs using colon syntax (:paramName). Parameters are available in req.params, while query strings are in req.query.

routes.ts
1// Single parameter
2app.get("/users/:id", (req, res) => {
3 const { id } = req.params;
4 return res.json({ userId: id });
5});
6
7// Multiple parameters
8app.get("/posts/:postId/comments/:commentId", (req, res) => {
9 const { postId, commentId } = req.params;
10 return res.json({ postId, commentId });
11});
12
13// Optional query parameters
14app.get("/search", (req, res) => {
15 const { q, page, limit } = req.query;
16 return res.json({
17 query: q,
18 page: page || 1,
19 limit: limit || 10
20 });
21});

Wildcard Matching

Use wildcards (*) to match any path segment. You can also name wildcards to capture the matched path. Useapp.all() to match all HTTP methods.

wildcards.ts
1// Wildcard route - catches all paths after /files/
2app.get("/files/*path", (req, res) => {
3 const filePath = req.params.path;
4 return res.json({
5 message: "File requested",
6 path: filePath
7 });
8});
9
10// Catch-all 404 handler
11app.all("*", (req, res) => {
12 return res.status(404).json({
13 error: "Not Found",
14 path: req.path
15 });
16});

Grouping Routes

Organize routes with common prefixes using app.group(). Groups can be nested to create hierarchical route structures.

groups.ts
1// Group routes with a common prefix
2app.group("/api/v1", (router) => {
3 router.get("/users", getUsers);
4 router.get("/users/:id", getUser);
5 router.post("/users", createUser);
6 router.put("/users/:id", updateUser);
7 router.delete("/users/:id", deleteUser);
8});
9
10// Nested groups
11app.group("/admin", (admin) => {
12 admin.group("/users", (users) => {
13 users.get("/", listAdminUsers);
14 users.post("/", createAdminUser);
15 });
16
17 admin.group("/settings", (settings) => {
18 settings.get("/", getSettings);
19 settings.put("/", updateSettings);
20 });
21});

Named Routes & Reverse Routing

Give your routes a name for easier referencing. Use the name() method chain and the global route() helper to generate URLs.

named-routes.ts
1// Define named route
2app.get("/users/:id", (req, res) => {
3 // ...
4}).name("users.show");
5
6// In your controller or view:
7const url = route("users.show", { id: 123 });
8// Output: /users/123
9
10// Redirect using named route
11return res.redirect(route("users.show", { id: 1 }));

Route Middleware

Apply middleware to specific routes or route groups. Middleware is executed in order before the route handler.

middleware.ts
1import { createApp, cors, logger } from "canxjs";
2
3const app = createApp({ port: 3000 });
4
5// Auth middleware
6const authMiddleware = async (req, res, next) => {
7 const token = req.header("authorization");
8
9 if (!token) {
10 return res.status(401).json({ error: "Unauthorized" });
11 }
12
13 req.context.set("user", { id: 1, name: "John" });
14 return next();
15};
16
17// Apply middleware to specific route
18app.get("/profile", authMiddleware, (req, res) => {
19 const user = req.context.get("user");
20 return res.json({ profile: user });
21});
22
23// Apply middleware to route group
24app.group("/api", (router) => {
25 router.middleware(authMiddleware);
26 router.get("/dashboard", getDashboard);
27 router.get("/settings", getSettings);
28});

Controller-based Routing
v1.6.3

New in v1.6.3: Use router.controller() to register entire controller classes with their decorated routes. This provides cleaner, more organized routing similar to Laravel.

routes.ts
1import { createApp, QueueController } from "canxjs";
2import { HomeController } from "./controllers/HomeController";
3import { AuthController } from "./controllers/AuthController";
4
5// New in v1.6.3: Controller-based routing
6app.routes((router) => {
7 // Mount controllers with router.controller()
8 router.controller('/', HomeController);
9 router.controller('/auth', AuthController);
10
11 // Built-in Queue Dashboard
12 router.controller('/canx-queue', QueueController);
13});

Router Options

OptionTypeDefaultDescription
caseSensitivebooleanfalseTreat /Users and /users as different routes
trailingSlash'ignore' | 'require' | 'remove''ignore'How to handle trailing slashes
cachebooleantrueEnable route matching cache
router-options.ts
1import { createRouter, createApp } from "canxjs";
2
3// Create router with options
4const router = createRouter({
5 caseSensitive: true, // /Users ≠ /users
6 trailingSlash: "remove", // /users/ → /users
7 cache: true // Enable route caching
8});
9
10// Use the router
11router.get("/users", getUsers);
12router.post("/users", createUser);
13
14// Mount router
15const app = createApp({ port: 3000 });
16// Routes from router are registered with app

Next Steps

Now that you understand routing, learn how to organize your handlers with controllers.