This Meteor package gives you a basic, out-of-the-box blog at /blog
(or where
ever).
This blog is very much a work in progress. To help decide what gets added next, vote with your Github issues!
We wanted a way to add a meteor-based blog within an existing project without running another app.
You can view an example application (without customization) at
http://blog-example.meteor.com .
Meteor no longer offers free hosting. There is an example app that you can run yourself.
$ meteor add ryw:blog
And then either:
$ meteor add iron:router
or
$ meteor add kadira:flow-router kadira:blaze-layout
You will by default get routes for:
/blog
/admin/blog
These paths are customizable (see below). /admin/blog
requires that Meteor.user()
return a user.
- Medium-style editor
- Slug-based URLs (editable)
- Add blog post images (store in database or upload to S3)
- Add featured, "hero" image for a post
- Support DISQUS comments
- Blog post tags and tag view
- Widget to embed recent posts on another (e.g. home) page
- Customizable layouts & templates
- Custom base paths
- SEO best practices (OpenGraph, Twitter Cards, share buttons, Google+ author attribution)
- Autosave
- Pagination
- Code syntax highlighting
- Multiple roles (admin/author)
- Have Public, Private & Draft modes
- Support for both Iron Router and Flow Router
- RSS feed
Check out the enhancements tracker
Changes between releases can be found in CHANGES.md
You do not need any configuration at all, if you are happy with the defaults. To
configure your blog, create a file shared on client/server, probably in
lib/blog.js
.
Meteor blog works with both Iron Router and Flow Router. If your app and the
blog have conflicting routes, your app will get priority. If you use Flow Router, you must add kadira:blaze-layout
to your app, as that is how Meteor blog renders its templates in a Flow Router route.
You can customize the base path for the blog and for the blog admin area.
Blog.config({
basePath: '/myBlog', // '/myBlog', '/myBlog/my-post', '/myBlog/tag/whatever', etc.
adminBasePath: '/myBlogAdmin'
});
If you set the basepath
to '/'
, blog posts will appear at the root path of
your app (e.g. http://myapp.com/my-post). This means that the blog index page
will be your home page, unless you override the route. This also means that
Meteor Blog can function as a crude CMS. For more CMS-like features, create a
Github issue!
If you need a pathFor
-like way to generate URLs, you can use blogPathFor
for either router (e.g. {{blogPathFor 'blogIndex'}}
).
By default, any logged-in user can administer the blog. To ensure that only select users can edit the blog, the package supports two roles:
adminRole
- Can create, and modify or delete any post.authorRole
- Can create, and modify or delete only my own posts.
In addition, if using groups from the alanning:roles package, set the associated group using
adminGroup
- Group associated withadminRole
.authorGroup
- Group associated withauthorRole
.
To enable either or both roles, specify values in the blog config:
Blog.config({
adminRole: 'blogAdmin',
authorRole: 'blogAuthor'
});
Then, you need to give blog users that role. Currently, you're on your own to add these roles somehow:
- Add these directly to admin users in the database (
"roles": ["blogAdmin"]
), or - Roll your own admin page using the methods provided by meteor-roles, or
- Use an accounts admin package like accounts-admin-ui-bootstrap-3.
The admin templates are designed for use with Bootstrap. To use the admin area,
you should add the meteor bootstrap-3
package.
$ meteor add mrt:bootstrap-3
The admin templates are designed for use with Bootstrap. However, the front-end is bare markup, ready to be styled, and does not depend on any CSS framework at all. If the default templates aren't doing it for you, you can override the default templates with your own by setting configuration variables:
Blog.config({
blogIndexTemplate: 'myBlogIndexTemplate', // '/blog' route
blogShowTemplate: 'myShowBlogTemplate' // '/blog/:slug' route
});
In your templates, you can use these Spacebars helpers provided by the package to display blog posts with some basic, semantic markup:
{{> blogIndex}}
- Renders list of blog posts (/blog
route){{> blogShow}}
- Renders single blog post (/blog/:slug
route)
Example:
<template name="myBlogIndexTemplate">
<h1>Welcome to my Blog</h1>
<div>{{> blogIndex}}</div>
</template>
If you don't want any of our markup, use the blog data provided in the template context directly:
blogReady
- Flag that is true when blog data is readyposts
- List ofminimongoid
blog post objects (/blog
route)post
-minimongoid
blog post object (/blog/:slug
route)
Example:
<template name="myBlogIndexTemplate">
<h1>Welcome to my Blog</h1>
<ul>
{{#if blogReady}}
{{#each posts}}
<li>
<h2>{{title}}</h2>
<p>Published on {{publishedAt}}</p>
<p>Excerpt: {{excerpt}}</p>
</li>
{{else}}
<li>No posts found.</li>
{{/each}}
{{else}}
<li>Loading...</li>
{{/if}}
</ul>
</template>
By default, the layout configured for your app is used. To specify a layout for only the blog pages:
Blog.config({
blogLayoutTemplate: 'myBlogLayout'
});
By default, if the browser loads a non-existent blog post, it will use your
app's notFound
handling. You can provide a custom notFoundTemplate
to use
when a blog post slug is not found.
Blog.config({
blogNotFoundTemplate: 'myNotFoundTemplate'
});
Meteor Blog has no built-in commenting feature.
This package supports DISQUS comments. Configure your
DISQUS short name in the client and comments will render below all your blog
posts. If you use your own blogShowTemplate
template, include {{> disqus this}}
to
display comments.
Blog.config({
comments: {
disqusShortname: 'myshortname'
}
});
This package has experimental integration with SideComments.js. Enable side comments in your blog settings. Currently, side comments uses the Meteor accounts for your Meteor site as comment users, which is probably not what you want. You can also allow anonymous comments, which lets anyone type in anything without even a name. Also, probably not what you want.
Blog.config({
comments: {
useSideComments: true, // default is false
allowAnonymous: true // default is false
}
});
Adding images to your blog posts works out of the box and saves the images to gridFS in your Mongo database.
You can optionally have these images to an Amazon S3 bucket that you configure.
To setup S3 for file storage, add the following in /settings.json
(or any
other location of your choice).
{
"public": {
"blog": {
"useS3": true
}
},
"private": {
"blog": {
"s3Config": {
"bucket": "your-bucket-name",
"s3ACL": "public-read",
"s3MaxTries": 2,
"accessKeyId": "XXXXXXXXXXXXX",
"secretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"region": "(OPTIONAL most of the time)"
}
}
}
}
When creating a blog post in the admin, you can set one of three modes:
Public
- Listed in the blog and viewable by anyonePrivate
- Not listed in the blog, but viewable by anyone with the linkDraft
- Unpublished and only viewable in the blog admin area
By default, blog summaries or excerpts are generated by taking the 1st paragraph
from the blog post. You can override this function by configuring a custom
excerptFunction
. For example, if you wanted to create an excerpt from the 1st
sentence:
Blog.config({
excerptFunction: function(body) {
return body.split('.')[0] + '.';
}
});
By default, blog posts are paged in 20 at a time. You can modify this value in
settings. Set to null
to turn off paging entirely.
Blog.config({
pageSize: 10
});
The default blogIndexTemplate
template displays a Load More
button. If you
use your own template, include the {{blogPager}}
helper to display the button.
If you fancy a coding blog, the blog package supports syntax highlighting using
highlight.js. If enabled, any content within <pre>
tags will get modified for syntax highlighting. You can specify any
highlight.js
style file.
Example config:
Blog.config({
syntaxHighlighting: true, // default is false
syntaxHighlightingTheme: 'atelier-dune.dark' // default is 'github'
});
This package depends on the liberation:shareit
package
for powering social sharing. By default, Facebook and Twitter buttons are
displayed. You can pass a configuration directly to shareit
. If you use your
own blogShowTemplate
template, include {{> shareit}}
to display share
buttons.
Blog.config({
shareit: {
siteOrder: ['twitter', 'facebook', 'pinterest'] // add Pinterest button
}
});
You can include a basic snippet of HTML displaying recent blog posts (e.g. on your home page). Insert the inclusion helper where you want the recent posts to appear.
{{> blogLatest}}
Or you can specify the # of posts to show:
{{> blogLatest num=5}}
There are classes in the template for styling, but you can use your own widget template as well.
Blog.config({
blogLatestTemplate: 'myLatestWidgetTemplate'
});
And then include {{> myLatestWidgetTemplate}}
anywhere you want. It will
receive the following data context variables:
latest
- List of most recentnum
blog postsdate
- Date format helper
An RSS feed is automatically generated at /rss/posts
. To set the title and
description in the feed, configure RSS:
Blog.config({
rss: {
title: 'My blog title',
description: 'My blog description'
}
});
Add a head tag somewhere in your .html
files so your RSS feed can be discovered:
<head>
<link rel="alternate" type="application/rss+xml" title="My blog title" href="/rss/posts">
</head>
You can change the text of the labels the blog uses in the Blog.config.
The following are the default labels used:
Blog.config({
language: {
blogEmpty: 'This blog is looking pretty empty...',
backToBlogIndex: 'Back to the Blog',
loadMore: 'Load More',
tags: 'Tags',
slug: 'Slug',
metaDescription: 'Meta Description',
body: 'Body',
showAsVisual: 'Visual',
showAsHtml: 'HTML',
save: 'Save',
cancel: 'Cancel',
"delete": 'Delete',
metaAuthorBy: 'By',
metaAuthorOn: 'on',
edit: 'Edit',
areYouSure: 'Are you sure?',
disqusPoweredBy: 'comments powered by',
adminHeader: 'Blog Admin',
addPost: 'Add Blog Post',
allPosts: 'All Posts',
myPosts: 'My Posts',
addPost: 'Add Post',
editPost: 'Edit Post',
title: 'Title',
author: 'Author',
updatedAt: 'Updated At',
publishedAt: 'Published At',
visibleTo: 'Visible To',
featuredImage: 'Featured Image',
selectFile: 'Select File',
imageAsBackground: 'Use as background for title',
enterTag: 'Type in a tag & hit enter',
postCreateFirst: 'Create the first blog',
postVisibilityAdmins: 'Me & Admins only',
postVisibilityLink: 'Anyone with link',
postVisibilityAnyone: 'The world',
saved: 'Saved',
editFeaturedImageSaved: 'Featured image saved',
editErrorSlugExists: 'Blog with this slug already exists',
editErrorBodyRequired: 'Blog body is required'
}
});
You can change the format of dates the blog uses in the Blog.config. Any acceptable display format supported by Moment.js can be selected (e.g., 'D MMM YYYY' or 'YYYY-MM-DD'). The default date format is:
Blog.config({
dateFormat: 'MMM Do, YYYY'
});
MIT