🐶   Puppy Tutorial   🐶

Welcome to Puppy! We're glad you're here. If you're reading this, you've already installed a Puppy project and have run npm start. We commend you!

If you still need to do that or are having issues, check out the Puppy README for more info.

The goal of this tutorial is to guide you through setting up and deploying your first Puppy project. Some basic web development knowledge is required, but if you're a beginner, these concepts shouldn't be too hard to grasp. If this isn't your first Puppy party, it's safe to delete this page and do your thing.

Otherwise, allow us to show you around!

First things first...

  • Crack open your favorite text editor (might we recommend Visual Studio Code?)
  • Split your screen between your text editor and preferred web browser
  • Keep your terminal close by


By default, the homepage of a Puppy project is the prototype index. It lists every page in your prototype. You can see it here.

In this section you'll learn how to...

  • Create your first page
  • Give it a name
  • Leverage the power of Twig
  • Reference an asset in the /public/ directory
  • Separate your content from the presentation layer

Create your first page

Pages live in the /src/pages/ directory.

It only seems fitting for our first page to be about puppies! First, create a new file in the /src/pages directory called puppies.html.

Give it a name

You can give your page metadata with YAML front matter headers. They look a little something like this:

title: My Puppy Page
- Adorable
- Floofy

The name of your page can be defined with the title attribute. Now, if you return to the index, you’ll see a link to your new page!

Leverage the power of Twig

So, our page has a name…but it still doesn’t have any content. To start adding content, we can use Twig syntax to create flexible page templates.

We’ve provided a simple page layout template under /src/templates/layouts called base.twig. Now, in puppies.html, you can extend this template and immediately start adding content like so:

<!-- in puppies.html -->

{% extends "@templates/layouts/base.twig" %}
{% block content %}

<div class="puppy-page">
  <h1 class="puppy-page__heading">My Puppy Page</h1>
  <p>A captivating description</p>

  <!-- Rest of content -->

{% endblock %}

Check out your page to see your new content!

Reference an asset in the /public/ directory

Any static images or assets you wish to use on your site can be moved to the /public/static directory.

From there, you can call the built-in function puppy.staticUrl('path/to/file') in your page template to display the asset.

Let's see how this works by adding this adorable face to our puppies.html page:

A puppy

To get the above photo as a file in your project, run this command in a new terminal tab/window at the project root:

curl -L https://picsum.photos/id/237/300/300 > public/static/img/puppy.jpg

You should now see the image in the /public/static/img directory. Here's how we can reference this image in our page template:

<!-- in puppies.html -->

{% extends "@puppy/layouts/base.twig" %}
{% block content %}

<div class="puppy-page">
  <h1 class="puppy-page__heading">My Puppy Page</h1>
  <p>A captivating description</p>

  <!-- Reference your image here -->
  <img class="puppy-page__img"
    src={{ puppy.staticUrl('img/puppy.jpg') }} />

{% endblock %}

You should now see the image on your page. Easy, right?

Separate markup and content with data

Now we know how to easily add content to a page. But what if we want to avoid hardcoding that content in our template markup?

Have no fear! Puppy allows you to easily separate your content from the presentation layer.

Any structured data you want your page to access can live in the /src/data directory.

Let's enhance our puppy page a bit by adding a list of dog breeds. This example will use a JSON data file, but Puppy also supports YAML and JavaScript data files. To start, we can create a new dog-breeds.json file in /src/data:

