Add ButterCMS NPM module as a dependency to your existing React Native project.

If you plan to use this project directly, simply execute below commands to get going:

npm i
npm run start

These commands will install the required dependencies for the project and start it using the Expo CLI.

ButterCMS is designed to be easy to integrate into your existing React Native project. If you are starting from scratch, check out this React Native Starter that you can use to instantly launch a React Native app that's fully integrated with ButterCMS.

https://github.com/ButterCMS/buttercms-react-native

Add your API token to butter-client.js file:

# ...
  const butter = Butter('<your key>')
# ...

Import ButterCMS client in your JS/TS file:

import Butter from 'buttercms'

const butter = Butter('<your key>')

export default butter

You can then test ButterCMS client by, for example, fetching all of your posts:

butter.post.list({page:1, page_size: 10});

This will fetch you up to 10 blog posts that you would have stored in your ButterCMS account.

Contents

Headless CMS

ButterCMS is a headless CMS that lets you manage content using our dashboard and integrate it into your tech stack of choice with our content APIs. You can use ButterCMS for new projects as well as add it to existing codebases.

If you're familiar with Wordpress, see how ButterCMS compares to WordPress.

ButterCMS provides a user-friendly UI for managing marketing sites, blogging, and custom content scenarios. We can be used for SEO landing pages, customer case studies, company news & updates, events + webinar pages, education center, location pages, knowledgebases, and more.

We are different from a traditional CMS like Drupal or Wordpress in that we're not a large piece of software you need to download, host, customize, and maintain. Instead we provide easy to consume, performant content API's that you add to your application.

For example, if you wanted to enable a non-technical person to be able to add customer case study pages to your marketing site, you might create a Case Study Page Type to represent these pages. The non-technical person would be able to manage these pages from our dashboard and the JSON API output would look something like this:

{  
  "data": {
    "slug": "acme-co-case-study",
    "page_type": "case_study",
    "name": "Case Study",
    "fields": {
      "seo_title": "Acme Co Customer Case Study",
      "seo_description": "Acme Co saved 200% on Anvil costs with ButterCMS",
      "title": "Acme Co loves ButterCMS",
      "body": "<p>We've been able to make anvils faster than ever before! - Chief Anvil Maker</p>"
    }
  }
}

Use Postman to experiment

Postman is a great tool for experimenting with our API. We wrote a post about it here. Once you've installed Postman, click this button to quickly add our end point Collection to your Postman.

Run in Postman

Write API

We have a Write / POST API that allows you to programmatically create content. This can enable many powerful use cases and allow you to scale your content faster than ever.

Refer to our Write API Documentation to learn more.

Our Write API is available in our Enterprise plan and you will need to use a write-enabled token which is provided on request. Just contact us via email or livechat to get yours.

Webhooks

Webhooks are a powerful feature that allow you to notify your internal systems whenever content in ButterCMS has changed. You can learn more about Webhooks in this blog post.

Image Transformation

ButterCMS has integrated with a rich image transformation API called Filestack. This allows you to modify your uploaded images in dozens of ways. Everything from resizing, cropping, effects, filters, applying watermarks and more. Check out Filestack full documentation for more detail.

After you upload an image to ButterCMS, it's stored on our CDN. To create a thumbnail, here's an example:

Original URL = https://cdn.buttercms.com/zjypya5tRny63LqhHQrv

Thumbnail URL = https://fs.buttercms.com/resize=width:200,height:200/zjypya5tRny63LqhHQrv

Resizing is just one of the many different transformations you can do to your images. Refer to the Filestack docs for full details.

Localization

ButterCMS has full support for localization of your content. Locale names and keys are completely customizable and there's no limit to the number of locales you can have. View our API Reference to learn how to query by locale.

Roles and Permissions

To give your team maximum control over what your users can do, your ButterCMS account comes with three roles by default:

  • Admin - can do everything on an account. You'll want to use this for your developers as they deal with the content configuration that is used within your project's code.
  • Publisher - can edit, publish and delete content, but cannot manage users or configure content schemas.
  • Author - can create and edit draft content (Blog Posts, Pages, Collections) but cannot publish content live to your site.

Custom built roles are available in our Enterprise plan. Chat with us to discuss Enterprise options.

Manage Multiple Environments

ButterCMS Multisite allows you to manage multiple websites and multiple environments from one place. You can get an admin level view and quickly switch between your ButterCMS instances.

From the Environment dashboard you can quickly switch between your different ButterCMS environments. In the example below, Elon is currently logged into Production and can switch into Staging, Dev, or QA in one-click

Multiple Environments

Multiple Environments are available in our Enterprise plan. Just contact us via email or livechat to get yours.

Environment Data Migration + Workflow

Migrations Overview

Using multiple environments is a development best practice for creating new content experiences. Working in a non-production environment helps separate experimental changes so you can safely work without accidentally impacting your production application.

