Skip to content

Getting Started

To get started, follow these steps:

  1. Install the package with your favorite package manager:

    sh
    pnpm add rose
    pnpm add rose
  2. Optionally, you can install the HTML package for JSX-like HTML support:

    sh
    pnpm add rose/html
    pnpm add rose/html
  3. Now, run the init command to scaffold a project:

    sh
    pnpm exec rose init
    pnpm exec rose init

Defining Routes

To define a route, simply create a new file. The path to the file will be the path of the route. For example, the following paths would map to the following routes:

  • /index.ts -> /
  • /foo/bar.ts -> /foo/bar

Routes can be defined on a per-method basis or for all methods using ALL.

Example code:

ts
// path: ./src/index.ts
import type { RouteHandler } from "rose";

// GET /
export const GET: RouteHandler = () => {
  return new Response("Hello world!", { status: 200 });
};
// path: ./src/index.ts
import type { RouteHandler } from "rose";

// GET /
export const GET: RouteHandler = () => {
  return new Response("Hello world!", { status: 200 });
};

Route Params and Patterns

Route params can be defined using two syntaxes. The syntax provided by rose is as follows:

  • simple params: [param]
  • optional params: [[param]]
  • wildcard: [...]
  • greedy params: [...param]
  • file extensions: [param].ext, name.[[ext]], etc.

For more information, refer to the Route Patterns documentation.

If you prefer to use itty-router's syntax to define route params, greedy params, wildcards, etc., check out the itty-router docs.

Middleware

By default, rose adds a global Not Found response for any unmatched routes. You can override this on a per-route basis by exporting an object. Middleware and Not Found responses can be defined on a per-method basis or for all methods using ALL.

Example code:

ts
// path: ./src/index.ts
import type { Middleware, NotFound, RouteHandler } from "rose";

// GET /
export const GET: RouteHandler = (req) => {
  const middlewareCtx = req.ctx["from-middleware"];
  return new Response(`Middleware Context: '${middlewareCtx}'`);
};

export const middleware: Middleware = {
  // GET /
  GET: (req) => {
    req.ctx["from-middleware"] = "Context from middleware";
  },
};

export const notFound: NotFound = {
  // POST /, PUT /, DELETE /, etc.
  ALL: () => {
    return new Response(
      "No route handler was defined for this request method",
      { status: 404 },
    );
  },
};
// path: ./src/index.ts
import type { Middleware, NotFound, RouteHandler } from "rose";

// GET /
export const GET: RouteHandler = (req) => {
  const middlewareCtx = req.ctx["from-middleware"];
  return new Response(`Middleware Context: '${middlewareCtx}'`);
};

export const middleware: Middleware = {
  // GET /
  GET: (req) => {
    req.ctx["from-middleware"] = "Context from middleware";
  },
};

export const notFound: NotFound = {
  // POST /, PUT /, DELETE /, etc.
  ALL: () => {
    return new Response(
      "No route handler was defined for this request method",
      { status: 404 },
    );
  },
};

For more information on middleware and Not Found responses, please check out our documentation for middleware and Not Found.