(Guide) How to Choose & Customize a Landing Page Template

Let’s say you’re the owner of a boutique soap store and you’re taking your business online. (Hey, in 2020, you wouldn’t be the only one.)

You’ve already got a simple website, but you wanna run promotions to really lather up some business. So, you get to work on your marketing campaign. You come up with an irresistible offer. You spend your lunch hours building an email list of existing and potential customers. You stay up late learning the basics of Google Ads. Then you start planning the landing page where you’ll send your campaign traffic.

With all the work you’ve already put in, you’re delighted to know you can save some time by starting with a landing page template. But when you go to choose one in your favorite builder (ahem), you don’t see any that look right for your business. There’s a template that seems like it’s meant for realtors, maybe. Another that’d be good for bakeries. But nothing for soap sellers like you. You’re stuck.

“Dangit, Unbounce. Where’re the soap landing pages?” — You, probably.

Not so fast, sudsy—you’re looking at this the wrong way. The idea here isn’t to find a landing page template that matches your business exactly. First and foremost, you want to choose a template that supports your campaign conversion goal. Everything else—your industry, your product or service, your branding—comes second. 

In this post, we’ll show you how to pick out the perfect template for your next marketing campaign. Then, we’ll show you how you can transform it into a custom-branded, high-converting masterpiece.

How to Choose a Template That Supports Your Conversion Goal

What’s a conversion goal, exactly?

Your conversion goal is the action you want visitors to take as a result of your marketing campaign. Maybe you want somebody to buy a product, like fancy soap. Or maybe you want them to sign up for a webinar about… I dunno, making fancy soap?

The point is that some landing page templates are better-suited to specific conversion goals than others. If you just want someone to buy a product, your landing page’s call to action is pretty straightforward. On the other hand, if you’re registering people for a webinar, you’re gonna need their name and email address (at least). That’ll mean a more complex call to action.

Which template is best for your conversion goal?

Broadly, landing page templates fall into one of two categories: click-through pages and lead generation pages. They’ve each got a distinct type of call to action meant to support a certain conversion goal. 

The page on the left is a click-through landing page, while the one on the right is a lead gen landing page.

Click-through landing pages prime visitors for the next step in their journey, like a checkout flow or sign-up page. Since the real ask comes wherever they end up after this page, the call to action here is simple—usually just a button. (“Buy Now” is a classic of this genre.)

On the other hand, lead generation landing pages use forms to capture visitor information that can be used later, like for promotional emails. These pages typically offer some kind of incentive (or “lead magnet”) for filling out the form—a downloadable ebook or webinar registration, for example.

What about the design of a template?

First, you need to decide whether your conversion goal requires a click-through or lead gen landing page. Then, consider how the template’s design spotlights your offer.

If you’re selling soap, you probably want a click-through template that can accommodate lots of photos of your product, like this one. And maybe you think that soap-making webinar we suggested earlier sounds like a great idea. You might want a lead gen template that can share a video of what people can expect, like this one.

Notice that neither of these templates have anything to do with soap. We chose ’em because their call to action supports our conversion goal and their design reinforces our offer. Now, we can start to replace elements of these pages with our own copy and imagery to integrate them into our marketing campaign.

Converting a Landing Page Template for Your Campaign

Every landing page template is different, but they usually have similar elements and follow the same general structure: a header section, a list of features and benefits, some social proof, and a call to action. (Also check out this post on the anatomy of a landing page.)

Follow the steps below to transform your chosen template into a branded landing page that’ll win over your visitors.

1. Your Header Section

  • Add a hero image of your product, service, or lead magnet. If you want to help prospects visualize the benefits, consider showing your offer in the context of use: someone using your product to solve a problem or improving themselves through your service. 
  • Be sure to include your company logo. You want people to know this is your landing page, after all. 
  • Write a descriptive headline that tells people exactly what you’re offering. You can also communicate your main value proposition using a couple of sentences just under your headline.
  • Update your call to action. If you’re using a click-through template, you could have a button that sends people to a product page on your website, a third-party delivery platform, or even add a Shopify integration. If you’re capturing leads, try to keep your form simple—only ask for the information you absolutely need.

