Reactive page title
April 21, 2026 ยท View on GitHub
Reactive page title
Change document.title on the fly in Meteor.js apps via flow-router-extra API.
ToC
Features
- ๐จโ๐ฌ 100% tests coverage
- โจ Use prefixes for groups, including nesting
- ๐ Per route, per group, and default (all routes)
titletag
Various ways to set title, ordered by priority:
FlowRouter.route()[overrides all below]FlowRouter.group()FlowRouter.globals- Head template
<title>Text</title>tag [superseded by any above]
Installation
meteor add ostrio:flow-router-title
Compatibility
- Meteor
>=1.4, including latest Meteor3.4; - Requires
ostrio:flow-router-extra@3.14.0+.
Demos
ES6 Import
import { FlowRouterTitle } from 'meteor/ostrio:flow-router-title';
AGENTS.md
The repo ships AGENTS.md: a compact implementation map for ostrio:flow-router-title. It complements API in this document.
SKILLS.md
- The main
ostrio:flow-router-extrapackage ships a bundled skill at.agents/skills/meteor-flow-router/SKILL.md(coversostrio:flow-router-extra,ostrio:flow-router-meta,ostrio:flow-router-title). Install into your project with the Skills CLI (npx skills):
# From a Meteor app repo (install into that appโs .agents/skills for Cursor, etc.)
npx skills add veliovgroup/flow-router --skill meteor-flow-router
# Only list skills discovered in the Flow Router repo (no install)
npx skills add veliovgroup/flow-router --list
# User-global Cursor skills dir (~/.cursor/skills)
npx skills add veliovgroup/flow-router --skill meteor-flow-router --agent cursor --global --yes
TypeScript
- Package ships
index.d.tsas a Meteor asset. Apps usingzodern:typesresolve typings formeteor/ostrio:flow-router-titleautomatically. - Import only from client code (same as this packageโs
mainModule). - Constructor expects
FlowRouterfrommeteor/ostrio:flow-router-extra(Routertype). Route / group options usetitle,titlePrefixas in the API section.
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
import { FlowRouterTitle } from 'meteor/ostrio:flow-router-title';
const titles = new FlowRouterTitle(FlowRouter);
titles.set('My title');
Related Packages
flow-router-title performs the best when used with the next packages:
- flow-router-meta - Per route
metatags,script, andlink(e.g. CSS) โ set per-route meta-tags, stylesheets, and scripts - flow-router-extra - Carefully extended FlowRouter
API
new FlowRouterTitle(FlowRouter)โ The mainFlowRouterTitleconstructor that acceptsFlowRouteras the only argumentFlowRouterTitle#set(title: string)โ The only method that changesdocument.titleduring runtime
After new FlowRouterTitle(FlowRouter) instance is initiated it extends FlowRouter.router() and FlowRouter.group() methods and FlowRouter.globals with support of:
title: stringโ String propertytitle: function(params, qs, data) => stringโ Method returning stringtitlePrefix: stringโ String property for page's title prefixtitlePrefix: function(params, qs, data) => stringโ Method returning string for page's title prefix
Usage
Initialize FlowRouterTitle class by passing FlowRouter object. Right after creating all routes:
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
import { FlowRouterTitle } from 'meteor/ostrio:flow-router-title';
FlowRouter.route('/', {
action() { /* ... */ },
title: 'Title'
/* ... */
});
const titleHandler = new FlowRouterTitle(FlowRouter);
404 / notFound compatibility
ostrio:flow-router-title supports both 404 styles in ostrio:flow-router-extra:
- Recommended: catch-all route via
FlowRouter.route('*', { title, action }) - Legacy/deprecated API:
FlowRouter.notFound = { title, action }
When both are present, latest registration wins, same as regular route registration order.
Set title via Route
Set title property in route's or group's configuration:
// Set default document.title value in
// case router has no title property
FlowRouter.globals.push({
title: 'Default title'
});
FlowRouter.route('/me/account', {
name: 'account',
title: 'My Account'
});
.set() method
Set document.title during runtime (without route(s)):
FlowRouter.route('/', {/* ... */});
const titleHandler = new FlowRouterTitle(FlowRouter);
titleHandler.set('My Awesome Title String'); // <- Returns `true`
// `.set()` method accepts {string} only
// Invalid values won't throw an exception
// instead it will simply return `false`
Function context
Use function context (with data hook):
FlowRouter.route('/post/:_id', {
name: 'post',
waitOn(params) {
return [Meteor.subscribe('post', params._id)];
},
async data(params) {
return await Collections.Posts.findOneAsync(params._id);
},
title(params, query, data) {
if (data) {
return data.title;
}
return '404: Page not found';
}
});
Group context
Use group context:
const account = FlowRouter.group({
prefix: '/account',
title: 'Account',
titlePrefix: 'Account > '
});
account.route('/', {
name: 'accountIndex' // Title will be `Account`
});
account.route('/settings', {
name: 'AccountSettings',
title: 'My Settings' // Title will be `Account > My Settings`
});
Reactive data sources
To change title reactively, just pass it as function:
FlowRouter.route('/me/account', {
name: 'account',
title() {
// In this example we used `ostrio:i18n` package
return i18n.get('account.document.title');
}
});
// Use params from route
FlowRouter.route('/page/:_id/:slug', {
name: 'somePage',
title(params) {
return `Page ${params.slug}`;
}
});
More examples
In all examples below title can be a Function or String:
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
FlowRouter.globals.push({
title() {/* ... */} // <-- Suitable for reactive data source
});
FlowRouter.globals.push({
title: 'Title text'
});
FlowRouter.group({
title() {/* ... */}, // <-- Suitable for reactive data source
titlePrefix() {/* ... */} // <-- Can accept reactive data source, but won't trigger re-computation
});
FlowRouter.group({
title: 'Title text',
titlePrefix: 'Title prefix text'
});
FlowRouter.route('/path', {
title() {/* ... */} // <-- Reactive
});
FlowRouter.route('/path', {
title: 'Title text'
});
Running Tests
- Clone this package
- In Terminal (Console) go to directory where package is cloned
- Then run:
Meteor/Tinytest
# Default
meteor test-packages ./
# With custom port
meteor test-packages ./ --port 8888
# With local MongoDB and custom port
MONGO_URL="mongodb://127.0.0.1:27017/flow-router-title-tests" meteor test-packages ./ --port 8888
Support this project
- Upload and share files using โ๏ธ meteor-files.com โ Continue interrupted file uploads without losing any progress. There is nothing that will stop Meteor from delivering your file to the desired destination
- Use โฒ ostr.io for Server Monitoring, Web Analytics, WebSec, Web-CRON and SEO Pre-rendering of a website
- Star on GitHub
- Star on Atmosphere
- Sponsor via GitHub
- Support via PayPal