Documentation Index Fetch the complete documentation index at: https://mintlify.com/meteor/meteor/llms.txt
Use this file to discover all available pages before exploring further.
Blaze is Meteor’s built-in reactive templating engine. It provides a simple, intuitive way to create dynamic user interfaces with automatic reactivity and live updates.
Installation
Blaze is included by default when you create a new Meteor app. To add it to an existing project:
meteor add blaze-html-templates
For reactive variables:
Quick Start
Create a Blaze app:
meteor create my-app --blaze
Basic Structure
Blaze uses HTML templates with special syntax for dynamic content:
< head >
< title > My Meteor App </ title >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
</ head >
< body >
< h1 > Welcome to Meteor! </ h1 >
{{> hello}}
{{> info}}
</ body >
< template name = "hello" >
< button > Click Me </ button >
< p > You've pressed the button {{counter}} times. </ p >
</ template >
< template name = "info" >
< h2 > Learn Meteor! </ h2 >
< ul >
< li >< a href = "https://www.meteor.com/try" target = "_blank" > Do the Tutorial </ a ></ li >
< li >< a href = "http://guide.meteor.com" target = "_blank" > Follow the Guide </ a ></ li >
</ ul >
</ template >
Template Helpers and Events
Add behavior to templates with JavaScript:
import { Template } from 'meteor/templating' ;
import { ReactiveVar } from 'meteor/reactive-var' ;
import './main.html' ;
Template . hello . onCreated ( function helloOnCreated () {
// counter starts at 0
this . counter = new ReactiveVar ( 0 );
});
Template . hello . helpers ({
counter () {
return Template . instance (). counter . get ();
},
});
Template . hello . events ({
'click button' ( event , instance ) {
// increment the counter when button is clicked
instance . counter . set ( instance . counter . get () + 1 );
},
});
Component-Based Structure
Organize Blaze templates as reusable components:
/imports
/ui
/components
/hello
hello.html
hello.js
/info
info.html
info.js
/layouts
/body
body.html
body.js
Component Example
< template name = "hello" >
< h1 > Welcome to Meteor! </ h1 >
< button > Click Me </ button >
< p > You've pressed the button {{counter}} times. </ p >
</ template >
import { Template } from 'meteor/templating' ;
import { ReactiveVar } from 'meteor/reactive-var' ;
import './hello.html' ;
Template . hello . onCreated ( function helloOnCreated () {
this . counter = new ReactiveVar ( 0 );
});
Template . hello . helpers ({
counter () {
return Template . instance (). counter . get ();
},
});
Template . hello . events ({
'click button' ( event , instance ) {
instance . counter . set ( instance . counter . get () + 1 );
},
});
Working with Collections
Blaze automatically reacts to data changes:
< template name = "info" >
< h2 > Learn Meteor! </ h2 >
< ul >
< li >
< form class = "info-link-add" >
< input type = "text" name = "title" placeholder = "Title" required >
< input type = "url" name = "url" placeholder = "Url" required >
< input type = "submit" value = "Add new link" >
</ form >
</ li >
{{#each links}}
< li >< a href = "{{url}}" target = "_blank" > {{title}} </ a ></ li >
{{/each}}
</ ul >
</ template >
import { Links } from '/imports/api/links/links.js' ;
import { Meteor } from 'meteor/meteor' ;
import { Template } from 'meteor/templating' ;
import './info.html' ;
Template . info . onCreated ( function () {
Meteor . subscribe ( 'links.all' );
});
Template . info . helpers ({
links () {
return Links . find ({});
},
});
Template . info . events ({
'submit .info-link-add' ( event ) {
event . preventDefault ();
const target = event . target ;
const title = target . title . value ;
const url = target . url . value ;
Meteor . callAsync ( 'links.insert' , title , url )
. then (() => {
target . title . value = '' ;
target . url . value = '' ;
})
. catch (( error ) => {
alert ( error . error || error . message );
});
},
});
Template Lifecycle
Blaze provides lifecycle callbacks for template instances:
Template . myTemplate . onCreated ( function () {
// Called when template instance is created
this . counter = new ReactiveVar ( 0 );
this . autorun (() => {
// Reactive computation
});
});
Template . myTemplate . onRendered ( function () {
// Called when template is rendered to DOM
this . $ ( 'input' ). focus ();
});
Template . myTemplate . onDestroyed ( function () {
// Called when template is removed
// Cleanup happens automatically for subscriptions and autorun
});
Template Syntax
Data Context
<!-- Current data context -->
< p > {{title}} </ p >
<!-- Nested property -->
< p > {{user.name}} </ p >
<!-- Helper function -->
< p > {{formatDate createdAt}} </ p >
Control Flow
<!-- Conditional rendering -->
{{#if isLoggedIn}}
< p > Welcome, {{username}}! </ p >
{{else}}
< p > Please log in. </ p >
{{/if}}
<!-- Iteration -->
{{#each tasks}}
< li > {{title}} </ li >
{{else}}
< li > No tasks found. </ li >
{{/each}}
<!-- With block -->
{{#with currentUser}}
< p > {{username}} </ p >
< p > {{email}} </ p >
{{/with}}
Template Inclusion
<!-- Include template -->
{{> taskItem}}
<!-- Pass data context -->
{{> taskItem task=currentTask}}
<!-- Pass multiple arguments -->
{{> userProfile user=currentUser editable=true}}
Reactivity
Reactive Variables
import { ReactiveVar } from 'meteor/reactive-var' ;
Template . example . onCreated ( function () {
this . searchQuery = new ReactiveVar ( '' );
});
Template . example . helpers ({
results () {
const query = Template . instance (). searchQuery . get ();
return Items . find ({ name: new RegExp ( query , 'i' ) });
},
});
Template . example . events ({
'input .search' ( event , instance ) {
instance . searchQuery . set ( event . target . value );
},
});
Reactive Dictionaries
import { ReactiveDict } from 'meteor/reactive-dict' ;
Template . example . onCreated ( function () {
this . state = new ReactiveDict ();
this . state . set ( 'loading' , false );
this . state . set ( 'filter' , 'all' );
});
Template . example . helpers ({
isLoading () {
return Template . instance (). state . get ( 'loading' );
},
currentFilter () {
return Template . instance (). state . get ( 'filter' );
},
});
Subscriptions
Template . taskList . onCreated ( function () {
// Subscribe to data
this . subscribe ( 'tasks' );
// Subscribe with parameters
this . autorun (() => {
const listId = FlowRouter . getParam ( 'listId' );
this . subscribe ( 'tasks' , listId );
});
});
Template . taskList . helpers ({
tasks () {
return Tasks . find ({});
},
isLoading () {
return ! Template . instance (). subscriptionsReady ();
},
});
Integration with React
React in Blaze
Blaze in React
Use React components inside Blaze templates: meteor add react-template-helper
< template name = "userDisplay" >
< div > Hello, {{username}} </ div >
< div > {{> React component=UserAvatar userId=_id}} </ div >
</ template >
import UserAvatar from './UserAvatar.jsx' ;
Template . userDisplay . helpers ({
UserAvatar () {
return UserAvatar ;
}
});
Use Blaze templates in React components: meteor add gadicc:blaze-react-component
import React from 'react' ;
import Blaze from 'meteor/gadicc:blaze-react-component' ;
const App = () => (
< div >
< Blaze template = "itemsList" items = { items } />
</ div >
);
Best Practices
Store state on template instances, not global variables: Template . example . onCreated ( function () {
this . counter = new ReactiveVar ( 0 ); // Good
});
// Not: let counter = 0; (Bad - shared across instances)
Use this.subscribe() in onCreated for automatic cleanup: Template . example . onCreated ( function () {
this . subscribe ( 'data' ); // Automatically cleaned up
});
Use autorun for reactive dependencies
Wrap reactive computations in autorun: Template . example . onCreated ( function () {
this . autorun (() => {
const id = Session . get ( 'currentId' );
this . subscribe ( 'item' , id );
});
});
Use .limit() and .fields() to reduce data transfer: Template . example . helpers ({
recentTasks () {
return Tasks . find ({}, {
limit: 10 ,
fields: { title: 1 , createdAt: 1 },
sort: { createdAt: - 1 }
});
},
});
Common Patterns
Loading States
Template . example . onCreated ( function () {
this . subscribe ( 'data' );
});
Template . example . helpers ({
isLoading () {
return ! Template . instance (). subscriptionsReady ();
},
});
{{#if isLoading}}
< div class = "loading" > Loading... </ div >
{{else}}
{{#each items}}
< div > {{name}} </ div >
{{/each}}
{{/if}}
< template name = "taskForm" >
< form class = "new-task" >
< input type = "text" name = "title" placeholder = "New task" required >
< button type = "submit" > Add Task </ button >
</ form >
</ template >
Template . taskForm . events ({
'submit .new-task' ( event ) {
event . preventDefault ();
const title = event . target . title . value ;
Meteor . callAsync ( 'tasks.insert' , title )
. then (() => {
event . target . title . value = '' ;
})
. catch (( error ) => {
alert ( error . message );
});
},
});
Resources
Blaze Guide Comprehensive guide to Blaze templating
Blaze API Complete API reference for Blaze
Blaze Tutorial Step-by-step tutorial for building Blaze apps
Reactive Var Documentation for ReactiveVar