// dog-breeds.json

  { "name": "Shiba Inu",
    "link": "https://en.wikipedia.org/wiki/Shiba_Inu"
  { "name": "Welsh Corgi",
    "link": "https://en.wikipedia.org/wiki/Welsh_Corgi"
  { "name": "Labrador Retriever",
    "link": "https://en.wikipedia.org/wiki/Labrador_Retriever"

Conveniently, all our data files can be accessed through a global site.data array. All we have to do is loop through site.data['dog-breeds.json'].

<!-- in puppies.html -->

<h2>Dog Breeds</h2>

{% for breed in site.data['dog-breeds.json'] %}
  <li><a href={{ breed.link }}>{{ breed.name }}</a></li>
{% endfor %}

If you visit your page now, you should see a list of breeds populated from your data!

Congrats! Now you have all the tools you need to create a basic page in your prototype. 🎉

But we're just getting to the fun stuff - let's see how we can spruce up our page a bit with some styling!


In this section you'll learn how to...

  • Add a Sass file
  • Link to a static asset (font, background image)

Add a Sass file

We enjoy using Sass for CSS preprocessing so much that Puppy supports .scss compiling by default!

This means adding styles to your page is as simple as creating a new .scss file in the /src/scss directory.

Currently in /src/scss we have:

  • main.scss - main stylesheet for your prototype that imports any individual stylesheets
  • tutorial.scss - styles for this tutorial page
  • reset.scss - styles to clear browser defaults

Ready to give your puppy page a makeover? Start by creating a new file called puppies.scss and placing it in /src/scss.

// in puppies.scss

.puppy-page {
  margin: 50px;

.puppy-page__heading {
  font-size: 48px;

// any additional styling

If you visit your puppies.html page...nothing has changed. That's because you need to import puppies.scss in main.scss!

// Path to static assets
$publicPath: '/';

// Project styles go here
@import 'puppies';    // Add this line

Hit save and now visit your page. All your new styles should be applied! ✨

Link to a static asset

In case you need to include any static assets in your SCSS files, you can drop those assets in the /public/static directory. We've provided a global variable called $publicPath in main.scss where you can set the path to your public directory.

For example, you can add custom web fonts to /public/static/fonts and import them into your stylesheets like so:

@font-face {
  font-family: 'My Custom Font';
  src: url($publicPath + 'static/fonts/my-custom-font.woff2') format('woff2');
  font-style: normal;
  font-weight: 400;


In this section you'll learn how to...

  • Add a Javascript file
  • Install and import a third party dependency

Add a Javascript file

Similar to adding styles, you can add .js files to the /src/js directory that this starter comes with.

Let's try this out by adding a file called puppy-alert.js that simply shows an alert every time our image of a puppy is clicked.

// in puppy-alert.js

  .addEventListener('click', () => alert('🐶'));

Before we can test our changes, we need to import our file in the provided main.js file in the /src/js directory.

// in main.js

import './puppy-alert';

Once that's done, our new JavaScript changes will be loaded on the page!

Install and import a third party dependency

You can add any third-party modules available on NPM to your Puppy project by running npm install <module-name>.

To use the installed module, import it wherever needed. For example:

import $ from 'jquery';


Ready to share your work with the rest of the world? Puppy can generate a static site for you, which means it's super easy to deploy your prototype to a live web server - one of our top picks is Netlify!

Deploy to Netlify

When it comes to deploying with Netlify, you have some options:

Deploy with Git (CD)

If your site has a Git repository, you can link it to Netlify and configure the build settings for CD (Continuous Deployment).

To add CD to your Puppy site, you can update your Netlify build settings to this:

  • Build command: npm run build - this builds your static site
  • Publish directory: dist - this is where your static site lives

If your project isn't at the root of your repository, you will need to update the "Base directory" and "Publish directory" settings to include the path to your project.

Deploy with CLI

You can also use the Netlify CLI tool to manually trigger deploys.

Set up your project with these commands:

npm install netlify-cli -g      # Install netlify-cli
netlify login                   # Authenticate your Netlify account
netlify init                    # Initialize repo at project root

Whenever you're ready to deploy, you can run:

npm run build                   # Build your static site
netlify deploy --dir=dist       # Deploy the dist directory

That's it! Now your Puppy site is live on the World Wide Web. 💥

So long, for now!

Thanks for spending the past 15 minutes with us!

Feel free to leave this page here to refer back to while you're getting your bearings.

When you're confident you've absorbed everything here you can remove this tutorial by:

  • Remove the line importing tutorial.scss from /src/scss/main.scss
  • Remove the entrypoint for tutorial.scss in webpack.config.js (line 12)
  • Delete /src/scss/tutorial.scss itself
  • Delete /src/pages/tutorial.html (this page!)