ButterCMS Migrations make migrating configuration data across your environments dead simple. Simply create a Migration from a test environment that specifies what you want to migrate and to which environment. For example, let's say we are working on creating a new FAQ section to our site, so we've developed a FAQ Page Type in our Dev environment. Now we are ready to move it to our Staging environment, simply create a Migration:

Migrations

Workflow

Just like in any development system, you should always follow the same flow in terms of which environment you create schema changes and proprogate up from.

For example, never make configuration changes directly in your Production environment. Instead make changes in your Dev environment and proprogate upward from there:

Migration Workflow

If you have a Dev, Stage, and Prod ButterCMS environments, you should always make configuration changes starting in your development environment. Once they are in a steady state, create a Migration to copy it into Stage and repeat. Test in Stage and create a final Migration to copy from Stage into Production.

Note that "Dev, Stage, Prod" is just an example. You can have any number of environments configured exactly how you want in Butter.

Avoid having to migrate content across environments

Avoid setting up a publishing workflow of having to migrate content across environments. A quick note on migrating configuration data versus content across ButterCMS environments. Configuration data (Page Types and Collections) in Butter is akin to a schema for a database. They are distinct from the content (data in a database). We recommend using environments for Migrating schema only. For example, testing out launching a new PageType or Collection or making changes to an existing one. Since this impacts the structure of the JSON from our API, you will want to test this in coordination with code changes in your application to display this new content. You can do this safely via ButterCMS environments and migrate across environments using our schema Migration feature..

For content migrations, migrating content across environments can become a complex + heavy process for your content editors. You can avoid this and have your editors only work in your production ButterCMS environment to manage and preview content changes.

To simplify the workflow for your editors, we support draft versions of content and previewing of that content in your Production ButterCMS instance. This allows editors to create content once, preview it on your staging/other environment, then once approved simply click a button and its published.

Technically the way this works is your staging environment would fetch content from your Production ButterCMS instance but it would append "?preview=1" to the API calls to fetch the draft content and display it on your staging environment. You can read more about this preview capability in our API docs here: https://buttercms.com/docs/api/

To ensure only the appropriate people are actually publishing content to Production, we have Roles and Permissions to restriction who is allowed to do that. So you would have users with the “Author” permission on your Production ButterCMS environment.

How to handle References

ButterCMS has a powerful feature called References which allows you to create relationships between your content types. In database terminology, this is like a foreign key from one table to another. Here's how to handle this when migrating:

  • PageTypeA has Reference to PageTypeB
  • Migrate PageTypeB first
  • Then migrate PageTypeA

If you have any questions chat with us and we're happy to help.

Manage Multiple Websites

Being able to manage multiple environments is great for a large project but what about massive projects where you need to manage multiple sites AND multiple environments? For instance if you're an Enterprise with several sub-branded websites that you want to be able to manage, this allows you to do that. Continuing from the example above, let's say Elon wanted to expand using Butter beyond just Tesla to include SpaceX and The Boring Company as well.

Our dashboard easily scales to meet this need. Now when Elon visits the multisite dashboard, he will see this:

Multiple Environments

Multiple Websites and Environments are available in our Enterprise plan. Just contact us via email or livechat to get yours.

Table of Contents

Introduction

Quickly launch a new marketing site or add CMS-powered pages to your existing site using our Pages. To create dynamic landing pages be sure to check out Components.

Create a Single Page

GET https://api.buttercms.com/v2/pages/*/?auth_token=your_token

Adding a CMS-powered page to your app involves three easy steps:

  1. Create the Page structure
  2. Populate the content
  3. Integrate into your application

If you need help after reading this, contact us via email or livechat.

Create the Page Structure

Create a new Page and define it's structure using our Page Builder. Let's create an example homepage.

PagesNewSinglePage

Populate the Content

Then populate our new page with content. In the next step, we'll call the ButterCMS API to retrieve this content from our app.

PagesNewSinglePageContent

Integrate into your application

With your homepage defined, the ButterCMS Pages API will return it in JSON format like this:

{
  "data": {
    "slug": "homepage",
    "name": "Homepage",
    "page_type": null,
    "fields": {
      "seo_title": "Anvils and Dynamite | Acme Co",
      "headline": "Acme Co provides supplies to your favorite cartoon heroes.",
      "hero_image": "https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV",
      "call_to_action": "Buy Now",
      "customer_logos": [
        {
          "logo_image": "https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV"
        },
        {
          "logo_image": "https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV"
        }
      ]
    }
  }
}

To integrate this into your app, simply make a call to ButterCMS APIs using the ButterCMS client. Place this call in the componentDidMount hook:

home.js
import React from 'react'
import { Text,View,StyleSheet,Image,Button } from 'react-native';
import { Actions } from 'react-native-router-flux';
import butter from './butter-client'
import { TouchableOpacity } from 'react-native-gesture-handler';
export default class Home extends React.Component {
   state = {
      data: ''
   }
   async componentDidMount() {
      const resp = await butter.page.retrieve('*', 'home')
      console.log(resp.data);
      this.setState(resp.data)
   }
   render() {
      const { fields } = this.state.data
      const goToAbout = () => {
         Actions.about()
      }
      const goToBlog = () => {
         Actions.blog()
      }
      if (fields) {
         return (
         <View>
            <Text style={styles.heading}>{fields.headline}</Text>
            <Image style={styles.heroimage} source={{uri: fields.hero_image}}></Image>
            <View style={styles.horizontal}>
            <TouchableOpacity style={styles.button}>
            <Button title={fields.call_to_action} onPress={goToAbout}></Button>
            </TouchableOpacity>
            <TouchableOpacity style={styles.button}>
            <Button title="Blog" onPress={goToBlog}></Button>
            </TouchableOpacity>
            </View>
         </View>

         )
      } else {
         return (
            <View>
               <Text>Loading..</Text>
            </View>
         )
      }
   }
}
const styles=StyleSheet.create({
   horizontal:{
      flex:1,
      flexDirection:'row',
      alignItems:"center",
      justifyContent:"center"
   },
   heading: {
      fontSize:'2em',
      fontFamily:'Georgia',
      color: '#333333',
      paddingTop:'10px'
   },
   heroimage:{
      width:'100%',
      height:'150px',
      padding: '20px'
   },
   button:{
      margin:20
   }
})

That's it! If you browse to your homepage you'll see your homepage populated with the content you created in Butter.

Create multiple pages using Page Types

Overview Video

Let's say you want to add a set of customer case study pages to your marketing site. They all have the same structure but the content is different. Page Types are perfect for this scenario and involves three easy steps:

  1. Create the Page Type structure
  2. Populate the content
  3. Integrate into your application

If you need help after reading this, contact us via email or livechat.

Create the Page Type structure

Create a Page Type to represent your Customer Case Study pages:

PagesNewPageType1

After saving, return to the configuration page by clicking the gear icon:

PagesNewPageType2

Then click on Create Page Type and name it "Customer Case Study". This will allow us to reuse this field configuration across multiple customer case study pages:

PagesNewPageType3

Populate the Content

Then populate our new page with content. In the next step, we'll call the ButterCMS API to retrieve this content from our app.

PagesNewSinglePageContent

Integrate into your application

Get all page content of specific type. For instance, customers for the case study:

customers.js
import React from 'react'
import { Text, ScrollView,StyleSheet,Image,Button } from 'react-native'
import { Actions } from 'react-native-router-flux'
import butter from './butter-client'
import { TouchableOpacity } from 'react-native-gesture-handler'
import HTMLView from 'react-native-htmlview';
export default class CaseStudy extends React.Component {
   state = {
      data: ''
   }
   async componentDidMount() {
      const resp = await butter.page.list('customer_case_study')
      this.setState(resp.data)
      console.log(resp.data);
   }
   render() {
      const { data } = this.state
      const goToHome = () => {
         Actions.home()
      }
      if (data) {
         return (
            <ScrollView style={{padding:20}}>
               {data.map(page =>
                  <ScrollView style={styles.post} key={page.slug}>
                     <Text style={styles.heading}>{page.fields.seo_title}</Text>
                     <Image style={styles.logo} source={{ uri: page.fields.customer_logo }} />
                     <HTMLView value={page.fields.testimonial}></HTMLView>
                  </ScrollView>
               )}
               <TouchableOpacity style={styles.button}>
                  <Button title="Back to Home" onPress={goToHome}></Button>
               </TouchableOpacity>

            </ScrollView>

         )
      } else {
         return (
            <ScrollView>
               <Text>Loading..</Text>
            </ScrollView>
         )
      }

   }
}
const styles = StyleSheet.create({
   post:{
      borderWidth:'1px',
      borderStyle:'solid',
      borderColor:'black',
      padding:20
   },
   vertical: {
      flex: 1,
      flexDirection: 'column',
      alignItems: "center",
      justifyContent: "center"
   },
   heading: {
      fontSize: '2em',
      fontFamily: 'Georgia',
      color: '#333333',
      paddingTop: '10px'
   },
   logo: {
      width: '90vw',
      height: '150px',
      alignItems:"center",
      flex:1,
      flexDirection:"column",
      justifyContent:"center"
   },
   content: {
      height:'100px',
      width:'100%'
   }
})

That's it! Any case study you create Butter dashboard will now immediately show in your app.

If you need help after reading this, contact us via email or livechat.

Table of Contents

Introduction

Learn how to quickly build a CMS-powered blog with React Native. To get started even quicker, here's a set of sample blog templates you can use.

If you need help after reading this, contact us via email or livechat.

Install SDK

If you haven't already, you'll want to install our SDK to make querying your content from our API into your app even easier. Once you've done that, you're ready to begin setting up your blog.

Displaying posts

To display posts we create a simple /blog route in our app and fetch blog posts from the Butter API. See our API reference for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination.

To retrieve the blog posts using ButterCMS client, you can use the function butter.post.list({})

