Sliced Backend

At this point index.js contains everything: the LiteNode instance, the marked config, and both routes. That's fine for a small demo. It becomes a problem when you have ten routes and several shared utilities.

The fix is straightforward: move each responsibility into its own file and import it where needed.

Extract the Marked setup

Move the marked configuration into functions/markedParseAndHighlight.js (you may have already done this in the previous section). Export the configured instance:

// functions/markedParseAndHighlight.js
export const markedParseAndHighlight = new Marked(/* ... */)

Create an initialize module

Create functions/initialize.js to hold the shared app and marked instances:

import { LiteNode } from "litenode"
import { markedParseAndHighlight } from "./markedParseAndHighlight.js"

const app = new LiteNode()
const marked = markedParseAndHighlight

export { app, marked }

Every route file will import from here instead of creating its own instance.

Extract routes

Create a routes/ directory and add one file per route.

routes/entryRoute.js

import { app, marked } from "../functions/initialize.js"

export const entryRoute = () => {
    app.get("/", (req, res) => {
        const parsed = app.parseMarkdownFile("index.md")
        const html_content = marked.parse(parsed.content)
        const { title, description } = parsed.frontmatter

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

routes/tutorialRoute.js

import { app, marked } from "../functions/initialize.js"

export const tutorialRoute = () => {
    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.redirect("/404", 302)

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

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

Slim down index.js

index.js becomes a thin entry point that wires things together:

import { app } from "./functions/initialize.js"
import { entryRoute } from "./routes/entryRoute.js"
import { tutorialRoute } from "./routes/tutorialRoute.js"

app.notFound((req, res) => {
    res.status(404).render("layouts/index.html", {
        title: "Page Not Found",
        description: "The server cannot find the requested resource.",
        notFoundRoute: true,
    })
})

entryRoute()
tutorialRoute()

app.startServer()

The resulting structure

litenode-markdown-app/
├── index.js
├── functions/
│   ├── initialize.js
│   └── markedParseAndHighlight.js
├── routes/
│   ├── entryRoute.js
│   └── tutorialRoute.js
└── views/
    ├── index.md
    ├── layouts/
    │   └── index.html
    ├── components/
    └── markdown/

Restart the server and verify everything still works. The behavior hasn't changed — only the organization has.

When you need a new route, add one file to routes/. When you need a new utility, add one file to functions/. index.js stays short and readable no matter how large the app grows.