This header from Promo (featured in our post on high-converting landing page examples) communicates their offer super clearly.

2. Your Benefits Section

  • People skim, so provide a bulleted list of the benefits of your offer. If you’re creating a sales page, use this space to highlight how your product or service improves your customers’ lives. If you’re offering a lead magnet (like an ebook), tell people what they’ll learn and how they can apply it.
  • Does your template have icons for each benefit? Make sure they’re relevant to your offer or brand. If not, lots of websites offer free icons you can use to replace ‘em: streamlineicons.com, flaticon.com, thenounproject.com, material.io, icons8.com, ionicons.com, among others.

3. Your Social Proof Section

  • Include a testimonial from a satisfied customer, or maybe an endorsement from an industry leader. The trick here is authenticity: use a real quote that sounds believable. Even real testimonials that are too positive can sound like you’re making ‘em up. 
  • Alternatively, you could showcase other kinds of proof: awards you’ve won, trust seals you’ve earned—that sorta thing.
  • Whatever you include here, remember to ask permission. For example, depending on where you source a testimonial from (Amazon, G2), there may be restrictions on how you can use it. 

4. Your About Section

  • Let people know more about your business. What makes your product or service unique? What’s your mission statement—your raison d’être? This is your opportunity to connect with visitors beyond this particular offer.
  • That said, you don’t want visitors to lose focus. Keep it short and sweet.

Coco Village (who we highlighted in our post on the best landing page examples) blends social proof with their own parenting philosophy.

5. Your CTA Section

  • If your page runs long, consider including a final pitch for your offer. This is your last chance, so make it count. Pump up the urgency or exclusivity, or remind visitors about the benefits they stand to gain—whatever it takes to get the conversion.
  • Repeat the call to action button from your header section. Or, if this is a lead gen page, include a button that bumps visitors back up to your form. 

6. Your Footer Section

  • Add your logo and any other details you need to communicate (contact information, copyright notice, any other necessary boilerplate) at the very bottom of the page.

And that about covers it. With that quick checklist, you can turn just about any template into an on-brand landing page in just a few minutes. Simple, right?

3 (More) Examples of Landing Page Template Customization

Alright, the soap example is feeling a little played out. Now, let’s take three templates that Unbounce put together in response to COVID-19 earlier this year—FreshGoods, Multor, and Horizons—and switch ‘em up for different industries.

You can do all of this yourself, of course. But just to make sure these examples are absolute fire, I’ve recruited Gus from our design team to help out.

Gus says “what’s up,” by the way. 👋

FreshGoods → UNIQ

First up is FreshGoods, a click-through landing page template that was designed to help brick-and-mortars get online super quick. Small retailers that don’t have a website can use it to launch a basic ecomm page. Restaurants and breweries can use it to link out to delivery platforms or run special promotions. But it can also fit a more general product launch page—say, for a new mobile app.

The design for FreshGoods clearly speaks to a bakery or cafe. You’ve got the hero image of a bread basket, secondary photography of hand-made pastries and specialty coffees, plus icons that imply food delivery. 

Landing Page Template Examples - FreshGoods
The original version of FreshGoods. (Click to see the whole thing.)

But what’s great about FreshGoods is that it’s both simple and comprehensive. You’ve got all the sections you need to communicate your offer in a compelling way, without any of the technical design elements you’d need to spend hours tinkering with. 

Changing it up is super easy. You’ve really just gotta swap in your logo, images, and icons—then you’ve got (what looks like) a totally custom landing page.

Landing Page Template Examples - FreshGoods (Revised)
The new landing page we built with FreshGoods. (Click to see the whole thing.)

Sure, when you compare the two pages side-by-side, you can see they’re similar. But think about the amount of real work that went into this. Swapping in the new logo? Two minutes. Sourcing images… say 10 minutes. (Or even less, considering our in-app integration with Unsplash.) Add a couple other minor tweaks, and what you’re looking at is, like, 20 minutes for a whole new page.