bloghome.js
import React from 'react'
import { Text, ScrollView,StyleSheet,Image,Button } from 'react-native'
import { Actions } from 'react-native-router-flux'
import butter from './butter-client'
import { TouchableOpacity } from 'react-native-gesture-handler'
import HTMLView from 'react-native-htmlview';
export default class Blog extends React.Component {
    state = {
        data: ''
     }
    async componentDidMount() {
        const { match } = this.props;
        let page = (match && match.params.page) || 1;
        const resp = await butter.post.list({ page: page, page_size: 10 })
        this.setState(resp.data)
        console.log(resp.data);
    }
    render() {
        const { data } = this.state
        const goToHome = () => {
            Actions.home()
        }
        const goToPost = (post)=>{
            Actions.post({slug:post});
        }
        const goToCategories=()=>{
            Actions.category();
        }
        if (data) {
            return (
                <ScrollView style={{ padding: 20,backgroundColor:'#eeeeee' }}>
                    {data.map(post =>
                        <TouchableOpacity style={styles.post} key={post.slug} onPress={()=>goToPost(post.url)}>
                            <Text style={styles.heading}>{post.title}</Text>
                            <Image style={styles.logo} source={{ uri: post.featured_image }} />
                            <HTMLView value={post.summary}></HTMLView>
                        </TouchableOpacity>
                    )}
                    <TouchableOpacity style={styles.button}>
                        <Button title="Back to Home" onPress={goToHome}></Button>
                        <Button title="All categories" onPress={goToCategories}></Button>
                    </TouchableOpacity>
                    
                    

                </ScrollView>

            )
        } else {
            return (
                <ScrollView>
                    <Text>Loading..</Text>
                </ScrollView>
            )
        }
    }

}
const styles = StyleSheet.create({
    post:{
       borderWidth:'1px',
       borderStyle:'solid',
       borderColor:'black',
       padding:20,
       margin:20
    },
    vertical: {
       flex: 1,
       flexDirection: 'column',
       alignItems: "center",
       justifyContent: "center"
    },
    heading: {
       fontSize: '2em',
       fontFamily: 'Georgia',
       color: '#333333',
       paddingTop: '10px'
    },
    logo: {
       width: '90vw',
       height: '150px',
       alignItems:"center",
       flex:1,
       flexDirection:"column",
       justifyContent:"center"
    },
    content: {
       height:'100px',
       width:'100%'
    }
 })

To display a complete post, you can use the butter.post.retrieve(<url>) method. See a full list of available post properties in our API reference.

blogpost.js
import React from 'react'
import { Text, ScrollView, StyleSheet, Image, Button } from 'react-native'
import { Actions } from 'react-native-router-flux'
import butter from './butter-client'
import { TouchableOpacity } from 'react-native-gesture-handler'
import HTMLView from 'react-native-htmlview';
export default class Post extends React.Component {
    state = {
        data: ''
    }
    async componentDidMount() {
        const { slug } = this.props;
        const resp = await butter.post.retrieve(slug)
        console.log('New State: ',resp.data);
        this.setState(resp.data)
    }
    render() {
        const post = this.state.data
        const goToHome = () => {
            Actions.home()
        }
        if (post) {
            return (
                <ScrollView style={{ padding: 20 }}>
                    <Text style={styles.heading}>{post.title}</Text>
                    <HTMLView value={post.body} ></HTMLView>
                    <TouchableOpacity style={styles.button}>
                        <Button title="Back to Home" onPress={goToHome}></Button>
                    </TouchableOpacity>
                </ScrollView>
            )
        } else {
            return (
                <ScrollView>
                    <Text>Loading..</Text>
                </ScrollView>
            )
        }
    }

}
const styles = StyleSheet.create({
    post:{
        borderWidth:'1px',
        borderStyle:'solid',
        borderColor:'black',
        padding:20
     },
    vertical: {
        flex: 1,
        flexDirection: 'column',
        alignItems: "center",
        justifyContent: "center"
    },
    heading: {
        fontSize: '2em',
        fontFamily: 'Georgia',
        color: '#333333',
        paddingTop: '10px'
    },
    logo: {
        width: '90vw',
        height: '150px',
        alignItems: "center",
        flex: 1,
        flexDirection: "column",
        justifyContent: "center"
    },
    content: {
        height: '100px',
        width: '100%'
    }
})

Previewing Posts

Butter is a headless CMS, which means the design, layout, and general look & feel of your blog is controlled by your own application. As you've seen above, we return your blog content as JSON data, which you then inject into your own templates. In other words, your blog templates are just another set of templates in your app and customizing how your blog looks is the same workflow as any other page in your app. A huge benefit to this is that your blog instantly utilizes all of your existing brand CSS styling so it looks great and visually matches the rest of your app.

Because your app controls the design of your blog, Butter utilizes it to generate live previews for your content editors when they want to preview a blog post before they publish it.

Click here to configure your Blog Preview URL

To setup previewing you will need to tell Butter what your Blog's base preview URL is. i.e.:

https://yoursite.com/blog/

Once that's defined, when you preview a blog post, Butter will append the blog post slug to that preview URL and take you to:

https://yoursite.com/blog/blog-post-slug

To provide a great content editing experience, we highly recommend setting your preview URL.

Categories, Tags, and Authors

Use Butter's APIs for categories, tags, and authors to feature and filter content on your blog:

Categories

category.js
import React from 'react'
import { Text, ScrollView, StyleSheet, Image, Button } from 'react-native'
import { Actions } from 'react-native-router-flux'
import butter from './butter-client'
import { TouchableOpacity } from 'react-native-gesture-handler'
import HTMLView from 'react-native-htmlview';
export default class Category extends React.Component {
    state = {
        data: ''
    }
    receivedSlug = false;
    async componentDidMount() {
        const { slug } = this.props;
        let resp = {};
        console.log('Slug: ', slug);
        if (slug != undefined) {
            resp = await butter.post.list({
                category_slug: slug
            });
            this.receivedSlug = true;
        } else {
            resp = await butter.category.list()
        }
        this.setState(resp.data)
        console.log(resp.data);
    }
    
    render() {
        const { data } = this.state
        const goToHome = () => {
            Actions.home()
        }
        const goToCategory = (slug) => {
            Actions.category({ slug: slug });
        }
        const goToPost = (post)=>{
            Actions.post({slug:post});
        }
        if (data) {
            if (this.receivedSlug) {
                return (
                    <ScrollView style={{ backgroundColor: '#eeeeee' }}>
                        <Text style={styles.heading}>Posts</Text>
                        {data.recent_posts.map(post =>
                            <TouchableOpacity style={styles.post} key={post.slug} onPress={() => goToPost(post.slug)}>
                                <Text style={styles.heading}>{post.title}</Text>
                                <Image style={styles.logo} source={{ uri: post.featured_image }} />
                                <HTMLView value={post.summary}></HTMLView>
                            </TouchableOpacity>
                        )}
                        <TouchableOpacity style={styles.button}>
                            <Button title="Back to Home" onPress={goToHome}></Button>
                        </TouchableOpacity>

                    </ScrollView>
                )
            } else {
                return (
                    <ScrollView style={{ padding: 20, backgroundColor: '#eeeeee' }}>
                        <Text style={styles.heading}>Categories</Text>
                        {data.map(category =>
                            <TouchableOpacity style={styles.post} key={category.slug} onPress={() => goToCategory(category.slug)}>
                                <Text style={styles.heading}>{category.name}</Text>
                            </TouchableOpacity>
                        )}
                        <TouchableOpacity style={styles.button}>
                            <Button title="Back to Home" onPress={goToHome}></Button>
                        </TouchableOpacity>

                    </ScrollView>

                )
            }

        } else {
            return (
                <ScrollView>
                    <Text>Loading..</Text>
                </ScrollView>
            )
        }
    }

}
const styles = StyleSheet.create({
    post: {
        borderWidth: '1px',
        borderStyle: 'solid',
        borderColor: 'black',
        padding: 20,
        margin: 20
    },
    vertical: {
        flex: 1,
        flexDirection: 'column',
        alignItems: "center",
        justifyContent: "center"
    },
    heading: {
        fontSize: '2em',
        fontFamily: 'Georgia',
        color: '#333333',
        paddingTop: '10px'
    },
    logo: {
        width: '90vw',
        height: '150px',
        alignItems: "center",
        flex: 1,
        flexDirection: "column",
        justifyContent: "center"
    },
    content: {
        height: '100px',
        width: '80%'
    }
})

Comments

Butter doesn't provide an API for comments due to the excellent existing options that integrate easily. Two popular services we recommend are:

Both products are free, include moderation capabilities, and give your audience a familiar commenting experience. They can also provide some additional distribution for your content since users in their networks can see when people comment on your posts. For a minimalist alternative to Disqus, check out RemarkBox or for an open-source option, Isso.

Social Sharing

To maximize sharing of your content, we recommend using a free tool called AddThis.

They provide an attractive and easy to integrate social sharing widget that you can add to your website.

Social Share Buttons

CSS

Butter integrates into your front-end so you have complete control over the design of your blog. Use the following CSS as boilerplate for post content styling.

.post-container {
          h1, h2, h3, h4, h5 {
            font-weight: 600;
            margin-bottom: 1em;
            margin-top: 1.5em;
          }

          ul, ol {
            margin-bottom: 1.25em;

            li {
              margin-bottom: 0.25em;
            }
          }

          p {
            font-family: Georgia, Cambria, "Times New Roman", Times, serif;
            font-size: 1.25em;
            line-height: 1.58;
            margin-bottom: 1.25em;
            font-weight: 400;
            letter-spacing: -.003em;
          }

          /* Responsive default image width */
          img {
            max-width: 100%;
            height: auto;
          }

          /* Responsive floating */
          @media only screen and (min-width: 720px)  {
            .butter-float-left {
              float: left;
              margin: 0px 10px 10px 0px;
            }

            .butter-float-right {
              float: right;
              margin: 0px 0px 10px 10px;
            }
          }

          /* Image caption */
          figcaption {
            font-style: italic;
            text-align: center;
            color: #ccc;
          }

          p code {
            padding: 2px 4px;
            font-size: 90%;
            color: #c7254e;
            background-color: #f9f2f4;
            border-radius: 4px;
            font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
          }

          pre {
            display: block;
            padding: 1em;
            margin: 0 0 2em;
            font-size: 1em;
            line-height: 1.4;
            word-break: break-all;
            word-wrap: break-word;
            color: #333333;
            background-color: #f5f5f5;
            font-family: Menlo, Monaco,Consolas, "Courier New", monospace;
          }
        }
        

