Run this in your commandline:

npm install buttercms --save

Butter can also be loaded using a CDN:

<script src="https://cdnjs.buttercms.com/buttercms-1.1.1.min.js"></script>

The source code is available on Github.

If you'd like a full example project, check out our Vue.js project on Github.

Set your API token:

var butter = require('buttercms')('your_api_token');

Using ES6:

import Butter from 'buttercms';
export const butter = Butter('your_api_token');

Using CDN:

<script src="https://cdnjs.buttercms.com/buttercms-1.1.1.min.js"></script>

<script>
  var butter = Butter('your_api_token');
</script>

Import this file into any component you want to use ButterCMS. Then from the console run:

butter.post.list({page: 1, page_size: 10}).then(function(response) {
  console.log(response)
})

This API request fetches our blog posts. Your account comes with one example post which you'll see in the response. If you get a response it means you're now able to connect to our API.

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",
    "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 experiement

Postman is a great tool for experiementing 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

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.

Table of Contents

Introduction

Quickly launch a new marketing site or add CMS-powered pages to your existing site using our Pages.

Create a Single Page

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",
    "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, create a route that fetches content for the page:

This guide uses the vue-cli webpack template to take advantage of vue-router already being setup.

Open your code editor and create a file called buttercms.js in your src directory.

Note, if you don't have an existing project, you can create one like so:

vue init webpack buttercms-project
cd buttercms-project
npm i
npm i -S buttercms
npm run dev
vue-cli now has an option to run npm install for you. If you selected "Yes, use NPM" when initializing the project skip npm i

src/buttercms.js

import Butter from 'buttercms';
export const butter = Butter('your_api_token');

Update the routes in your app

router/index.js:

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    }
  ]
})

In components/Home.vue we define a getPage() method to get our particular homepage based on it's slug.

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'customer-page',
    data() {
      return {
        page: {
          fields: {}
        }
      }
    },
    methods: {
      getPage() {
        butter.page.retrieve('*', 'homepage')
          .then((res) => {
            console.log(res.data.data)
            this.page = res.data.data
          }).catch((res) => {
            console.log(res)
          })
      }
    },
    created() {
      this.getPage()
    }
  }
</script>

Display the results

<template>
  <div id="customer-page">
    <figure>
      <img :src="page.fields.hero_image">
    </figure>
    <h1>{{ page.fields.headline }}</h1>
    <button>{{ page.fields.call_to_action }}</button>

    <h3>Customers Love Us!</h3>
    <!-- Loop over customer logos -->
    <img v-for="logo in page.fields.customer_logos" :src="logo.logo_image">
</template>

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

With a case study defined, the ButterCMS Pages API will return it in JSON format like this:

{
    "data": {
        "slug": "acme-co",
        "fields": {
            "facebook_open_graph_title": "Acme Co loves ButterCMS",
            "seo_title": "Acme Co Customer Case Study",
            "headline": "Acme Co saved 200% on Anvil costs with ButterCMS",
            "testimonial": "<p>We've been able to make anvils faster than ever before! - <em>Chief Anvil Maker</em></p>\r\n<p><img src=\"https://cdn.buttercms.com/NiA3IIP3Ssurz5eNJ15a\" alt=\"\" caption=\"false\" width=\"249\" height=\"249\" /></p>",
            "customer_logo": "https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV",
        }
    }
}

This guide uses the vue-cli webpack template to take advantage of vue-router already being setup.

Open your code editor and create a file called buttercms.js in your src directory.

If you haven't already, create this file so you can import the butter sdk into your Vue components.

Note, if you don't have an existing project, you can create one like so:

vue init webpack buttercms-project
cd buttercms-project
npm i
npm i -S buttercms
npm run dev
vue-cli now has an option to run npm install for you. If you selected "Yes, use NPM" when initializing the project skip npm i

src/buttercms.js

import Butter from 'buttercms';
export const butter = Butter('your_api_token');

Update the routes in your app

router/index.js:

import Vue from 'vue'
import Router from 'vue-router'
import CustomersHome from '@/components/CustomersHome'
import CustomerPage from '@/components/CustomerPage'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/customers/',
      name: 'customers-home',
      component: CustomersHome
    },
    {
      path: '/customers/:slug',
      name: 'customer-page',
      component: CustomerPage
    }
  ]
})

Setup the Customers Page to list all our customers.

In components/CustomersHome.vue we define a getPages() method to get all customer pages