All you’ve gotta do now is write your campaign copy. (And if you want tips on how to write for your industry, you can pull some insights from our Conversion Benchmark Report.)

Multor → PersonalTrainer

The idea for the Multor lead gen template was to help businesses offer digital alternatives to their in-person services. Healthcare clinics and dentists can use it to offer online consultations. Realtors can schedule people for virtual home walkthroughs. Fitness instructors can register people for video classes… which gives us a great idea for a new page.

We’ll get to that in a second, but let’s have a look at the original page first. Multor Senior feels pretty Silicon Valley, right? It’s all photos of people on computers. (We even snuck a coffee in there, which is very tech.) And the blue is evoking logic and dependability. Look, there it goes!

Landing Page Template Examples - Multor
The original version of Multor. (Click to see the whole thing.)

Like FreshGoods, Multor is meant to be easily customizable. To create our new fitness landing page, we just added our logo and hero image, changed the icons, and replaced the old photos and video. Then we tinkered with some of the fonts, colors, and backgrounds.

Landing Page Template Examples - Multor (Revised)
The new landing page we built with Multor. (Click to see the whole thing.)

Lo and behold—we’ve got a whole new page in less time than it takes to finish your morning cup’a joe.

Horizons → MKT Masters

With the Horizons template, we wanted to help brands capture leads and for promotions during a down period. Think travel and hospitality companies that wanna get people booked for events next year, or marketing agencies hoping to attract business with an ebook or webinar.

Landing Page Template Examples - Horizons
The original version of Horizons. (Click to see the whole thing.)

You’ll see that the design fits some kind of outdoorsy company, what with the photos of nature and delightful orienteering icons. We’d originally mocked up the page for a downloadable ebook, but this template is great for any kind of lead magnet.

How about… an online class all about great marketing, hosted by future me?

Landing Page Template Examples - Horizons (Revised)
The new landing page we built with Horizons. (Click to see the whole thing.)

We went a little bit wild with this one. In addition to changing up the imagery and colors, we decided to rearrange the sections to have our video just under the fold. That way, the first thing visitors will see when they scroll the page is a preview of our class—the most compelling piece of promo material we’ve got.

Create Your Next Landing Page with a Quick-Start Template

Are you still building your landing pages from scratch? (Or, worse yet, relying on a developer to code ‘em for you?)

Forget that. Using one of Unbounce’s 100+ templates, you can put together a fully-branded, campaign-customized landing page in just a few minutes. That means you can spend less time creating pages and more time creating artisanal soaps—or, y’know, whatever else you wanna do with your time.

Go on—give it a shot.

Creating A Static Blog With Sapper And Strapi

Creating A Static Blog With Sapper And Strapi

Creating A Static Blog With Sapper And Strapi

Daniel Madalitso Phiri


In this tutorial, we will build a statically generated minimal blog with Sapper, a Svelte-based progressive JavaScript framework, for our front end, and then use Strapi, an open-source headless content management system (CMS), for the back end of our application. This tutorial is aimed at intermediate front-end developers, specifically those who want the versatility of a headless CMS, like Strapi, as well as the minimal structure of a JavaScript framework, like Sapper. Feel free to try out the demo or check out the source code on GitHub.

To go through the article smoothy, you will need the LTS version of Node.js and either Yarn or npm installed on your device beforehand. It’s also worth mentioning that you will need to have a basic understanding of JavaScript and GraphQL queries.

Before getting started, let’s get some definitions out of the way. A static-site generator is a tool that generates static websites, and a static website can be defined as a website that is sourced from purely static HTML files. For an overview of your options for static-site generators today, check out “Top 10 Static Site Generators in 2020”.

A headless CMS, on the other hand, is a CMS accessible via an API. Unlike the traditional CMS’ of the past, a headless CMS is front-end agnostic and doesn’t tie you to a single programming language or platform. Strapi’s article “Why Frontend Developers Should Use a Headless CMS” is good resource to understand the usefulness of a headless CMS.