Migration

To import content from another platform like WordPress or Medium, send us an email.

Dynamic landing pages using Components

Components enable your marketers to compose flexible page layouts and easily reorder those layouts.

The above examples use Pages with fairly simple content models. Simple is great, especially when you're looking to create a lot of pages with the exact same structure and layout. However, if your marketing team needs to create a wide array landing pages with of differing layouts, you'll love Components.

There are two types of these fields when modeling your Page: Component and Component Picker.

Component

Seo Component

A Component field represents a single Component. A Component is a nice way to group related fields of a Page together. For example, configuring a SEO Component on your Page is a great idea to give your marketers the control they need over SEO and social sharing meta tags.

Here's how the Component looks to marketers when they are editing the content of the page:

Seo Component Marketer View

And the content for a Component is serialized as you would expect, an object within the larger Page fields object.

{
  "data": {
    "slug": "homepage",
    "fields": {
      "seo": {
        "seo_title": "...",
        "meta_description": "...",
        "opengraph_title": "...",
        "opengraph_image": "https://cdn.buttercms.com/..."
      }
    }
  }
}

Component Picker

Component Picker

A Component Picker defines a palette of Components your marketer can use when composing a page. For example, above is a Component Picker named "Sections" (to represent horizontal sections of a page) with two Components.

Component Picker Modal

This allows your marketer to compose a new page using any combination and ordering of Components. For example...

Your Homepage could be composed of these Components...

  • Hero
  • Call to Action
  • Key Benefit

While your Solutions page uses these Components:

  • Hero
  • Call to Action
  • Solution Details
  • Call to Action

Marketers can create limitless combinations of landing pages, all without needing to involve engineering.

Component Picker is serialized as an array of Components within the larger Page fields object. Each item in the array has fields and type properties. So a Component Picker named sections would look like this:

{
  "data": {
    "slug": "homepage",
    "fields": {
      "sections": [
        {
          "fields": {
            "headline": "...",
            "subheadline": "...",
            "call_to_action": "..."
          },
          "type": "hero"
        },
        {
          "fields": {
            "video_headline": "...",
            "video_link": "..."
          },
          "type": "product_video"
        }
      ]
    }
  }
}

Here's the logic to render a page template in your application using a Component Picker.


  //Pseudocode
  For each component in sections:
  if type is 'hero':
    render hero.html template with template data/context set to component.fields
  if type is 'product_video':
    render product_video.html template with template data/context set to component.fields

  // Code
  for component in page.fields.sections:
    if component.type == 'hero':
      render('components/hero.html', { data: component.fields })
    if component.type == 'product_video':
      render('components/product_video.html', { data: component.fields })

Collaborate with marketing when defining your Component Library

When using Components, collaborate with your marketing team to define a library of Components (i.e. SEO, Call to Action, Hero, Key Benefits, etc) that your team will use to compose pages. Once you've defined this Component library, your marketing team will have a good understanding of what Components are available to them as they launch new campaigns.

Previewing Pages

To give your marketers the ability to preview pages you will want to first configure the preview URL of your Page Type.

When your marketer clicks "Preview", they will get taken to that preview URL such as https://yoursite.com/the-page/?preview=1 with a preview=1 parameter appended.

Your application will then look for that preview=1 parameter and when detected, call the ButterCMS API with the same preview parameter. You can see this defined in our API docs when querying Pages.

Passing preview=1 to ButterCMS will cause the draft version of the Page content to be returned and thus displayed within your application, allowing your marketing team to see a full in-context preview of their draft changes.

Introduction

GET https://api.buttercms.com/v2/content/your_collection_key/?auth_token=your_token

Collections are tables of data to be referenced by Pages, extending the use cases that you can achieve with ButterCMS. Collections can also be queried from the API directly. We'll cover example use cases of both.

Several of these use cases involve References. References are a powerful field type you can add to Pages and Collections that allow you to create links between your content.

Use Cases

Tables of Related Content

There are many use cases for Collections. Another is using Collections as tables of related data which you can query directly. For example let's say you want to create a music site for musicians and you want to store data like Albums and Artists. Here's how you'd model that out using Collections in Butter and then query your content.

For code examples of making API calls to query a Collection directly, check out our Collections API Reference.

First create a Collection for Artists and configure it's properties to be Name, Headshot, and Genre.

Artists Collection