<script>
  // import ButterCMS from 
  import { butter } from '@/buttercms'
  export default {
    name: 'customers-home',
    data() {
      return {
        page_title: 'Customers',
        // Create array to hold the pages from ButterCMS API
        pages: []
      }
    },
    methods: {
      // Get List of Customer Pages
      getPages() {
        butter.page.list('customer_case_study')
          .then((res) => {
            // console.log(res.data.data) // Check the results in the console
            this.pages = res.data.data
          })
      }
    },
    created() {
      // Fire on page creation
      this.getPages()
    }
  }
</script>

Display the results

<template>
  <div id="customers-home">
    <h1>{{ page_title }}</h1>
    <div v-for="(page,index) in pages" :key="page.slug + '_' + index">
      <router-link :to="'/customers/' + page.slug">
        <div>
          <img :src="page.fields.customer_logo" alt="">
          <h2>{{ page.fields.headline }}</h2>
        </div>
      </router-link>
    </div>
  </div>
</template>
Quick syntax note: Vue.js provides special shorthands for two of the most often used directives in templates, v-bind and v-on. The code presented in this tutorial will use the shorthand. Learn more

Setup the Customer Page to view single customer

In components/CustomerPage.vue we define a getPage() method to get a particular page based on it's slug.

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'customer-page',
    data() {
      return {
        slug: this.$route.params.slug,
        page: {
          slug: '',
          fields: {}
        }
      }
    },
    methods: {
      getPage() {
        butter.page.retrieve('customer_case_study', this.slug)
          .then((res) => {
            console.log(res.data.data)
            this.page = res.data.data
          }).catch((res) => {
            console.log(res)
          })
      }
    },
    created() {
      this.getPage()
    }
  }
</script>

Display the result

<template>
  <div id="customer-page">
    <figure>
      <img :src="page.fields.customer_logo">
    </figure>
    <h1>{{ page.fields.headline }}</h1>
    <h3>Testimonials</h3>
    <div v-html="page.fields.testimonial"></div>
    <div v-html="page.fields.body"></div>
  </div>
</template>

That's it! We can now navigate to the Customer Page you created in your butter dashboard via the list of all Customer Pages or directly via url.

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

Table of Contents

Introduction

This guide uses Vue.js but Butter works with any client-side JavaScript framework including Angular and React.js. For a sample project, checkout this Vue.js Github Repo.

Content Fields are global pieces of content that can be managed by your team. They can be used for content that spans multiple pages (header, footer) or platforms (desktop, mobile). Each content field has unique ID for querying via our API. Let's see how you can use them to power a knowledge base. Again Content Fields are great for content that can appear in multiple places so this knowledge base could appear on your website and mobile app. This example will focus on your website.

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

Setup content fields

Let's suppose we want to add a CMS to a static FAQ page with a title and a list of questions with answers.

Making your content dynamic with Butter is a two-step process:

  1. Setup custom content fields in Butter
  2. Integrate the fields into your application

To setup custom content fields, first sign in to the Butter dashboard.

Create a new workspace or click on an existing one. Workspaces let you organize content fields in a friendly way for content editors and have no effect on development or the API. For example, a real-estate website might have a workspace called "Properties" and another called "About Page".

Once you're in a workspace click the button to create a new content field. Choose the "Object" type and name the field "FAQ Headline":

After saving, add another field but this time choose the "Collection" type and name the field FAQ Items:

On the next screen setup two properties for items in the collection:

Now go back to your workspace and update your heading and FAQ items.

Integrate your app

To display this dynamic content in our app, we fetch the fields with an API call and then reference them in our view. First, setup the route to your FAQ's page:

router/index.js:

import Vue from 'vue'
import Router from 'vue-router'

import FAQ from '@/components/FAQ'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/faq',
      name: 'faq',
      component: FAQ
    }
  ]
})

Then create components/FAQ.vue with a call to get the FAQ's from ButterCMS:

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'faq',
    data() {
      return {
        page_title: 'FAQ',
        faq_items: []
      }
    },
    methods: {
      getFaqs() {
        butter.content.retrieve(['faq_headline', 'faq_items'])
          .then((res) => {
            console.log(res.data.data)
            this.page_title = res.data.data.faq_headline
            this.faq_items = res.data.data.faq_items
          })
      }
    },
    created() {
      this.getFaqs()
    }
  }
</script>

Notice that we predefined page_title as 'FAQ' and then updated it with the API call to 'Frequently Asked Questions'. Now display the result:

<template>
  <div id="faq">
    <h1>{{ page_title }}</h1>
    <div v-for="(faq, index) in faq_items" :key="index">
      <p>{{ faq.question }}</p>
      <p>{{ faq.answer }}</p>
    </div>
  </div>