Static-site generators, like headless CMS’, are quickly gaining mainstream appeal in the front-end web development community. Both pieces of technology bring with them a much lower barrier to entry, flexibility, and a generally better developer experience. We’ll see all this and more as we build our blog.

You might be wondering, “Why should I use this instead of the alternatives?” Sapper is based on Svelte, which is known for its speed and relatively small bundle size. In a world where performance plays a huge role in determining an effective user experience, we want to optimize for that. Developers today are spoiled for choice when it comes to front-end frameworks — if we want to optimize for speed, performance, and developer experience (like I do in this project), then Sapper is a solid choice!

So, let’s get started building our minimal blog, starting with our Sapper front end.

Sapper Front End

Our front end is built with Sapper, a framework for building extremely high-performance web apps using Svelte. Sapper, which is short for “Svelte app maker”, enables developers to export pages as a static website, which we will be doing today. Svelte has a very opinionated way of scaffolding projects, using Degit.

“Degit makes copies of Git repositories and fetches the latest commit in the repository. This is a more efficient approach than using git clone, because we’re not downloading the entire Git history.”

First, install Degit by running npm install -g degit in your command-line interface (CLI).

Next up, run the following commands in the CLI to set up our project.

npx degit "sveltejs/sapper-template#rollup" frontend
# or: npx degit "sveltejs/sapper-template#webpack" frontend
cd frontend
npm install
npm run dev

Note: We have the option of using either Rollup or Webpack to bundle our project. For this tutorial, we will be using Rollup.

These commands scaffold a new project in the frontend directory, install its dependencies, and start a server on localhost.

If you’re new to Sapper, the directory structure will need some explaining.

Sapper’s App Structure

If you look in the project directory, you’ll see this:

├ package.json
├ src
│ ├ routes
│ │ ├ # your routes here
│ │ ├ _error.svelte
│ │ └ index.svelte
│ ├ client.js
│ ├ server.js
│ ├ service-worker.js
│ └ template.html
├ static
│ ├ # your files here
└ rollup.config.js / webpack.config.js

Note: When you first run Sapper, it will create an additional __sapper__ directory containing generated files. You’ll also notice a few extra files and a cypress directory — we don’t need to worry about those for this article.

You will see a few files and folders. Besides those already mentioned above, these are some you can expect:

  • package.json
    This file contains your app’s dependencies and defines a number of scripts.
  • src
    This contains the three entry points for your app: src/client.js, src/server.js, and (optionally) src/service-worker.js, along with a src/template.html file.
  • src/routes
    This is the meat of the app (that is, the pages and server routes).
  • static
    This is a place to put any files that your app uses: fonts, images, and so on. For example, static/favicon.png will be served as /favicon.png.
  • rollup.config.js
    We’re using Rollup to bundle our app. You probably won’t need to change its configuration, but if you want to, this is where you would do it.

The directory structure is pretty minimal for the functionality that the project provides. Now that we have an idea of what our project directory looks like and what each file and folder does, we can run our application with npm run dev.

You should see the Svelte-eque starter home page of our blog.

A screenshot of the Sapper Starter webpage.

Your Sapper home page. (Large preview)

This looks really good! Now that our front end is set up and working, we can move on to the back end of the application, where we will set up Strapi.

Strapi Back End

Strapi is both headless and self-hosted, which means we have control over our content and where it’s hosted — no server, language, or vendor lock-in to worry about, and we can keep our content private. Strapi is built with JavaScript and has a content editor built with React. We’ll use this content editor to create some content models and store actual content that we can query later on. But before we can do all of this, we have to set it up by following the instructions below.

1. Install Strapi and Create New Project

  • Open your CLI.
  • Run yarn create strapi-app backend --quickstart. This will create a new folder named backend and build the React admin UI.

2. Create Administrator

A screenshot of the Strapi register screen.

Create an admin account. (Large preview)