Then add a few Arists to the Collection.

Add Artists To Collection

You can query Collections directly via our API. Here's what the API JSON response looks like for your Artists Collection.

GET https://api.buttercms.com/v2/content/artists/

{
    "data": {
        "artists": [
            {
                "genre": "Rap",
                "name": "Drake",
                "headshot": "https://cdn.buttercms.com/V0mLWb47TaI9qmrRkzAC"
            },
            {
                "genre": "Country",
                "name": "Carrie Underwood",
                "headshot": "https://cdn.buttercms.com/FRToQffDSK2IE1O3fUuq"
            },
            {
                "genre": "Rock",
                "name": "Young the Giant",
                "headshot": "https://cdn.buttercms.com/jqVWtHf6T6acW8APrh3g"
            }
        ]
    }
}

With your Artists Collection created, you can now create a Collection for Albums which will include a Reference to our Artist Collection (every Album belongs to an Artist).

Albums Collection

Then add a few Albums.

Add Albums To Collection

Here's what the API JSON response looks like for your Albums Collection. Note artist is a Reference the Artists Collection above.

GET https://api.buttercms.com/v2/content/albums/

{
    "data": {
        "albums": [
            {
                "release_date": "2018-06-29T00:00:00",
                "artist": {
                    "genre": "Rap",
                    "name": "Drake",
                    "headshot": "https://cdn.buttercms.com/V0mLWb47TaI9qmrRkzAC"
                },
                "cover_art": "https://cdn.buttercms.com/uorkxsTQfit8N8uW6Im4",
                "album_name": "Scorpion"
            },
            {
                "release_date": "2018-09-14T00:00:00",
                "artist": {
                    "genre": "Country",
                    "name": "Carrie Underwood",
                    "headshot": "https://cdn.buttercms.com/FRToQffDSK2IE1O3fUuq"
                },
                "cover_art": "https://cdn.buttercms.com/3m0oGGyXQNCUnQke4Ps5",
                "album_name": "Cry Pretty"
            },
            {
                "release_date": "2018-10-12T00:00:00",
                "artist": {
                    "genre": "Rock",
                    "name": "Young the Giant",
                    "headshot": "https://cdn.buttercms.com/jqVWtHf6T6acW8APrh3g"
                },
                "cover_art": "https://cdn.buttercms.com/ThLT87lBSzyCkhivr64l",
                "album_name": "Mirror Master"
            }
        ]
    }
}

This use case demonstrates is how you can use Collections to create tables of data that Reference each other for complex content structures.

Page Facets to Group/Filter By

You can use Collections as Facets (filterable properties) for your Pages. The simpliest example would be to add Categories to your Pages. Let's say you have a recipe website for different cocktails and you want to add categories to better organize these cocktail pages for your customers.

Each cocktail Page has a name, image, and ingredients:

Sample Cocktail Page

Here's what the API JSON response looks like for your cocktail pages. You're going to enhance this by adding a Reference to a Category Collection.

GET https://api.buttercms.com/v2/pages/cocktails/

{
    "data": [
        {
            "slug": "old-fashioned",
            "fields": {
                "name": "Old Fashioned",
                "image": "https://cdn.buttercms.com/k4UHbZOuRhOMKw3Gys8s",
                "ingredients": "<p>1/2 tsp Sugar<br />3 dashes Angostura bitters<br />1 tsp Water<br />2 oz Bourbon</p>"
            }
        },
        {
            "slug": "martini",
            "fields": {
                "name": "Martini",
                "image": "https://cdn.buttercms.com/UKVn6r1RQSVyKoZIVeHU",
                "ingredients": "<p>2 oz. vodka</p>\n<p>1/2 oz. dry vermouth</p>\n<p>Shake ingredients with ice. Strain into a martini glass. Popular garnishes include a lemon twist and olives.</p>"
             }
        }
    ],
    meta": {
        "count": 2,
        "previous_page": null,
        "next_page": null
    }
}

To add a Category to your cocktail pages, first create a Category Collection and then configure your Collection data structure by adding Name and Slug properties to it.

Create Category Collection

Now you can add some cocktail categories to it like Martini, Old Fashioned, etc...

Adding Items To Collection

With your Collection in place, go back to your Cocktail Page Type and add a Reference field called "Category" to the Category Collection

Adding Reference Field To Collection

Now when editing your cocktail pages, you can now categorize your cocktails.

Select a Category

These categories of course also show up in your API response your cocktails:

GET https://api.buttercms.com/v2/pages/cocktails/