</template>

That's it! The values entered in the Butter dashboard will immediately update the content in our 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 Vue.js. Note Butter works with any client-side JavaScript framework including Angular and React.js. For a sample project, check out out this Vue.js Github Repo. 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.

Open your code editor and create a file called buttercms.js in your src directory.

If you haven't already, create this file so you can import the butter sdk into your Vue components.

src/buttercms.js

import Butter from 'buttercms';
export const butter = Butter('your_api_token');

Display posts

To display posts we create a simple /blog route (using vue-router) in our app and fetch blog posts from the Butter API, as well as a /blog/:slug route to handle individual posts. 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.

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.

router/index.js:

import Vue from 'vue'
import Router from 'vue-router'
import BlogHome from '@/components/BlogHome'
import BlogPost from '@/components/BlogPost'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/blog/',
      name: 'blog-home',
      component: BlogHome
    },
    {
      path: '/blog/:slug',
      name: 'blog-post',
      component: BlogPost
    }
  ]
})

Then create components/BlogHome.vue which will be your blog homepage that lists your most recent posts.

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'blog-home',
    data() {
      return {
        page_title: 'Blog',
        posts: []
      }
    },
    methods: {
      getPosts() {
        butter.post.list({
          page: 1,
          page_size: 10
        }).then((res) => {
          // console.log(res.data)
          this.posts = res.data.data
        })
      }
    },
    created() {
      this.getPosts()
    }
  }
</script>

Display the result

<template>
  <div id="blog-home">
      <h1>{{ page_title }}</h1>
      <!-- Create v-for and apply a key for Vue. Example is using a combination of the slug and index -->
      <div v-for="(post,index) in posts" :key="post.slug + '_' + index">
        <router-link :to="'/blog/' + post.slug">
          <article class="media">
            <figure>
              <!-- Bind results using a ':' -->
              <!-- Use a v-if/else if their is a featured_image -->
              <img v-if="post.featured_image" :src="post.featured_image" alt="">
              <img v-else src="http://via.placeholder.com/250x250" alt="">
            </figure>
            <h2>{{ post.title }}</h2>
            <p>{{ post.summary }}</p>
          </article>
        </router-link>
      </div>
  </div>
</template>

Now create components/BlogPost.vue which will be your Blog Post page to list a single post.

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'blog-post',
    data() {
      return {
        post: {}
      }
    },
    methods: {
      getPost() {
        butter.post.retrieve(this.$route.params.slug)
          .then((res) => {
            // console.log(res.data)
            this.post = res.data
          }).catch((res) => {
            console.log(res)
          })
      }
    },
    created() {
      this.getPost()
    }
  }
</script>

Display the results

<template>
  <div id="blog-post">
    <h1>{{ post.data.title }}</h1>
    <h4>{{ post.data.author.first_name }} {{ post.data.author.last_name }}</h4>
    <div v-html="post.data.body"></div>

    <router-link v-if="post.meta.previous_post" :to="/blog/ + post.meta.previous_post.slug" class="button">
      {{ post.meta.previous_post.title }}
    </router-link>
    <router-link v-if="post.meta.next_post" :to="/blog/ + post.meta.next_post.slug" class="button">
      {{ post.meta.next_post.title }}
    </router-link>
  </div>
</template>

Now our app is pulling all blog posts and we can navigate to individual posts.However, our next/previous post buttons are not working.

One thing to note when using routes with params is that when the user navigates from /blog/foo to /blog/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called.

Visit the Vue.js docs to learn more about Dynamic Route Matching

To fix this we need to simply watch the $route object and call getPost() when the route changes.

Updated script section in components/BlogPost.vue:

<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'blog-post',
    data() {
      return {
        post: {}
      }
    },
    methods: {
      getPost() {
        butter.post.retrieve(this.$route.params.slug)
          .then((res) => {
            // console.log(res.data)
            this.post = res.data
          }).catch((res) => {
            console.log(res)
          })
      }
    },
    watch: {
      $route(to, from) {
        this.getPost()
      }
    },
    created() {
      this.getPost()
    }
  }
</script>

Now our app has a working blog that can be updated easily in the ButterCMS dashboard.

Categories, Tags, and Authors

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

See our API reference for more information about these objects:

Here's an example of listing all categories and getting posts by category. Call these methods on the created() lifecycle hook:

methods: {
  ...
  getCategories() {
    butter.category.list()
      .then((res) => {
        console.log('List of Categories:')
        console.log(res.data.data)
      })
  },
  getPostsByCategory() {
    butter.category.retrieve('example-category', {
        include: 'recent_posts'
      })
      .then((res) => {
        console.log('Posts with specific category:')
        console.log(res)
      })
  }
},
created() {
  ...
  this.getCategories()
  this.getPostsByCategory()
}

RSS, Atom, and Sitemap

Butter generates RSS, Atom, and sitemap XML markup. To use these on your blog, return the generated XML from the Butter API with the proper content type headers.

Create a file to see an example of what you get back from the API.

components/RssAtomSitemap.vue

<template>
  <div id="rss">
    <div v-if="rss">
      <pre>
        
      </pre>
      <hr>
    </div>
    <div v-if="atom">
      <pre>
        
      </pre>
      <hr>
    </div>
    <div v-if="sitemap">
      <pre>
        
      </pre>
      <hr>
    </div>
  </div>
</template>
<script>
  import { butter } from '@/buttercms'
  export default {
    name: 'rss-atom-sitemap',
    data() {
      return {
        rss: '',
        atom: '',
        sitemap: ''
      }
    },
    methods: {
      getRss() {
        butter.feed.retrieve('rss').then((res) => {
          console.log(res.data.data)
          this.rss = res.data.data
        })
      },
      getAtom() {
        butter.feed.retrieve('atom').then((res) => {
          console.log(res.data.data)
          this.atom = res.data.data
        })
      },
      getSitemap() {
        butter.feed.retrieve('sitemap').then((res) => {
          console.log(res.data.data)
          this.sitemap = res.data.data
        })
      },
    },
    created() {
      this.getRss()
      this.getAtom()
      this.getSitemap()
    }
  }
</script>

Update your routes

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import RssAtomSitemap from '@/components/RssAtomSitemap'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/rss',
      name: 'rss',
      component: RssAtomSitemap
    },
  ]
})

Navigate to localhost:8080/rss

You can see ButterCMS passes back the entire xml need to create a feed or sitemap. So you need to create xml files your subscribers can link to in their RSS readers. To do this, you'll be utilizing our Webhooks that can POST change notifications to your app.

Setup to create feeds and sitemap

First, you'll need to setup up a listener url in your application or webhost that will trigger a rebuild/redeploy of your static site when it receives a POST request from our Webhook.

Then, setup a POST Webhook in the ButterCMS dashboard with the Event "Blog Post Create, Update, or Delete" and paste the listener url into Target URL field.

ButterCMS Webhooks

Create a basic webpack plugin

You can create plugin as part of your webpack build that to create the XML files and save them in the /dist folder.

Learn more about writing plugins for webpack

Add the plugin to the webpack base config file by requiring it at the top of the file and then adding/updating the plugins array after the output object.

build/webpack.base.conf.js

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
var BuildButterCmsXmlPlugin = require('./BuildButterCmsXmlPlugin')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  plugins: [
    new BuildButterCmsXmlPlugin()
  ],
  resolve: {
  ...

Create the plugin file in the build directory

build/BuildButterCmsXmlPlugin.js

let fs = require('fs')
let path = require('path')
let Butter = require('buttercms')

function BuildButterCmsXmlPlugin() {}

BuildButterCmsXmlPlugin.prototype.apply = function (compiler) {
  compiler.plugin('done', () => {
    const butter = Butter('your_api_token')

    function getRss() {
      var rss
      butter.feed.retrieve('rss').then((res) => {
        rss = res.data.data
        fs.writeFileSync(
          path.resolve('dist/rss.xml'),
          rss
        )
      })
    }

    function getAtom() {
      var atom
      butter.feed.retrieve('atom').then((res) => {
        atom = res.data.data
        fs.writeFileSync(
          path.resolve('dist/atom.xml'),
          atom
        )
      })
    }

    function getSitemap() {
      var sitemap
      butter.feed.retrieve('sitemap').then((res) => {
        sitemap = res.data.data
        fs.writeFileSync(
          path.resolve('dist/sitemap.xml'),
          sitemap
        )
      })
    }
    getRss()
    getAtom()
    getSitemap()
  })
}

module.exports = BuildButterCmsXmlPlugin

Now whenever you run npm run dev or npm run build you should see our feeds and sitemap XML's created in our /dist folder.

This means also that whenever the webhook makes a POST request to our host anytime you create, update or delete a post, our site is redeployed with updated feeds and sitemap.

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.

Get started now

Sign up with Google Sign up with Github
or