Unified Routes

One route can handle every Markdown file in a directory. The key is consistency: every file needs the same frontmatter fields so the template always has what it needs.

Consistent frontmatter

Each template uses {{title}} and {{description}}. If any page's frontmatter is missing those fields, the template will render them as empty. Make every file follow the same structure:

---
title: Page Title
description: "A short description of this page."
href: page-slug
---

The href value becomes the URL: /tutorial/page-slug.

Create the pages

Create a views/markdown/ directory and add these five files to practice with.

installation.md

---
title: Installation
description: How to install LiteNode
href: installation
---

Install LiteNode with npm:

```bash
npm install litenode
```

basic-usage.md

---
title: Basic Usage
description: Creating a basic server with LiteNode
href: basic-usage
---

```js
import { LiteNode } from "litenode"

const app = new LiteNode()
app.get("/", (req, res) => res.end("Hello!"))
app.startServer()
```

middleware.md

---
title: Middleware
description: Using middleware in LiteNode
href: middleware
---

```js
app.use((req, res) => {
    console.log(`${req.method} ${req.url}`)
})
```

error-handling.md

---
title: Error Handling
description: Handling errors in LiteNode
href: error-handling
---

```js
app.onError(async (err, req, res) => {
    res.status(500).txt("Internal Server Error")
})
```

add-ids-to-headings.md

---
title: Add IDs to Headings
description: Adding custom IDs to headings using the {#id} syntax
href: add-ids-to-headings
---

Use `{#id}` after a heading to give it a custom ID:

# Introduction {#intro}

## Getting Started {#getting-started}

The unified route

One route handles all of them:

app.get("/tutorial/:href", async (req, res) => {
    const pages = await app.parseMarkdownFileS("markdown")

    const current = pages.find((file) => file.frontmatter.href === req.params.href)

    if (!current) {
        return res.status(404).txt("Not found")
    }

    const { title, description } = current.frontmatter
    const html_content = marked.parse(current.content)

    res.render("layouts/index.html", { title, description, html_content })
})

Restart the server and visit any of these URLs:

Each one renders the correct page through the same route handler. When you add a new Markdown file to the directory, it becomes available automatically — no new route needed.

Restarting the server

After changing index.js, you need to restart the server for the changes to take effect. Stop the running server with Ctrl+C, then start it again:

npm start

For development, it is recommended to run the application using the development mode:

npm run dev

which uses Node.js' built-in watch mode:

node --watch index.js

This automatically monitors server-side JavaScript files and restarts the server whenever changes are detected.

Note: The built-in --watch flag is available from Node.js 18.11.0, but it became stable in Node.js 20.13.0. If you are using a Node.js version older than 20.13.0, or if your application is not started with npm run dev, use a file watcher such as Nodemon instead.

Install Nodemon as a development dependency:

npm i -D nodemon

Then run the server with:

npx nodemon index

Nodemon watches for file changes and restarts the server automatically.

Changing a Markdown file does not require a server restart — only server-side JavaScript changes (such as changes to index.js) require restarting the server.