3. Create Blog Collection Type

  • Navigate to “Content-Types Builder”, under “Plugins” in the left-hand menu.
  • Click the “+ Create new collection type” link.
  • Name it “blog”.
  • Click “Continue”.

A screenshot of the Strapi dashboard - creating a new collection type

Create a new collection type. (Large preview)
  • Add a “Text field” (short text), and name it “Title”.
  • Click the “+ Add another field” button.

A screenshot of the Strapi dashboard - creating a new text field

Create a new Text field. (Large preview)
  • Add a “Text field” (long text), and name it “Description”.
  • Click the “+ Add another field” button.

A screenshot of the Strapi dashboard - creating a new text field

Create a new Text field. (Large preview)
  • Add a “Date field” of the type “date”, and name it “Published”.
  • Click the “+ Add another field” button.

A screenshot of the Strapi dashboard - creating a new date field

Create a new Date field. (Large preview)
  • Add a “Rich Text field”, and name it “Body”.
  • Click the “+ Add another field” button.

A screenshot of the Strapi dashboard - creating a new rich text field

Create a new Rich Text field. (Large preview)
  • Add another “Text field” (short text), and name it “Slug”.
  • Click the “+ Add another field” button.

A screenshot of the Strapi dashboard - adding a new text field

Create a new Text field. (Large preview)
  • Add a “Relation field”.
  • On the right side of the relation, click on the arrow and select “User”.
  • On the left side of the relation, change the field name to “author”.

A screenshot of the Strapi dashboard - creating a new relation

Create a new Relation field. (Large preview)
  • Click the “Finish” button.
  • Click the “Save” button, and wait for Strapi to restart.

When it’s finished, your collection type should look like this:

A screenshot of the Blog collection type showing all its fields

Overview of your Blog collection type. (Large preview)

4. Add a New User to “Users” Collection Type

  • Navigate to “Users” under “Collection Types” in the left-hand menu.
  • Click “Add new user”.
  • Enter your desired “Email”, “Username”, and “Password”, and toggle the “Confirmed” button.
  • Click “Save”.

A screenshot of the User collection type with the 'add new user' button highlighted

Add some user content. (Large preview)

Now we have a new user who we can attribute articles to when adding articles to our “Blog” collection type.

5. Add Content to “Blogs” Collection Type

  • Navigate to “Blogs” under “Collection Types” in the left-hand menu.
  • Click “Add new blog”.
  • Fill in the information in the fields specified (you have the option to select the user whom you just created as an author).
  • Click “Save”.

A screenshot of the Blog collection type with the 'add new blog' button highlighted

Add some blog content. (Large preview)

6. Set Roles and Permissions

  • Navigate to “Roles and Permissions” under “Plugins” in the left-hand menu.
  • Click the “Public” role.
  • Scroll down under “Permissions”, and find “Blogs”.
  • Tick the boxes next to “find” and “findone”.
  • Click “Save”.

A screenshot of the Strapi Permissions page with the find and findone actions highlighted

Set permissions for your Public role. (Large preview)

7. Send Requests to the Collection Types API

Navigate to https://localhost:1337/blog to query your data.

You should get back some JSON data containing the content that we just added. For this tutorial, however, we will be using Strapi’s GraphQL API.

To enable it:

  • Open your CLI.
  • Run cd backend to navigate to ./backend.
  • Run yarn strapi install graphql to install the GraphQL plugin.

Alternatively, you can do this:

  • In the admin UI, navigate to “Marketplace” under “General” in the left-hand menu.
  • Click “Download” on the GraphQL card.
  • Wait for Strapi to restart.

A screenshot of the Strapi Marketplace with the download button on the GraphQL plugin highlighted

Download the GraphQL plugin. (Large preview)

When the GraphQL plugin is installed and Strapi is back up and running, we can test queries in the GraphQL playground.

That is all for our back-end setup. All that’s left for us to do is consume the GraphQL API and render all of this beautiful content.

Piecing Together Both Ends

