Boilerplate based on the default Sapper template. It allows setting up and kick-off your web project development within minutes. The boilerplate gathers:
- Svelte
- Contentful as Content Management System.
scss
syntax and Tailwindcss for styling.- Webpack
- Deployment in Now
Clone the project and dive in.
git clone git@github.com:boxfish-studio/svelte-contentful-boilerplate.git
cd svelte-contentful-boilerplate
Create Contentful environment file based on the given template
cp .env.example .env
Fill in the blank variables with your own Contentful space parameters
CONTENTFUL_SPACE=your_space_id
CONTENTFUL_ACCESS_TOKEN=your_space_delivery_token
CONTENTFUL_STAGING_TOKEN=your_space_preview_token
Install dependancies and run:
yarn
yarn dev
The site should be available at localhost:3000.
The project deploys with Now by default. There will be necessary to add the environment variables before using the scripts for deployment.
Environment Variables in Now
First of all, you need to install now and login with your account. Once it is done, you can define the environment variables in now
.
The needed secrets names can be found in now.json
:
{
"env": {
"CONTENTFUL_SPACE": "@contentful_space",
"CONTENTFUL_ACCESS_TOKEN": "@contentful_access_token",
"CONTENTFUL_STAGING_TOKEN": "@contentful_staging_token"
}
}
Once the environment variables are defined in now
you can execute the scripts for deployment.
There are two npm
scripts for deployment, one for production (npm run deploy-production
) and another one for "draft" mode (npm run deploy-draft
)``
The goal of using Svelte with Contentful is to be able to easily manage content and components. Therefore, there must be certain relation between Contentful models and Svelte components (i.e.: a component called Button
could be associated to the model Button
in Contentful).
On the other hand, a page from Contentful will be composed as:
// contentful.types.ts
export type Page = {
id: string
title: string
slug: string
components: Array<Component>
}
Where components
defines all components to be injected into the rendered src/routes/[slug].svelte
file.
On top of the standard Sapper template, Contentful and tailwindcss have been added.
This folder hosts the necessary files for the integration with Contentful
.
In this file, there is a class that contains the configuration for Contentful
client and some functions to retrieve data from the contentful API. some environment variables can be found in the constructor
of this class. These variables are necessary to connect your app with your contentful space. In order to do that, these variables are initialized in a .env
file that you can copy from .env.example
in the root folder. The API keys can be found in the contentful space settings.
In this file, you can find some types that will be used along with contentful models in the fetch functions of src/lib/contentful/contentful.ts
.
These two files are used to retrieve the pages (content_type: 'page') from contentful API.
The file src/routes/[slug].json.js
uses the created ContentfulApi
class to fetch the page content from Contentful
depending on the slug
introduced in any /:slug
route.
After fetching the data, the file src/routes/[slug].svelte
renders the page content based on that data by importing a component called ComponentSwitch
which will be the responsible for detecting the data type of page.components
and rendering each component in the correct way.
// ComponentSwitch.svelte
{#each page.components as componentData (componentData.id)}
<ComponentSwitch {componentData} />
{/each}
This component renders each "component" of page.components
based on the type
property of each one:
// contentful.types.ts
export type Component = {
id: string
type: string // based on this property (e.g.: 'button')
fields: Array<any>
}
To do that, this component should have an array of objects which represent the relationship between a Contentful Model and a Svelte Component. The id
property represents the Contentful Model type and the component
property represents the Svelte Component itself (notice that each component has to be imported to this file).
// ComponentSwitch.svelte
let COMPONENT_LIST = [
{ id: 'button', component: Button },
{ id: 'richTextBlock', component: RichTextBlock },
{ id: 'markdownBlock', component: MarkdownBlock }
]
Finally, this component finds out which component should render and renders it whith its properties.
This boilerplate uses both tailwindcss
and scss
.
To integrate them, there has been used two aproaches, one for general styles and another one for component based styles.
npm
scripts has been used to achieve this integration. You can check package.json
file to see all the existing scripts.
The script used to run the app in development mode is dev-draft
which throught other npm
scripts compiles all static/styles.scss
styles to a final file static/styles.css
and runs the app in "draft" mode to be able of fetching "draft" content from Contentful, which is the best aproach for development purposes. If you need to find out more information about how these npm
scripts work, this css-tricks article has been used as main reference.
This integration has been done following this tutorial: https://dev.to/sarioglu/using-svelte-with-tailwindcss-a-better-approach-47ph but with some differences due to that this tutorial is just for Svelte (without Sapper). The only difference is in the section "3-Make the integration", where there only has been created "postcss.config.js" (removing purgecss from it) and instead of changing "rollup.config.js" (which doesn't exists in Sapper), there has been modified the file "svelte.config.js":
// svelte.config.js
const sveltePreprocess = require('svelte-preprocess')
module.exports.preprocess = sveltePreprocess({
postcss: {
plugins: [require('tailwindcss'), require('autoprefixer')]
},
scss: true
})
Notice that to use scss
in components it is necessary write the style
tag with type="text/scss"
:
<!-- SomeComponent.svelte -->
<style type="text/scss">
/* scss and tailwind styling here... */
</style>