Module configuration options
Apostrophe modules can be configured with settings that influence functionality without having to write custom JavaScript. The sections below describe the options available in all modules as well as those specific to certain module types.
All settings described here are placed in a module's options
configuration object. The options
object can be added in the module's index.js
file, as well as where the module is instantiated in the app.js
file.
index.js
example:
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
// 👇 Module configuration options
options: {
alias: 'article',
label: 'Article',
pluralLabel: 'Articles',
quickCreate: true
},
// Other settings, such as `fields`
}
app.js
example:
// app.js
require('apostrophe')({
shortName: 'bowling-league-site', // Unique to your project
modules: {
article: {
extend: '@apostrophecms/piece-type',
// 👇 Module configuration options
options: {
alias: 'article',
label: 'Article',
pluralLabel: 'Articles',
quickCreate: true
},
// Other settings, such as `fields`
}
}
});
Using module options
Most module options in Apostrophe core and official extension modules are used automatically for specific purposes. No additional work is needed to use them for their original purposes other than configuring them.
Module options can also be referenced directly in custom module code. Module configuration function sections take a self
argument, which is the module itself. You can then get the options as self.options
.
For example, if you had a custom piece type, it might look like this:
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
alias: 'article'
},
init (self) {
const moduleOptions = self.options;
// ...
},
methods (self) {
return {
logOptions () {
console.log('The module alias is ', self.options.alias);
}
}
}
}
Options for any module
Option settings in this section apply to every module in Apostrophe.
Option | Value type | Description |
---|---|---|
alias | String | Configure an alias to more easily reference the module elsewhere. |
components | Object | Configure custom UI Vue components to be used for the module. |
csrfExceptions | Array | An array of route names in the module, or URLs starting with / , that should bypass CSRF protection. |
i18n | Boolean/Object | Indicate that the module will include localization strings for the i18n module (with optional configuration). |
templateData | Object | Set data to be included on req.data for requests to this module. |
alias
Set to a string, the alias
value will be applied to the apos
object (accessible in many places) as a quick reference to the module. set an alias to easily reference the module from other modules. There is no default value.
Example
// modules/news-article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
alias: 'article'
},
// ...
}
This article
module can then be referenced anywhere the apos
object is present as apos.article
. Otherwise it would be available via apos.modules['news-article']
.
NOTE
With the exception of modules present in Apostrophe core at the time of the 3.x stable release, modules distributed via npm should never set alias
for themselves or assume that it has been set. This is to avoid conflict when multiple modules attempt to use the same alias.
components
The components
options is an object identifying Vue components to use for the module's related user interface. The keys of this object, and thus the UI being overridden, will vary based on the module type. For example, piece modules use managerModal
and editorModal
components.
This is an advanced option since it can easily break the user interface.
Example
// modules/@apostrophecms/piece-type/index.js
module.exports = {
options: {
components: {
managerModal: 'MyCustomPiecesManager'
}
},
// ...
}
csrfExceptions
See the Express module for more on CSRF protection in Apostrophe. This option can contain an array of route names or relative URLs that should bypass CSRF protection.
Example
// modules/access/index.js
module.exports = {
options: {
csrfExceptions: [ 'login', '/safe-url' ]
},
// ...
}
i18n
If set to a truthy value, Apostrophe will look for an i18n
subdirectory in that module with one or more JSON files with localization string definitions (e.g., modules/project-languages/es.json
). The JSON file names should match configured locale names. See the static i18n guide for more information.
If set to an object, there may be ns
and browser
properties.
i18n setting | Value type | Description |
---|---|---|
ns | String | A namespace for localization string keys in this module. If undefined, Apostrophe will use the 'default' namespace. That namespace is intended for project-level localization. |
browser | Boolean | Set to true to make the JSON key/string pairs available on the browser window (e.g., apos.i18n.i18n.en.default ) when logged in. Necessary when localizing strings in the UI, including doc type labels. |
INFO
The namespace 'apostrophe'
is reserved for Apostrophe's UI. You may intentionally set ns
to 'apostrophe'
if your goal is to localize the Apostrophe user interface.
See the static i18n guide for more information on both settings.
Example
// modules/project-languages/index.js
module.exports = {
extend: '@apostrophecms/module',
options: {
i18n: {
namespace: 'projectName',
browser: true
}
}
}
templateData
Similar to browser
, the templateData
module option can be set to an object whose properties will be made available in templates of that module. Properties are attached directly to the data
object in templates.
Example
// modules/heading-widget/index.js
module.exports = {
extend: '@apostrophecms/widget-type',
options: {
templateData: {
defaultColor: '#55ff93'
}
},
// ...
}
You might use that value as a fallback for user-editable fields.
{# In `modules/heading-widget/index.js` #}
{% set bgColor = data.widget.color or data.defaultColor %}
<h2 style="background-color: {{ bgColor }}">
Title Here
</h2>
Options for all doc type modules
Option settings in this section apply to all modules that extend @apostrophecms/doc-type
(doc type modules). These include all piece and page types.
Option | Value type | Description |
---|---|---|
adminOnly | Boolean | Set to true to only allow admins to manage the doc type. |
autopublish | Boolean | Set to true to publish all saved edits immediately. |
label | String | The human-readable label for the doc type. |
localized | Boolean | Set to false to exclude the doc type in the locale system. |
sort | Object | Configure sort order for docs of this type. |
slugPrefix | String | Add a prefix to all slugs for this doc type. |
adminOnly
If true
, only users with the sitewide admin permission can read or write docs of this type. The @apostrophecms/user
module uses this setting due to its impact on user access. There is no default value.
Example
// modules/official-memo/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
adminOnly: true
},
// ...
}
autopublish
Set autopublish
to true
to automatically publish any changes saved to docs of this type. There is then effectively no draft mode for this doc type.
The core image and file modules use this option, for example. It eliminates the need for users to think about the distinction between draft and published content while preserving the possibility of translation for different locales.
Example
// modules/article-category/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
autopublish: true
},
// ...
}
label
(for doc types)
label
should be set to a text string to be used in user interface elements related to this doc type. This includes buttons to open piece manager modals and the page type select field.
If not set, Apostrophe will convert the module name
meta property to a readable label by splitting the name
on dashes and underscores, then capitalizing the first letter of each word.
Example
// modules/feature/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
label: 'Featured Article'
},
// ...
}
localized
Defaults to true
. If set to false
, this doc type will not be included in the locale system. This means there will be only one version of each doc, regardless of whether multiple locales (e.g., for languages or regions) are active. The "users" piece disables localization in this way.
Example
// modules/administrative-category/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
localized: false
},
// ...
}
sort
The sort
option for a doc type defines a sorting order for requests to the database for that type. The option is set to an object containing field name keys with 1
as a property value for ascending order and -1
for descending order.
The default sort for all doc types is { updatedAt: -1 }
, meaning it returns documents based on the updatedAt
property (the date and time of the last update) in descending order. The sort
object can have multiple keys for more specific sorting.
Example
This sort
setting will return articles first based on a custom priority
field in ascending order, then by the core updatedAt
property in descending order.
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
sort: {
priority: 1,
updatedAt: -1
}
},
fields: {
add: {
priority: {
type: 'integer',
min: 1,
max: 5
},
// ...
}
}
// ...
}
slugPrefix
Set slugPrefix
to a string to prepend all slugs for docs of this type. This can prevent slugs, which must be unique to each doc, from being reserved in some cases. For example, Apostrophe image docs have the slugPrefix
value of 'image-'
so images, which do not typically have public pages, do not accidentally reserve a more reader-friendly slug.
Example
// modules/article-category/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
slugPrefix: 'category-'
},
// ...
}
Options for all piece modules
Option settings in this section apply to all piece modules (those that extend @apostrophecms/piece-type
).
Option | Value type | Description |
---|---|---|
pluralLabel | String | The plural readable label for the piece type. |
perPage | Integer | The number of pieces to include in a set of GET request results. |
publicApiProjection | Object | Piece fields to make available via a public REST API route. |
quickCreate | Boolean | Set to true to add the piece type to the quick create menu. |
searchable | Boolean | Set to false to remove the piece type from search results. |
pluralLabel
Similar to label
for all doc types, the pluralLabel
option sets the string the user interface will use to describe a piece type in plural contexts. All page types are referred to as "Pages" in these contexts, but pieces should have unique labels (e.g., "Articles," or "Teams").
If no pluralLabel
value is provided, Apostrophe will append the label
(whether set manually or generated as described), with "s", as is typical for English words. Even in English this is often not correct, so pluralLabel
should usually be defined explicitly.
Example
// modules/goose/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
label: 'Goose',
pluralLabel: 'Geese'
},
// ...
}
perPage
In piece types, the perPage
option, expressed as an integer, sets the number of pieces that will be returned in each "page" during GET
requests that don't specify an _id
. This value defaults to 10.
Example
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
perPage: 20 // REST `GET` requests will return 20 pieces per page.
},
// ...
}
publicApiProjection
(for pieces)
By default the built-in Apostrophe REST APIs are not accessible without proper authentication. You can set an exception to this for GET
requests to return specific document properties with the publicApiProjection
option.
This should be set to an object containing individual field name keys set to 1
for their values. Those fields names included in the publicApiProjection
object will be returned when the GET
API requests are made without authentication.
Example
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
publicApiProjection: {
title: 1,
authorName: 1,
_url: 1 // 👈 Dynamic properties are allowed
}
},
// ...
}
Unauthenticated GET /api/v1/article
requests would return each piece with only the title
, authorName
, and _url
properties.
quickCreate
(for pieces)
Setting quickCreate: true
on a piece adds that piece type to the admin bar "quick create" menu. The Apostrophe admin bar user interface includes the quick create menu button to add new pieces without first opening their respective manager modals.
Example
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
quickCreate: true
},
// ...
}
searchable
Setting searchable: false
on a piece type will exclude that piece type from the results in Apostrophe's built-in search.
Example
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
searchable: false
},
// ...
}
Options for the core page module
Option settings in this section apply to the core page module (@apostrophecms/page
).
Option | Value type | Description |
---|---|---|
builders | Object | Set query builder values to be used when pages are served. |
home | Boolean/Object | Change how the home page is added to req.data when pages are served. |
minimumPark | Array | Override default parked pages, including the home page. |
park | Array | Set pages to be created on site start with configuration. |
publicApiProjection | Object | Set query builder values to be used when pages are served. |
quickCreate | Boolean | Set to false to remove pages from the quick create menu. |
types | Array | Set the page types available for new pages. |
builders
The builders
option can be used to apply any existing query builders when a page is served by its URL. This affects the data available on the page object, req.data.page
(data.page
in templates).
The default value is:
{
children: true,
ancestors: { children: true }
}
In this example, page objects are fetched with one level of page tree "children" as _children
and their "ancestor" pages, each with one level of their child pages, on _ancestors
.
Example
// modules/@apostrophecms/page/index.js
module.exports = {
options: {
builders: {
children: { depth: 2 }
}
},
// ...
}
In this example, we are not including ancestor pages and are requesting two levels of child pages (direct children and their direct children).
home
The home page document is added to all page requests on req.data.home
so it can be referenced in all page templates. That home page object also includes a _children
property containing an array of top level page objects. The home
option offers minor performance improvements for large sites by setting one of the following values:
Setting | Description |
---|---|
false | Disables adding the home page document to the requests. |
{ children: false } | Includes the home page document, but without the child pages array. If the builders option has an ancestors property, that will take precedence. |
Example
// modules/@apostrophecms/page/index.js
module.exports = {
options: {
home: { children: false }
},
// ...
}
minimumPark
The minimumPark
option sets the initial defaults for the home page and archive "page" (the page archive). This should normally be left as it is. A possible use case for changing this might be when building an installable module meant to change the defaults for all websites that use it.
WARNING
Configuring this poorly, especially by leaving out one of the two required pages, will break page functionality. In almost every situation it is better to use the park
option instead, including for updating home page properties.
The default is:
[
{
slug: '/',
parkedId: 'home',
_defaults: {
title: 'Home',
type: '@apostrophecms/home-page'
}
},
{
slug: '/archive',
parkedId: 'archive',
type: '@apostrophecms/archive-page',
archived: true,
orphan: true,
title: 'Archive'
}
]
Example
// modules/@apostrophecms/page/index.js
module.exports = {
options: {
minimumPark: [
{
slug: '/',
parkedId: 'home',
_defaults: {
title: 'Welcome', // 👈
type: 'welcome-page' // 👈
}
},
{
slug: '/archive',
parkedId: 'archive',
type: '@apostrophecms/archive-page',
archived: true,
orphan: true,
title: 'Archive'
}
]
},
// ...
}
park
Use the park
option to add an array of pages that should be created when the app starts up if they do not already exist. Each page is added as an object with initial properties, including the required parkedId
.
Required and recommended parked page properties include:
Setting | Requirement | Description |
---|---|---|
parkedId | Required | A unique ID value used to identify it among parked pages. |
slug | Required | The page slug. |
type | Required | The page type to be used for the parked page. |
title | Recommended | The page title. If not set, it will be "New Page." |
If added on the top level of the page object, these properties will not be editable through the user interface. Properties other than parkedId
may be included in a _defaults
property instead, which will allow them to be edited in the UI.
Example
// modules/@apostrophecms/page/index.js
module.exports = {
options: {
park: [
// The blog page has a permanent slug, title, and type.
{
parkedId: 'blogParkedId',
slug: '/blog',
title: 'Blog',
type: 'blog-page'
},
// The team page has a permanent type, but editable slug and title.
{
parkedId: 'teamParkedId',
type: 'staff-page',
_defaults: {
slug: '/team',
title: 'Our Team',
}
}
]
},
// ...
}
publicApiProjection
(for pages)
By default the built-in Apostrophe REST APIs are not accessible without proper authentication. You can set an exception to this for GET
requests to return specific document properties with the publicApiProjection
option.
This should be set to an object containing individual field name keys set to 1
for their values. Those fields names included in the publicApiProjection
object will be returned when the GET
API requests are made without authentication.
Example
// modules/@apostrophecms/page/index.js
module.exports = {
options: {
publicApiProjection: {
title: 1,
_url: 1 // 👈 Dynamic properties are allowed
}
},
// ...
}
Unauthenticated GET /api/v1/@apostrophecms/page
requests would return each piece with only the title
and _url
properties.
quickCreate
(for pages)
Pages are included in the admin bar "quick create" menu by default. Setting quickCreate: false
on the page module will disable this.
Example
// modules/@apostrophecms/page/index.js
module.exports = {
options: {
quickCreate: false
},
// ...
}
types
The types
array defines the page types available to users when creating or editing pages. Each item in the array should have a label
property and a name
property, which matches an active page type. If no types
array is set, only the core "Home" page type will be available.
Parked pages may use page types that are not in the types
option array. This allows developers to do things such as parking a single search page but not allowing users to create additional search pages.
Example
// modules/@apostrophecms/page/index.js
module.exports = {
options: {
types: [
{
name: 'default-page',
label: 'Default'
},
{
name: 'article-page',
label: 'Article Index'
}
{
name: '@apostrophecms/home-page',
label: 'Home'
}
]
},
// ...
}
Options for page type modules
Option settings in this section apply to all page types (modules that extend @apostrophecms/page-type
).
Option | Value type | Description |
---|---|---|
scene | String | Change the "scene" for this page type from the default 'public' . |
scene
Scenes are contexts in which certain sets of front end assets are delivered. Normally, anonymous site visitors receive only the stylesheets and scripts included in the 'public'
asset scene (those that are placed in the module's ui/public
directory). If your page will use assets, such as Apostrophe's modals, that are normally reserved for logged-in users you can set scene: 'apos'
in order to load them with pages of this type.
Example
// modules/fancy-form-page/index.js
module.exports = {
extend: '@apostrophecms/page-type',
options: {
scene: 'apos'
},
// ...
}
Options for piece page types
Option settings in this section apply to all piece page types (modules that extend @apostrophecms/piece-page-type
).
Option | Value type | Description |
---|---|---|
perPage | Integer | Set the number of pieces to display in each set of paginated index page results. |
next | Boolean/Object | Enable and optionally configure the req.data.next object. |
piecesFilters | Array | Configure pieces filters for index pages. |
pieceModuleName | String | Specify the associated piece type if it doesn't match the module name. |
previous | Boolean/Object | Enable and optionally configure the req.data.previous object. |
perPage
For piece pages, the perPage
option, expressed as an integer, defines the number of pieces that will be added to the req.data.pieces
array when the page is served. The specific pieces in the set will be based on the total number of pieces and the page
query parameter in the request.
This is, more simply, the number of pieces that will normally be displayed on each page of a paginated index page. This value defaults to 10.
Example
// modules/article-page/index.js
module.exports = {
extend: '@apostrophecms/piece-page-type',
options: {
perPage: 12
},
// ...
}
next
If set to true
, Apostrophe will include the next piece, based on the sort option, on req.data.next
when serving a show page. This is useful to add links to a show page directing visitors to the next item in a series (e.g., the next oldest blog post). If not set, req.data.next
will not be available.
next
can also be set to an object, which will be used as a query builder for retrieving that next piece document.
Example
// modules/article-page/index.js
module.exports = {
extend: '@apostrophecms/piece-page-type',
options: {
next: true
},
// ...
}
// OR
module.exports = {
extend: '@apostrophecms/piece-page-type',
options: {
// The next article piece would be returned with only the `title`, `_url`,
// and `publishedAt` properties.
next: {
project: {
title: 1,
_url: 1,
publishedAt: 1
}
}
},
// ...
}
piecesFilters
piecesFilters
, configured as an array of objects, supports filtering pieces on an index page. Each object must have a name
property associated with a valid query builder. These include:
- Custom query builders configured in an app that include a
launder
method - Field names whose field types automatically get builders:
boolean
checkboxes
date
float
integer
relationship
select
slug
string
url
When the index page is served, configured filters will be represented on a req.data.piecesFilters
object (data.piecesFilters
in the template). If you include counts: true
in a filter object, the number of pieces matching that filter are included on req.data.piecesFilters
properties.
Example
// modules/article-page/index.js
// 👆
module.exports = {
extend: '@apostrophecms/piece-page-type',
options: {
piecesFilters: [
{ name: '_author' },
{
name: 'category',
counts: true
}
]
},
fields: {
_author: {
type: 'relationship',
label: 'Author'
},
category: {
type: 'select',
label: 'Category',
choices: [
// Category choices here
]
}
// Other fields...
},
// ...
}
pieceModuleName
Piece page types are each associated with a single piece type. If named with the pattern [piece name]-page
, the associated piece type will be detected automatically. For example, if the article-page
module extends @apostrophecms/piece-page-type
, it will automatically be associated with an article
piece type.
You can override this pattern by explicitly setting pieceModuleName
to an active piece type name. Ths can be useful if there is more than one piece page type for a single piece type (e.g., to support different functionality in each).
Example
// modules/team-page/index.js
// 👆 This module name would look for a piece type named `team` if not for
// `pieceModuleName`
module.exports = {
extend: '@apostrophecms/piece-page-type',
options: {
pieceModuleName: 'person'
},
// Maybe there's code here to group people by team.
// ...
}
previous
If set to true
, Apostrophe will include the previous piece, based on the sort option, on req.data.previous
when serving a show page. This is useful to add links to a show page directing visitors to the previous item in a series (e.g., the next newest blog post). If not set, req.data.previous
will not be available.
previous
can also be set to an object, which will be used as a query builder for retrieving that next piece document.
Example
// modules/article-page/index.js
module.exports = {
extend: '@apostrophecms/piece-page-type',
options: {
previous: true
},
// ...
}
// OR
module.exports = {
extend: '@apostrophecms/piece-page-type',
options: {
// The previous article piece would be returned with only the `title`,
// `_url`, and `publishedAt` properties.
previous: {
project: {
title: 1,
_url: 1,
publishedAt: 1
}
}
},
// ...
}
Options for widget modules
Option settings in this section apply to all widgets (modules that extend @apostrophecms/widget-type
).
Option | Value type | Description |
---|---|---|
className | String | Applies a class to core widget templates. |
icon | String | Select an available icon to include with the label in area menus. |
label | String | The human-readable label for the widget type. |
className
Official Apostrophe widget templates support adding an html class from the className
module option. The class is applied to the outer, wrapping HTML element in the widget template for easy styling.
Example
// modules/@apostrophecms/image-widget/index.js
module.exports = {
options: {
className: 'c-image-widget'
},
// ...
}
icon
Identify an icon to be used with a widget label in the area menu with the icon
option. That icon must be included in the list of globally available UI icons or configured on the module in its icons
section. See the module settings reference for how to make new icons available.
Example
// modules/two-column-widget/index.js
module.exports = {
extend: '@apostrophecms/widget-type',
options: {
icon: 'pillar'
},
icons: {
pillar: 'Pillar'
},
// ...
};
label
(for widgets)
label
should be set to a text string to be used in the area menu. If not set, Apostrophe will convert the module name
meta property to a readable label by removing -widget
from the end, splitting the name
on dashes and underscores, and capitalizing the first letter of each word.
Example
// modules/two-column-widget/index.js
module.exports = {
extend: '@apostrophecms/widget-type',
options: {
label: 'Two Column Layout'
},
// ...
};
Options for the core rich text widget
Option settings in this section apply to the core rich text widget module (@apostrophecms/rich-text-widget
).
Option | Value type | Description |
---|---|---|
defaultData | Object | Define initial default data for rich text content. |
defaultOptions | Object | Configure the rich text toolbar and styles for rich text widgets. |
editorTools | Object | Configure rich text tools and their Vue components. |
defaultData
Rich text widgets can start with default content by setting defaultData
to an object with a content
property. That value would be a string of text or HTML that all rich text widgets would include when added.
Example
// modules/@apostrophecms/rich-text-widget/index.js
module.exports = {
options: {
defaultData: {
content: '<p>Replace me</p>'
}
},
// ...
}
defaultOptions
The rich text widget is configured by default with useful rich text toolbar settings and styles. These can be overridden by setting defaultOptions
. This configuration object can include any of the toolbar
, styles
, and color
sub-options. Sub-options that are not included will fall back to the defaults.
defaultOptions
can also be overridden in schema configuration where an area configures its rich text widgets. So a project can have site-wide defaults, but a specific area can have its own separate configuration.
Example
// modules/@apostrophecms/rich-text-widget/index.js
module.exports = {
options: {
defaultOptions: {
toolbar: [
'bold',
'color',
'italic',
'link'
],
styles: [],
color: {
presetColors: [ '#000000', '#ffffff', '#ff0000', '#00ff00', '#0000ff'],
}
}
},
// ...
}
editorTools
The rich text editor toolbar tools (e.g., "bold," "link," and "underline" buttons) can be reconfigured to have different labels (seen by assistive technologies), different icons, or even new Vue components altogether. editorTools
can be completely overridden to do this if desired.
WARNING
Using this option takes full responsibility for the configuration of the rich text editor tools. Use this with caution. If overriding, be sure to include all rich text tools that you will use.
If introducing an editor tool that is not included in core, you will need to create both the Vue component and, often, a tiptap extension.
// modules/@apostrophecms/rich-text-widget/index.js
module.exports = {
options: {
editorTools: {
styles: {
component: 'MyTiptapStyles',
label: 'Styles'
},
'|': { component: 'MyTiptapDivider' },
bold: {
component: 'MyTiptapButton',
label: 'Bold',
icon: 'format-bold-icon'
},
italic: {
component: 'MyTiptapButton',
label: 'Italic',
icon: 'format-italic-icon'
},
// Many more tools...
}
},
// ...
}