We’ve just queried our Strapi back end and gotten back some data. All we have to do now is set up our front end to render the content that we get from Strapi via the GraphQL API. Because we are using the Strapi GraphQL, we will have to install the Svelte Apollo client and a few other packages to make sure everything works properly.

Installing Packages

  • Open the CLI, and navigate to ./frontend.
  • Run npm i --save apollo-boost graphql svelte-apollo moment.

Moment.js helps us to parse, validate, manipulate, and display dates and times in JavaScript.

The packages are now installed, which means we are able to make GraphQL queries in our Svelte app. The blog we’re building will have three pages: “home”, “about” and “articles”. All of our blog posts from Strapi will be displayed on the “articles” page, giving users access to each article. If we think about how that would look, our “articles” page’s route will be /articles, and then each article’s route will be /articles/:slug, where slug is what we enter in the “Slug” field when adding the content in the admin UI.

This is important to understand because we will tailor our Svelte app to work in the same way.

In./frontend/src/routes, you will notice a folder named “blog”. We don’t need this folder in this tutorial, so you can delete it. Doing so will break the app, but don’t worry: It’ll be back up and running once we make our “articles” page, which we’ll do now.

  • Navigate to./frontend/src/routes.
  • Create a folder named “articles”.
  • In./frontend/src/routes/articles, create a file named index.svelte, and paste the following code in it.
  • When pasting, be sure to replace <Your Strapi GraphQL Endpoint> with your actual Strapi GraphQL endpoint. For your local version, this will usually be https://localhost:1337/graphql.
