How to Use Apostrophe as a Headless CMS
Antonello Zanini
Posted on June 16, 2023
Apostrophe is an open-source content management system (CMS) and website builder built on JavaScript. In addition to the features offered by traditional CMS technologies, Apostrophe can also be configured to function as a headless CMS. A headless CMS allows developers to manage and reuse content over multiple formats and devices, without being tied to a particular output format. It separates the content layer from the presentation layer.
Thanks to its built-in RESTful API endpoints, developers can create, retrieve, update, and delete (CRUD) content through simple HTTP calls. Here, you will learn about what endpoints Apostrophe exposes, and how to use them!
Let’s dive in!
Is Apostrophe a Headless CMS?
Short answer: Yes, Apostrophe is a headless CMS! More specifically, it is also a headless CMS.
Apostrophe is a full-stack content management system based on Node.js and Vue.js that provides a powerful platform for building websites, web apps, and digital experiences. On top of that, it comes with advanced built-in headless capabilities.
This means that editors and designers can take advantage of all of the benefits of a traditional CMS, such as WordPress. Simultaneously, developers can interact with content and media via API, such as in Contentful. Check out our Contentful vs Apostrophe article for more details.
Get the best of the two worlds with Apostrophe!
Set Up Apostrophe as a Headless CMS
In this step-by-step section, you will learn how to get started with Apostrophe and configure it as a headless CMS. If you already have an ApostropheCMS project, you can skip the first three subchapters and go straight to the last one.
Initialize an Apostrophe Project
First, make sure you have MongoDB and the latest LTS version of Node installed on your machine. Then, launch the command below to install the Apostrophe CLI:
npm install -g @apostrophecms/cli
Now, you can create a new Apostrophe project with:
apos create apos-app
The command will take care of installing the required dependencies and walk you through the initialization process.
Refer to the Setting Up
guide from the official documentation in case of need.
Define the Piece Types
In Apostrophe, a piece type represents the model of a real-world content entity. Specifically, it contains all the field attributes required to define a stand-alone piece of content in the CMS. Here, you will learn how to set up the article
piece type. Keep in mind that content modeling depends on your application domain, so adapt the examples below to your needs.
To create a new piece in Apostrophe, you need to add a module that extends @apostrophecms/piece-type
. You can generate the starter code for the article
type using the official CLI command below:
apos add piece article
In the modules
folder, you will now have an article
directory containing the following index.js
file:
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
label: 'Article',
// Additionally add a `pluralLabel` option if needed.
},
fields: {
add: {},
group: {}
}
};
If you do not want to use the Apostrophe CLI, you can initialize this JavaScript file manually. By default, a piece type with no extra configuration has the title
, slug
, and visibility
fields.
You can define a proper model for blog articles by updating index.js
as follows:
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
label: 'Article'
// Additionally add a `pluralLabel` option if needed.
},
fields: {
add: {
image: {
label: 'Featured image',
type: 'area',
options: {
max: 1,
widgets: {
'@apostrophecms/image': {}
}
}
},
content: {
label: 'Content',
type: 'area',
options: {
widgets: {
// enable the rich-text editor
'@apostrophecms/rich-text': {},
// allow multimedia files
'@apostrophecms/image': {},
'@apostrophecms/video': {}
}
}
}
},
group: {
basics: {
label: 'Basics',
fields: [ 'title', 'content', 'image' ]
}
}
}
};
The fields
object should involve the following two attributes:
-
add
: defines the attributes of the content type -
group
: specifies how the attribute inputs are grouped in tabs in the UI Then, register the new piece types in themodules
field inapp.js
:
// app.js
require('apostrophe')({
shortName: 'my-blog',
modules: {
article: {},
// remaining configs ...
}
});
Great! This is how content modeling works in ApostropheCMS! Read our guide to learn how to build a blog in Apostrophe.
Create Some Pieces
Individual records of a specific piece type are called “pieces.” You can populate them through the easy-to-use content management UI offered by Apostrophe.
Time to create some content. In the Admin UI, click on the “Articles” button in the top menu.
Then, click “New Article” to open the following modal:
Fill out the form and click on the “Publish” button to create a new article piece. Repeat this process to generate more content.
Do the same for all other piece types in your project.
As you can see, managing content in Apostrophe is simple and intuitive. Anyone can do it, even non-technical users. Let’s now learn how to publicly access this content via API.
Apostrophe Headless CMS APIs in Action
Apostrophe automatically exposes several RESTful endpoints for each piece type. This means that the tool offers built-in headless CMS capabilities, and you do not need extra configuration to enable this feature.
It is time to see the most common headless endpoints offered by Apostrophe in action. To test the sample API calls you will see in this section, an HTTP client is recommended. Postman or Insomnia will do.
Check out the docs to explore all API endpoints available!
API Authentication
Apostrophe comes with several API authentication methods, including API keys, bearer tokens, and session cookies. Here, we will focus on bearer tokens. Since they are associated with a single account, they represent the most appropriate option for browser use and headless applications.
To get a valid bearer authentication token, perform a POST
request to /api/v1/@apostrophecms/login/login
, with username
and password
in the JSON body:
{
"username": "<YOUR_USERNAME>",
"password": "<YOUR_PASSWORD>"
}
If the login credentials are correct, Apostrophe will respond with a JSON object including a token
property:
{
"token": "clhj8xkji0004y0ff0jjl9zx9"
}
Store the bearer token returned by the server in a safe place. You can use it to access APIs that require login by specifying it in the HTTP [Authorization] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization)
header of the request as below:
Bearer <YOUR_BEARER_TOKEN>
Take a look at the documentation to explore other authentication methods available.
Make the API Endpoints Public
By default, the Apostrophe REST APIs are accessible only by authenticated users. However, you can elect to allow the HTTP GET
endpoints for a specific piece to be made publicly accessible using the [publicApiProjection] (https://v3.docs.apostrophecms.org/reference/api/authentication.html#allowing-public-access)
option:
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
label: 'Article',
publicApiProjection: {
title: 1,
slug: 1,
image: 1
},
// other options...
},
fields: {
// omitted for brevity...
}
};
This option enables you to control the fields returned by the GET
endpoints by adding or omitting them in the publicApiProjection
object. Note that this applies only to unauthenticated users. Authenticated users will always receive all available data.
Alternatively, if you want to give a SPA the ability to access all the fields in a piece type through the GET
endpoint without also having other CRUD privileges, you can do so through the guestApiAccess option. This gives a logged-in guest user with no editing privileges full GET
access.
Keep in mind that this does mean the user must log in, typically via our bearer token API. So it is well-suited to sites requiring user signup, such as with our @apostrophecms-pro/signup module, and possibly payment to access content with the "login required" flag. But if you want the whole world to see your content, use publicApiProjection
instead.
You can enable this configuration for a specific piece as follows:
// modules/article/index.js
module.exports = {
extend: '@apostrophecms/piece-type',
options: {
label: 'Article',
guestApiAccess: true
// other options...
},
fields: {
// omitted for brevity...
}
};
Retrieve All Pieces
You can get all records of a specific piece type in a paginated manner with the [GET /api/v1/:piece-type-name] (https://v3.docs.apostrophecms.org/reference/api/pieces.html#get-api-v1-piece-name)
endpoint.
For example, you can get all articles with a GET
request to /api/v1/article
.
Apostrophe will produce a paginated response in the following format:
{
"pages": 1,
"currentPage": 1,
"results": [
{
"_id": "clhj5wwoi0031bwffh65df6ga:en:published",
"slug": "failure-key-to-success",
"title": "Why Failure is the Key to Success: Lessons from Famous Failures",
"image": {
// ...
},
"cacheInvalidatedAt": "2023-05-11T13:25:36.568Z"
},
// ...
{
"_id": "clhj5mp8g0017bwff6bkf9t57:en:published",
"slug": "benefits-traveling-alone",
"title": "5 Surprising Benefits of Traveling Alone",
"image": {
// ...
},
"cacheInvalidatedAt": "2023-05-11T13:17:40.524Z"
}
]
}
If you elected to use the publicApiProjection
option and did not present a bearer token, the entities inside results
will only include the attributes specified in the configuration object.
results
contains only the first 10 elements, also known as the first page. You can access other pages by specifying the page
query parameter, as in the example below:
http://localhost:3000/api/v1/article?page=2
You will now have access also to the content
field.
Retrieve a Specific Piece
You can retrieve a specific piece by _id
with the [GET /api/v1/:piece-type-name/:_id] (https://v3.docs.apostrophecms.org/reference/api/pieces.html#get-api-v1-piece-name-id)
API.
For example, you can get the clhj5wwoi0031bwffh65df6ga:en:published
article with:
http://localhost:3000/api/v1/article/clhj5wwoi0031bwffh65df6ga:en:published
Apostrophe will produce a flat JSON object containing all attributes associated with the specified piece. In case of some missing data, it will return a [404 Not Found] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404)
error response.
Filter Some Pieces
Apostrophe allows you to filter the result of the paginated GET
endpoint through some special query parameters. For example, you can get all articles containing the word “happiness” with:
http://localhost:3000/api/v1/article?search=happiness
Thanks to these parameters, you can also get localized and draft content. Note that authentication is required to get drafts.
Create a New Piece
You can create a new piece by passing all required fields to the JSON body of the [POST /api/v1/:piece-name] (https://v3.docs.apostrophecms.org/reference/api/pieces.html#post-api-v1-piece-name)
endpoint.
For example, you can insert a new article as in the image below:
By default, Apostrophe will publish the content and return its attributes, including the _id
. To create a draft, specify the aposMode=draft
query parameter in the request.
In case of some missing required fields, the server will respond with a [422 Unprocessable Content] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422)
error.
Update a Piece
Similarly to above, you can update a piece with the [PUT /api/v1/:piece-name/:_id] (https://v3.docs.apostrophecms.org/reference/api/pieces.html#put-api-v1-piece-name-id)
API. The main difference is that you also have to specify the _id
of the existing piece in the endpoint.
If you omit a field in the JSON body, this will be restored to its default value. To partially update only some attributes of a piece, use the [PATCH /api/v1/:piece-name/:_id] (https://v3.docs.apostrophecms.org/reference/api/pieces.html#patch-api-v1-piece-name-id)
endpoint.
Delete an Existing Piece
To delete a piece, specify its _id
in the [DELETE /api/v1/:piece-name/:_id] (https://v3.docs.apostrophecms.org/reference/api/pieces.html#delete-api-v1-piece-name-id)
endpoint.
For example, you can remove the clhj5wwoi0031bwffh65df6ga:en:published
article through the DELETE
request below:
http://localhost:3000/api/v1/article/clhj5wwoi0031bwffh65df6ga:en:published
Other APIs
In addition to the piece type REST API, Apostrophe also offers:
- Page type REST API: provides endpoints for creating, reading, updating, and deleting page objects. It requires authentication and is useful for programmatically managing pages within an Apostrophe site.
- Media API: exposes endpoints to perform CRUD operations on images, videos, and files. This allows you to upload new media files and retrieve, replace, and download existing ones. With Apostrophe, the headless possibilities are endless!
Conclusion
In this article, we looked at Apostrophe as a headless CMS, what its content APIs offer, and how to access them. In detail, Apostrophe is a CMS and website builder that also has headless capabilities. This makes it an extremely flexible tool.
Following this step-by-step tutorial, you learned how to use Apostrophe as a headless CMS, explore its API, and retrieve or publish content. As proven here, Apostrophe allows you to create a complete headless CMS with just a few lines of code.
Posted on June 16, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.