Skip to main content
Deno 2 is finally here πŸŽ‰οΈ
Learn more

fsrouter | deno doc format lint test release

A file system based router for Deno.

Usage

Given a project with the following folder structure:

my-app/
β”œβ”€ pages/
β”‚  β”œβ”€ blog/
β”‚  β”‚  β”œβ”€ post.ts
β”‚  β”‚  β”œβ”€ index.ts
β”‚  β”œβ”€ about.ts
β”‚  β”œβ”€ index.ts
β”œβ”€ mod.ts

Each β€œroute file” must export a FsHandler as its default export:

// my-app/pages/blog/post.ts
export default (req: Request) => {
  return new Response("hello world!");
};

.js files are fine as well:

// my-app/pages/blog/post.js
export default (req) => {
  return new Response("hello world!");
};

As well as .jsx and .tsx files, with jsx runtime modules from whichever source you wish:

// my-app/pages/blog/post.tsx

/** @jsx h */
import { h, renderSSR } from "https://deno.land/x/nano_jsx@v0.0.33/mod.ts";

function App() {
  return (
    <html>
      <head>
        <title>Hello from JSX</title>
      </head>
      <body>
        <h1>Hello world</h1>
      </body>
    </html>
  );
}

export default (_req: Request) => {
  const html = renderSSR(<App />);

  return new Response(html, {
    headers: {
      "content-type": "text/html",
    },
  });
};

Initialize a server by calling fsRouter:

// my-app/mod.ts
import { fsRouter } from "https://deno.land/x/fsrouter@{VERSION}/mod.ts";
import { serve } from "https://deno.land/std@{VERSION}/http/server.ts";

// Use the file system router with base directory 'pages'
serve(await fsRouter("pages"));

Now running:

deno run --allow-read --allow-net my-app/mod.ts

Results in routes being served as follows:

File Route
pages/index.ts /
pages/about.ts /about
pages/blog/index.ts /blog
pages/blog/post.ts /blog/post

During development, you can use Deno’s built-in --watch=<folder> to restart the server on changes. Providing a bare --watch has the caveat of not being able to detect new file additions, since by default Deno will watch only files it can statically discover. By providing a root directory, Deno will be able to detect new file additions as well:

deno run --allow-read --allow-net --watch=pages my-app/mod.ts

Permissions

Since fsrouter requires access to both the network and the file system, --allow-read and --allow-net are required arguments when executing modules.

Deno Deploy

This module uses dynamic imports to resolve file names to their respective routes. As Deno Deploy does not support dynamic imports, this module is not Deno Deploy compatible. There are workarounds available that involve generating static manifests using a sort of build-step – in the future, supporting this type of workflow will be considered.