<script context="module">
        import ApolloClient, { gql } from 'apollo-boost';  
        import moment from 'moment';

        const blogQuery = gql`
        query Blogs {  
                blogs {
                        author {
        export async function preload({params, query}) {
                const client = new ApolloClient({ 
                        uri: '<Your Strapi GraphQL Endpoint>',
                        fetch: this.fetch
                const results = await client.query({
                        query: blogQuery
                return {posts: results.data.blogs}

        export let posts;

        ul, p {
                margin: 0 0 1em 0;
                line-height: 1.5;
        .main-title {
                font-size: 25px;


<h1>recent posts</h1>

{#each posts as post}
          <a class="main-title" rel='prefetch' href='articles/{post.Slug}'>
  {moment().to(post.Published, "DD-MM-YYYY")} ago by {post.author.username} 

This file represents our /articles route. In the code above, we’ve imported a few packages and then used Apollo Client to make a query: blogQuery. We then stored our query response in a variable, results, and used the preload() function to process the data needed on our page. The function then returns posts, a variable with the parsed query result.

We’ve used Svelte’s #each block to loop through the data from Strapi, displaying the title, date of publication, and author. Our <a> tag, when clicked, goes to a page defined by the slug that we entered for our post in Strapi’s admin UI. This means that when the link is clicked, we open up a page for a particular article, and the slug is used to identify that article.

For our /articles/:slug route, create a file named [slug].svelte, in ./src/routes/articles, and paste the following code:

<script context="module">
        import ApolloClient, { gql } from 'apollo-boost';  
        import moment from 'moment';

        const blogQuery = gql`
        query Blogs($Slug: String!) {
                blogs: blogs(where: { Slug: $Slug }) {
                        author {
        export async function preload({params, query}) {
                const client = new ApolloClient({ 
                        uri: '<Your Strapi GraphQL Endpoint>',
                        fetch: this.fetch
                const results = await client.query({
                        query: blogQuery,
                        variables: {"Slug" : params.slug} 
                return {post: results.data.blogs}

        export let post;

        .content :global(h2) {
                font-size: 1.4em;
                font-weight: 500;
        .content :global(pre) {
                background-color: #f9f9f9;
                box-shadow: inset 1px 1px 5px rgba(0,0,0,0.05);
                padding: 0.5em;
                border-radius: 2px;
                overflow-x: auto;
        .content :global(pre) :global(code) {
                background-color: transparent;
                padding: 0;
        .content :global(ul) {
                line-height: 1.5;
        .content :global(li) {
                margin: 0 0 0.5em 0;

        <title>an amazing article</title>

{#each post as post}
                <h3>{moment().to(post.Published)} by {post.author.username}</h3>

                <div class='content'>
                {@html post.Body} </div>


<p>⇺<a href="articles"> back to articles</a></p>

Note: In Svelte, dynamic parameters are encoded using [brackets]. Our [slug].svelte file lets us add routes for different posts dynamically.

Just like in routes/articles/index.svelte, here we’ve imported a few packages, and then used Apollo Client to make a query: blogQuery. This query is different because we’re filtering our data to make sure it returns a specific blog post. The params argument in our preload() function lets us access params.slug, which is the slug of the current page (that is, the slug of this particular blog post). We used params.slug as a variable in our GraphQL query so that only the data with a slug matching the slug of our web page is returned. We then stored our query response in a variable (results), and our preload() function returns posts, a variable with the parsed query result.

Finally, we displayed our post’s title, publication date, and body (wrapped in Svelte’s {@html} tag).

That’s it. We can now dynamically display pages for any posts added to Strapi’s back end.

We can now work on the “about” and “home” pages. In ./frontend/src/routes, paste this code in the about.svelte file:


<h1>about this site</h1>

minimalist web design really let's the content stand out and shine. 
this is why a simple website design is the first choice of so many artists, photographers, 
and even some writers. they want their creative content to be the center of attention, 
rather than design elements created by someone else. 

<p>this minimal blog is built with <a href="https://svelte.dev/">svelte</a> and <a href="https://strapi.io/">strapi</a> 
images by <a href="https://unsplash.com/@glencarrie">glen carrie</a> from unsplash 

For our home page, let’s go to ./frontend/src/routes and paste the following code in index.svelte:

        h1, figure, p {
                text-align: center;
                margin: 0 auto;
        h1 {
                font-size: 2.8em;
                font-weight: 400;
                margin: 0 0 0.5em 0;
        figure {
                margin: 0 0 1em 0;
        img {
                width: 100%;
                max-width: 400px;
                margin: 0 0 1em 0;
        p {
                margin: 1em auto;
                padding-bottom: 1em;
        @media (min-width: 480px) {
                h1 {
                        font-size: 4em;

        <title>a minimal sapper blog</title>
<p>welcome to</p>

        <img alt='the birds on a line' src='bird-bg.png'>
        <figcaption>where less is more</figcaption>

we're minimal and that might seem boring, except you're actually paying attention.
<p class="link"><a href="about">find out why</a>...</p>

We’ve created all the pages needed in order for our app to run as expected. If you run the app now, you should see something like this:

A screenshot of the minimal blog home page

Your finished minimal blog home page. (Large preview)

Pretty sweet, yeah?

Locally, everything works great, but we want to deploy our static blog to the web and share our beautiful creation. Let’s do that.

Deploy To Netlify

We’re going to deploy our application to Netlify, but before we can do that, log into your Netlify account (or create an account, if you don’t already have one). Sapper gives us the option to deploy a static version of our website, and we’ll do just that.

  • Navigate to ./frontend.
  • Run npm run export to export a static version of the application.

Your application will be exported to ./frontend/sapper/export.

Drag your exported folder into Netlify, and your website will be live in an instant.

The Netlify Dashboard

Drag your export folder to the Netlify Dashboard. (Large preview)

Optionally, we can deploy our website from Git by following Netlify’s documentation. Be sure to add npm run export as the build command and __sapper__/export as the base directory.

We also have the option to deploy to with Vercel (formally ZEIT, as mentioned in Sapper’s documentation).


That was fun, right? We just built a static blog with Sapper and Strapi and deployed it to Netlify in less than 15 minutes? Besides the stellar developer experience, Strapi and Sapper are such a delight to work with. They bring a fresh perspective to building for the web, and this tutorial is a testament to that. We definitely aren’t limited to static websites, and I can’t wait to see what you all build after this. Share your projects with me on Twitter. I can’t wait to see them. Take care, till next time!


Smashing Editorial
(ks, ra, al, yk, il)