Spina CMS
Spina Academy
Home Guides

Configuring a theme

The first thing you do after creating a new Spina app is configure your theme.

The Spina installer generates an initializer in config/initalizers/themes/default.rb (or demo.rb if you chose that theme during installation). The initializer defines your theme using the following configurable keys:
  • Parts
  • View templates
  • Custom pages
  • Resources
  • Navigations
  • Layout parts
  • Plugins


Parts are the heart of Spina's content model. All page content is made up of these parts. Spina comes with a great set of parts that offer a lot of flexibility. All included parts are POROs (Plain Old Ruby Objects) that include the AttrJson::Model module. All content in Spina is stored as JSON and AttrJson enables that.

Adding your own custom parts is easy, but rarely needed. Make sure your custom parts can be stored as JSON and you're good to go.

In your theme configuration, put all parts that you're going to be using in the theme.parts array. We will reference those parts later.

theme.parts = [
  {name: 'text', title: "Body", part_type: "Spina::Parts::Text"},
  {name: 'image', title: "Image", part_type: "Spina::Parts::Image"}
Reference the docs to learn about all configuration options for the included parts.

View templates

Each page in Spina has a view template which defines which parts are available to that page. This way it's super easy to only include parts a page needs and leave out the rest.

theme.view_templates = [
  {name: 'homepage', title: 'Homepage', parts: %w(text)}, 
  {name: 'show', title: 'Page', description: 'Default page template', parts: %w(image text)}
The view template name here matches the actual view template living in app/views/[your_theme]/pages/. The description key is used to show the end-user what a view template can be used for. Adding a description to your view templates is optional, but recommended for usability.

Custom pages

Some pages are more special than other pages. The most obvious example is your homepage. Pages defined in theme.custom_pages are generated automatically when setting up your website and can be referenced by their name.

theme.custom_pages = [
  {name: 'homepage', title: 'Homepage', deletable: false, view_template: 'homepage'}
In this example we've made sure the homepage is not deletable (a pretty good default) and we've made sure that page uses the homepage view template. When a non-deletable custom page uses a particular view template, that view template will be unavailable to other pages. It wouldn't make sense for users to create additional homepages for the same website for example.


Very simple websites (like a personal website with 5 pages) can simply render all pages in a list to act as navigation. Most websites however, need a bit more control over what gets rendered and in what order. You can define multiple navigations for your theme. You could have a primary navigation for your header and another one for your footer for example. 

theme.navigations = [
  {name: 'main', label: 'Main navigation'},
  {name: 'footer', label: 'Footer navigation'},
Adding, removing and sorting entries in a navigation happens in Spina's UI, you don't have to do that in your theme config file.

Layout parts

Pages have content, divided into parts. Sometimes, you want to edit content on your website that doesn't really belong to one page, but to the entire layout instead. Things like taglines, copyright notices or USPs. You can define those in theme.layout_parts.

theme.layout_parts = ["copyright", "usps"]
You only have to set the names of parts you want to use. Make sure you only add parts that you've defined in theme.parts. Make sure that you've defined these parts in theme.parts before using them in theme.layout_parts.


Resources are a very powerful tool to organise pages in Spina. Think of them like separate collections of pages. Say for example you want to manage articles (like the one you're reading right now), we can create a resource called articles.

theme.resources = [
  {name: 'articles', label: "Articles", view_template: "article", slug: "articles"}
In Spina's UI you now have the ability to create articles in the Articles collection. Getting all articles for your frontend is now very easy:
Spina::Resource.find_by(name: "articles").pages
Pages in resources are even sorted automatically. In Spina's UI you can switch between a number of different sorting options, including manual sorting.


If you're using Spina plugins you can enable those for your theme by referencing them in theme.plugins

theme.plugins = ['reviews']
You don't have to do this though, all available plugins are enabled by default.