Skip to content

Express

Express is the most common integration. Use setupExpress() for one-line setup.

Setup

const express = require('express');

const miki = require('miki-template');



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views' });



app.get('/', (req, res) => res.render('home', { user: req.user }));

app.get('/partials/:name', (req, res) =>

  res.render(`home#${req.params.name}`, { user: req.user })

);



app.listen(3000);
import express from 'express';

import miki from 'miki-template';



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views' });



app.get('/', (req, res) => res.render('home', { user: req.user }));

app.get('/partials/:name', (req, res) =>

  res.render(`home#${req.params.name}`, { user: req.user })

);



app.listen(3000);

Options

| Option | Default | Description |

|--------|---------|-------------|

| extension | 'html' | File extension for views. Use 'miki' if you prefer .miki files. |

| views | app.get('views') | Views directory (passed to app.set('views', ...)). |

| async | false | Use the async engine (__expressAsync). For Express 5+ with async helpers. |

The res.render shim intercepts only view names containing a #. Everything else (full pages, res.render(view, cb), callback forms) goes through Express's normal view lookup, so the integration is fully compatible with existing Express middleware.

Manual Setup

If you prefer full control:

const express = require('express');

const { __express } = require('miki-template');



const app = express();

app.engine('html', __express);

app.set('view engine', 'html');

app.set('views', './views');
import express from 'express';

import { __express } from 'miki-template';



const app = express();

app.engine('html', __express);

app.set('view engine', 'html');

app.set('views', './views');

Async Express 5+

Express 5+ supports async route handlers natively. Pass async: true to setupExpress, or use __expressAsync directly:

const express = require('express');

const miki = require('miki-template');



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views', async: true });



app.get('/user/:id', async (req, res) => {

  const user = await User.findById(req.params.id);

  if (!user) return res.status(404).send('Not found');

  res.render('user-profile', { user });

});
import express from 'express';

import miki from 'miki-template';



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views', async: true });



app.get('/user/:id', async (req, res) => {

  const user = await User.findById(req.params.id);

  if (!user) return res.status(404).send('Not found');

  res.render('user-profile', { user });

});

Partial Renderer Middleware

Add partial rendering without changing engine registration:

const express = require('express');

const miki = require('miki-template');



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views' });

app.use(miki.expressPartialRenderer());



app.get('/card', (req, res) => res.renderPartial('home#card', { user: req.user }));
import express from 'express';

import miki from 'miki-template';



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views' });

// Note: must call expressPartialRenderer() before routes

app.use(miki.expressPartialRenderer());



app.get('/card', (req, res) => res.renderPartial('home#card', { user: req.user }));

Express Adapter (app.engine)

If you prefer not to use setupExpress(), you can use express() directly as a view engine:

const express = require('express');

const { express: mikiExpress } = require('miki-template');



const app = express();

app.engine('html', mikiExpress({ async: true }));

app.set('view engine', 'html');

app.set('views', './views');
import express from 'express';

import { express as mikiExpress } from 'miki-template';



const app = express();

app.engine('html', mikiExpress({ async: true }));

app.set('view engine', 'html');

app.set('views', './views');

HTMX Example

miki-template's partial rendering (#partialName) is purpose-built for HTMX and similar frameworks:

const express = require('express');

const miki = require('miki-template');



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views' });



// Full page — initial load

app.get('/', (req, res) => res.render('home', { user: req.user }));



// HTMX partial — only re-renders the "card" component

app.get('/partials/:name', (req, res) =>

  res.render(`home#${req.params.name}`, { user: req.user })

);



app.listen(3000);
import express from 'express';

import miki from 'miki-template';



const app = express();

miki.setupExpress(app, { extension: 'html', views: './views' });



app.get('/', (req, res) => res.render('home', { user: req.user }));



app.get('/partials/:name', (req, res) =>

  res.render(`home#${req.params.name}`, { user: req.user })

);



app.listen(3000);

Next Steps