Documentation Index Fetch the complete documentation index at: https://buttercms.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This integration guide shows you how to how to update your existing project to:
install the ButterCMS package
instantiate ButterCMS
create components to fetch and display each of the three ButterCMS content types: Pages , Collections , and Blog Posts .
Starter project
Or, you can jump directly to the starter project below, which will allow you to clone, install, run, and deploy a fully working
starter project that’s integrated with content already inside of your ButterCMS account.
Gridsome Starter Project Hit the ground running with a pre-configured Gridsome + ButterCMS setup.
Installation
Add your API token to .env:
BUTTERCMS_API_TOKEN = your_api_token
Initialize the client
Create a reusable client module:
// src/lib/buttercms.js
const Butter = require ( 'buttercms' );
const butter = Butter ( process . env . BUTTERCMS_API_TOKEN );
module . exports = butter ;
For complete SDK documentation including all available methods and configuration options, see the JavaScript SDK Reference .
Pages
Gridsome loads external data at build time via gridsome.server.js. Add a custom data source to fetch ButterCMS pages:
// gridsome.server.js
const butter = require ( './src/lib/buttercms' );
module . exports = function ( api ) {
api . loadSource ( async ({ addCollection }) => {
const pagesCollection = addCollection ( 'ButterPage' );
try {
const response = await butter . page . list ( 'landing-page' , { page_size: 100 });
const pages = response . data . data ;
pages . forEach (( page ) => {
pagesCollection . addNode ({
id: page . slug ,
slug: page . slug ,
fields: page . fields ,
});
});
} catch ( error ) {
console . error ( 'Error fetching ButterCMS pages:' , error );
}
});
api . createPages ( async ({ createPage , graphql }) => {
const { data } = await graphql ( `
{
allButterPage {
edges {
node {
slug
}
}
}
}
` );
data . allButterPage . edges . forEach (({ node }) => {
createPage ({
path: node . slug === 'home' ? '/' : `/page/ ${ node . slug } ` ,
component: './src/templates/LandingPage.vue' ,
context: {
slug: node . slug ,
},
});
});
});
};
Create the page template:
<!-- src/templates/LandingPage.vue -->
< template >
< Layout >
< main v-if = " $page . butterPage " >
< h1 > {{ $page . butterPage . fields . headline }} </ h1 >
< p > {{ $page . butterPage . fields . subheadline }} </ p >
< img
v-if = " $page . butterPage . fields . hero_image "
: src = " $page . butterPage . fields . hero_image "
: alt = " $page . butterPage . fields . headline "
/>
< div v-html = " $page . butterPage . fields . body " / >
</ main >
</ Layout >
</ template >
< page-query >
query LandingPage($slug: String!) {
butterPage(slug: $slug) {
slug
fields {
headline
subheadline
hero_image
body
}
}
}
</ page-query >
< script >
export default {
metaInfo () {
const page = this . $page . butterPage ;
if ( ! page ) return {};
const seo = page . fields . seo || {};
return {
title: seo . title || page . fields . headline ,
meta: [
{ name: 'description' , content: seo . description },
],
};
} ,
} ;
</ script >
Collections
Add your collections to the Gridsome data store:
// gridsome.server.js (add inside api.loadSource)
const brandsCollection = addCollection ( 'ButterBrand' );
try {
const response = await butter . content . retrieve ([ 'brands' ]);
const brands = response . data . data . brands ;
brands . forEach (( brand , index ) => {
brandsCollection . addNode ({
id: String ( index ),
name: brand . name ,
logo: brand . logo ,
description: brand . description ,
});
});
} catch ( error ) {
console . error ( 'Error fetching ButterCMS brands:' , error );
}
Query and display collection items in a Vue component:
<!-- src/pages/Brands.vue -->
< template >
< Layout >
< main >
< h1 > Our Brands </ h1 >
< ul >
< li v-for = " brand in $page . allButterBrand . edges " : key = " brand . node . id " >
< img : src = " brand . node . logo " : alt = " brand . node . name " />
< h2 > {{ brand . node . name }} </ h2 >
< div v-html = " brand . node . description " / >
</ li >
</ ul >
</ main >
</ Layout >
</ template >
< page-query >
{
allButterBrand {
edges {
node {
id
name
logo
description
}
}
}
}
</ page-query >
Dynamic components
Component Renderer
<!-- src/components/ComponentRenderer.vue -->
< template >
< div >
< component
v-for = " ( item , index ) in components "
: key = " index "
: is = " componentMap [ item . type ] "
v-if = " componentMap [ item . type ] "
v-bind = " item . fields "
/>
</ div >
</ template >
< script >
import Hero from './Hero.vue' ;
import Features from './Features.vue' ;
import Testimonials from './Testimonials.vue' ;
import CTA from './CTA.vue' ;
export default {
props: {
components: {
type: Array ,
default : () => [],
},
} ,
data () {
return {
componentMap: {
hero: Hero ,
features: Features ,
testimonials: Testimonials ,
cta: CTA ,
},
};
} ,
} ;
</ script >
Example Component
<!-- src/components/Hero.vue -->
< template >
< section class = "hero" >
< h1 > {{ headline }} </ h1 >
< p > {{ subheadline }} </ p >
< a v-if = " button_label " : href = " button_url " class = "btn" > {{ button_label }} </ a >
< img v-if = " image " : src = " image " : alt = " headline " />
</ section >
</ template >
< script >
export default {
props: [ 'headline' , 'subheadline' , 'image' , 'button_label' , 'button_url' ] ,
} ;
</ script >
Using in templates
<!-- src/templates/ComponentPage.vue -->
< template >
< Layout >
< main v-if = " $page . butterPage " >
< ComponentRenderer : components = " $page . butterPage . fields . body " />
</ main >
</ Layout >
</ template >
< page-query >
query($slug: String!) {
butterPage(slug: $slug) {
slug
fields {
body {
type
fields {
headline
subheadline
image
button_label
button_url
}
}
}
}
}
</ page-query >
< script >
import ComponentRenderer from '~/components/ComponentRenderer.vue' ;
export default {
components: { ComponentRenderer } ,
} ;
</ script >
Blog
Add blog posts to the data store in gridsome.server.js:
// gridsome.server.js (add inside api.loadSource)
const postsCollection = addCollection ( 'ButterPost' );
try {
const response = await butter . post . list ({ page_size: 100 });
const posts = response . data . data ;
posts . forEach (( post ) => {
postsCollection . addNode ({
id: post . slug ,
slug: post . slug ,
title: post . title ,
summary: post . summary ,
body: post . body ,
published: post . published ,
featured_image: post . featured_image ,
author: post . author ,
});
});
} catch ( error ) {
console . error ( 'Error fetching ButterCMS posts:' , error );
}
// Create blog post pages
api . createPages ( async ({ createPage , graphql }) => {
const { data } = await graphql ( `
{
allButterPost {
edges {
node {
slug
}
}
}
}
` );
data . allButterPost . edges . forEach (({ node }) => {
createPage ({
path: `/blog/ ${ node . slug } ` ,
component: './src/templates/BlogPost.vue' ,
context: { slug: node . slug },
});
});
});
Blog Post List
Single Blog Post
<!-- src/pages/Blog.vue -->
< template >
< Layout >
< main >
< h1 > Blog </ h1 >
< ul >
< li v-for = " post in $page . allButterPost . edges " : key = " post . node . slug " >
< h2 >
< g-link : to = " `/blog/ ${ post . node . slug } ` " > {{ post . node . title }} </ g-link >
</ h2 >
< p v-html = " post . node . summary " / >
< span >
By {{ post . node . author . first_name }} {{ post . node . author . last_name }}
</ span >
</ li >
</ ul >
</ main >
</ Layout >
</ template >
< page-query >
{
allButterPost(sortBy: "published", order: DESC) {
edges {
node {
slug
title
summary
published
author {
first_name
last_name
}
}
}
}
}
</ page-query >
<!-- src/templates/BlogPost.vue -->
< template >
< Layout >
< article v-if = " $page . butterPost " >
< h1 > {{ $page . butterPost . title }} </ h1 >
< p >
By {{ $page . butterPost . author . first_name }} {{ $page . butterPost . author . last_name }}
on {{ formatDate ( $page . butterPost . published ) }}
</ p >
< img
v-if = " $page . butterPost . featured_image "
: src = " $page . butterPost . featured_image "
: alt = " $page . butterPost . title "
/>
< div v-html = " $page . butterPost . body " / >
< g-link to = "/blog" > Back to Posts </ g-link >
</ article >
</ Layout >
</ template >
< page-query >
query BlogPost($slug: String!) {
butterPost(slug: $slug) {
slug
title
body
published
featured_image
author {
first_name
last_name
}
}
}
</ page-query >
< script >
export default {
methods: {
formatDate ( dateStr ) {
return new Date ( dateStr ). toLocaleDateString ();
},
} ,
metaInfo () {
const post = this . $page . butterPost ;
if ( ! post ) return {};
return {
title: post . title ,
};
} ,
} ;
</ script >
Resources
Gridsome Starter Pre-configured starter project
JavaScript SDK Complete SDK reference
GitHub Repository View source code
Content API REST API documentation