Routing

Basil has two ways to map URLs to handlers: site mode (the filesystem is the router) and explicit routes (listed in basil.yaml). A project can use either or both.

Site Mode

Point site.path at a directory and files in it become routes:

site:
  path: ./site
site/
β”œβ”€β”€ index.pars            β†’ /
β”œβ”€β”€ about/
β”‚   └── about.pars        β†’ /about
└── blog/
    └── index.pars        β†’ /blog, /blog/anything…

How a request finds its handler

For a request to /blog/2024/hello, Basil walks back from the deepest path segment looking for a handler:

  1. site/blog/2024/hello/hello.pars, then site/blog/2024/hello/index.pars
  2. site/blog/2024/2024.pars, then site/blog/2024/index.pars
  3. site/blog/blog.pars, then site/blog/index.pars βœ“
  4. …up to site/index.pars

Two conventions, checked in order:

Subpaths

The portion of the URL the handler didn't consume is its subpath β€” so site/blog/index.pars handles /blog/2024/hello with subpath /2024/hello. One handler can render a whole section, React-router-style, by dispatching on it.

Query & form parameters

@params merges URL query parameters and POST form data (form wins on conflicts):

// /search?q=basil
@params.q          // "basil"

Explicit Routes

List routes in basil.yaml when you want control over paths, per-route auth, or caching:

routes:
  - path: /
    handler: ./handlers/index.pars
  - path: /dashboard
    handler: ./handlers/dashboard.pars
    auth: required        # See Authentication
  - path: /api/*
    handler: ./handlers/api.pars

Static Files

Two ways to serve them:

public_dir (the usual way) β€” files under it are served at the web root, and Parsley paths are rewritten to URLs automatically:

public_dir: ./public
<img src={@./public/images/logo.png}/>
// renders as <img src="/images/logo.png"/>

static routes β€” mount any directory at any prefix:

static:
  - path: /static/
    root: ./public

Asset Bundling

Basil automatically bundles every .css and .js file from your handlers directory into /__site.css and /__site.js (concatenated depth-first alphabetically, cache-busted). Include them with the built-in tags:

<head>
    <Css/>
    <Script/>
</head>

See Also