{
    "data": [
        {
            "slug": "old-fashioned",
            "fields": {
                "name": "Old Fashioned",
                "image": "https://cdn.buttercms.com/k4UHbZOuRhOMKw3Gys8s",
                "ingredients": "<p>1/2 tsp Sugar<br />3 dashes Angostura bitters<br />1 tsp Water<br />2 oz Bourbon</p>",
                "category": {
                    "name": "Old Fashioned",
                    "slug": "old-fashioned"
                }
            }
        },
        {
            "slug": "martini",
            "fields": {
                "name": "Martini",
                "image": "https://cdn.buttercms.com/UKVn6r1RQSVyKoZIVeHU",
                "ingredients": "<p>2 oz. vodka</p>\n<p>1/2 oz. dry vermouth</p>\n<p>Shake ingredients with ice. Strain into a martini glass. Popular garnishes include a lemon twist and olives.</p>",
                "category": {
                    "name": "Martini",
                    "slug": "martini"
                }
             }
        }
    ],
    meta": {
        "count": 2,
        "previous_page": null,
        "next_page": null
    }
}

Naturally, now that your pages have categories, you'll want to filter your pages by category. To do this just add fields.category.slug=martini to your API query.

GET https://api.buttercms.com/v2/pages/cocktails/?&fields.category.slug=martini

{
    "data": [
        {
            "slug": "martini",
            "fields": {
                "name": "Martini",
                "image": "https://cdn.buttercms.com/UKVn6r1RQSVyKoZIVeHU",
                "ingredients": "<p>2 oz. vodka</p>\n<p>1/2 oz. dry vermouth</p>\n<p>Shake ingredients with ice. Strain into a martini glass. Popular garnishes include a lemon twist and olives.</p>",
                "category": {
                    "name": "Martini",
                    "slug": "martini"
                }
             }
        }
    ],
    meta": {
        "count": 1,
        "previous_page": null,
        "next_page": null
    }
}

To take this example further, let's say you wanted multiple Facets to organize your cocktails by. You could set up multiple Collections such as:

  • Drink Types: Cider, Colada, Cosmo, ...
  • Spirits: Bourbon, Whiskey, Gin
  • Color: Brown, Yellow, Orange

Then you would add a corresponding Reference field to link each Collection to your cocktail Pages.

This use case demonstrates is how you can use Collections to add filterable Facets to your Pages.

Reusable Promotional Page Content

There are many use cases for Collections. Another is using Collections to store reusable promotional content that can be Referenced by multiple pages. A common example is customer testimonials. You can store all of your testimonials in a Collection, then Reference those testimonials from your Pages. Here's how you'd do that:

First let's assume your marketing site has some features Pages, each focusing on a particular feature of your product or service.

ButterCMS Feature Page

Here's what the API JSON response looks like for your feature page. You're going to enhance this by adding a Reference to a Testimonials Collection.

GET https://api.buttercms.com/v2/pages/*/full-cms-feature-page

{
    "data": {
        "slug": "full-cms-feature-page",
        "fields": {
            "headline": "Powerful CMS. Zero headache.",
            "hero_image": "https://cdn.buttercms.com/RB2R32WbSxqcanOXiHYA",
            "benefits": [
                {
                    "benefit": "SEO Landing Pages"
                },
                {
                    "benefit": "Customer Case Studies"
                },
                {
                    "benefit": "Company News & Updates"
                }
            ]
        }
    }
}

Create a Collection for testimonials, each having the name of the person, their quote, a headshot, and their title + company.

Testimonials Collection

Then add your customer testimonials to your Collection.

Add Testimonials To Collection

Then add a Reference field from your feature Pages to your Testimonials Collection.

Reference to Testimonials Collection

Now you can easily add multiple testimonials to display on your marketing Pages

Selecting Testimonials From Reference

The API JSON response for your feature page now includes the testimonials you just linked.

GET https://api.buttercms.com/v2/pages/*/full-cms-feature-page

{
    "data": {
        "slug": "full-cms-feature-page",
        "fields": {
            "headline": "Powerful CMS. Zero headache.",
            "hero_image": "https://cdn.buttercms.com/RB2R32WbSxqcanOXiHYA",
            "benefits": [
                {
                    "benefit": "SEO Landing Pages"
                },
                {
                    "benefit": "Customer Case Studies"
                },
                {
                    "benefit": "Company News & Updates"
                }
            ],
            "testimonials": [
                {
                    "name": "Maggie Summers",
                    "headshot": "https://cdn.buttercms.com/iAvdwmxmSjKVfpuqPjWJ",
                    "title_company": "Sasquatch",
                    "quote": "After several attempts at implementing an open source CMS into my app, I found Butter. It’s the best!"
                },
                {
                    "name": "Drew Johnson",
                    "headshot": "https://cdn.buttercms.com/q3z0MfVTJWso2JM5IXvg",
                    "title_company": "App Partner",
                    "quote": "Wordpress was too slow and impacting our business. Butter is more performant and a faster alternative. A no brainer."
                },
                {
                    "name": "BEAU O'HARA",
                    "headshot": "https://cdn.buttercms.com/vOWy5G1LRzm60NyRd3P0",
                    "title_company": "Anstar Products",
                    "quote": "I've tried other API-first CMS'. I liked their programs, but I got yours up and running the fastest"
                }
            ]
        }
    }
}

This use case demonstrates is how you can use Collections to store reusable promotional content that can be Referenced by multiple pages.

If you need help after reading this, contact us via email or livechat.