Customization Example
Vulcan was made to be extensible from the ground up. This means that you can tweak and adapt many existing features to your needs without having to rewrite them from scratch.
In this tutorial, we’ll look at the example-customization
code file by file to see how we can easily extend Vulcan with minimal work.
Note that we’re mainly talking about customizing forum packages here.
Intro
Custom Packages
In Vulcan, everything is a package, so the first thing you’ll need to do is to create a new directory in /packages
to hold your code, and a package.js
file inside that:
1 | Package.describe({ |
Let’s go through this file block by block.
Package.describe
is used to set your package’s metadata. Only thename
is required, but you can also add a version, Git repository, etc.Package.onUse
contains the code used to load our package.api.use
declares the package’s dependencies on other Meteor packages. These dependencies can be either local (living in/packages
likevulcan:*
) or remote (pulled from Meteor’s package server likefourseven:scss
).api.mainModule
is used to declare your package’s client and server entry points and should be used to load JavaScript files.api.addFiles
is used to add files one by one, usually HTML or CSS.api.addAssets
is used to add static assets to your package. Basically, anything that’s not a JavaScript, HTML, or CSS file. Make sure to declare the files for client side['client']
otherwise you might not see these files. images should come from\packages\<package-name>\static\
the “static” folder name is where you store your images, you can rename this to whatever you want. Beware of storing static assets in git. More info can be found in Meteor’s docs regardingAssets
.
Custom Styles
The simplest and most common customization is probably tweaking your styles. Thanks to Meteor’s automatic CSS packaging features, all you need to do is point your custom package to a style file.
1 | api.addFiles([ |
And since we’re using the fourseven:scss
package, we can use a SCSS file:
1 | .logo-hello { |
Protip: a good way to make sure that your CSS file is getting properly bundled up and applied is to include something very visible like body{ background: red; }
.
Replacing Components
A really cool feature of Vulcan’s theming system is the ability to replace a specific component without having to overwrite the entire theme.
For example, let’s consider the Forum example’s Logo
component:
1 | import React from 'react'; |
We’ll replace it with a new component that shows a welcome message next to the logo:
1 | import React from 'react'; |
Note how we’re adding the withCurrentUser
higher-order component to give our new CustomLogo
component access to the currentUser
prop.
All that’s needed now is to import this file from modules.js
:
1 | import "./components/CustomLogo.jsx"; |
Extending Components
Replacing the entire component works for simple components, but sometimes you only want to replace one part of the component (typically its render
method) while preserving others.
Take a look at the CustomNewsletter
component to see an example of doing just that:
1 | import { Components, replaceComponent, getRawComponent } from 'meteor/vulcan:core'; |
It’s interesting to note that we’re using the extend
syntax to extend the original component, in order to inherit from all its methods. We’re extending getRawComponent('Newsletter')
and not just Components.Newsletter
to make sure we extend the original component before it gets wrapped with any HoCs such as withCurrentUser
, withRouter
, etc.
What’s more, the replaceComponent
method will make sure to preserve the original component’s HoCs and re-wrap our new custom component with them.
By extending the component, we’re able to only redefine the render
method while preserving all the others (in this case constructor
, componentWillReceiveProps
, etc.).
You can also look at the CustomPostItem
component to see another example of extending components.
You can learn more about replacing and extending components in the Components & Theming section.
Strings & Internationalization
Another common need is changing the wording of a specific string. Vulcan uses the react-intl library to make every string in the default components customizable and translatable.
1 | import { addStrings } from 'meteor/vulcan:core'; |
You can learn more about translating strings in the Internationalization section.
Custom Fields
Custom fields let you add extra properties to predefined collections like Posts
or Comments
. In the custom_fields.js
file, we’re adding a new color
property to posts, and making it insertable, editable, and viewable by any member of the members
user group (in other words, regular users):
1 | import Posts from "meteor/vulcan:posts"; |
We’ll then extend the PostsItem
component to add a CSS class to the posts-item
div based on this color field:
1 | import { replaceComponent, getRawComponent } from 'meteor/vulcan:core'; |
Don’t forget to also add the color
property to the fragment that governs what data we query for.
Learn more about adding your own custom fields in the Custom Fields section.
Callbacks
Callbacks let you insert your own server-side logic at key points in Vulcan’s code. For example, the callbacks.js
file shows you how you can insert random emojis in a post title whenever a new post is inserted:
1 | import { addCallback } from 'meteor/vulcan:core'; |
You can learn more about callbacks in the Callbacks section.
Groups
Out of the box, Vulcan considers three kind of users: guests (users without an account), members (users with a normal account), and admins. Let’s add a fourth kind, mods, in groups.js
:
1 | import Users from 'meteor/vulcan:users'; |
We’ll give mods two extra actions: editing and removing other user’s posts. Note that like everybody else, mods are also considered part of the default
group so they inherit all the default permissions too.
You can learn more about user groups in the Groups & Permissions section.
Routes
Adding a new route is easy enough. After creating a new MyCustomPage
component we just add the following code in routes.js
:
1 | import { addRoute } from 'meteor/vulcan:core'; |
You can learn more about routes in the Routing section.
Emails & Email Templates
Finally, we’ll also customize the email notification that gets sent out when a user creates a new post, as well as add a new email template. This is a three-step process.
First, we need to create the new templates (customEmail.handlebars
and customNewPost.handlebars
in lib/server/emails
) using the Handlebars templating language.
Then, we register these two files as assets in package.js
:
1 | api.addAssets([ |
Finally, we retrieve these two assets and assign them to email templates in lib/server/templates.js
:
1 | import VulcanEmail from 'meteor/vulcan:email'; |
You can learn more about customizing emails in the Email section.
Conclusion
By going through this sample package’s code, you’ve learned how to customize most aspects of Vulcan without having to modify any of Vulcan’s original code.
You can now use that newfound knowledge to build your app, or even create new themes and plugins to add to the Vulcan ecosystem. The rest is up to you!