Go back to blogs

Trello + Sapper JAMstack (Part 3)


Sep 24 '20

Sapper setup

Setting up Sapper is very easy to install for more details check here. I personally prefer Rollup.

# for Rollup
npx degit "sveltejs/sapper-template#rollup" my-app
# for webpack
npx degit "sveltejs/sapper-template#webpack" my-app
cd my-app

npm install
npm run dev & open http://localhost:3000
Enter fullscreen mode Exit fullscreen mode

Once you have opened the project in your editor you will notice a confusing directory structure that may look daunting at first but it is pretty straight forward when it comes to producing your SSG part of Sapper.

│   │   index.svelte
│   │   about.svelte
│   │   _layout.svelte
|   |   _error.svlete
│   └───blog
│       │   [slug].svelte
│       │   index.svelte
│       │   [slug].json.js
│       │   _posts.js
│       │   index.json.js
Enter fullscreen mode Exit fullscreen mode

In Sapper, any file with _ underscore at the beginning is a hidden/private file. Our logic to obtain blog posts via API from Trello happens in the _posts.js file which generates the right JSON files for the blog posts. [slug].svelte and index.svelte contains template responsible for list of posts and the post itself. [slug].json.js and index.json.js exports the JSON it is possible without these files and yet has SSG done but it is a major hit on the performance and is very much noticeable with my series on headless WordPress and Sapper.

Snippet for _posts.jswhere we export a JSON object that has data for the blog post that could be populated on index.svelte and [slug].svelte


import fetch from "node-fetch";
let data = {};
let url = `https://api.trello.com/1/lists/5f538d3a842e0a3b6ce9f259/cards?key={key}&token={token}`; //this is from your previous post
let trello = async function getPosts() {
  const res = await fetch(url);
  data = await res.json();
  return (data = data.map((e) => {

    const months = ["jan", "feb", "mar","apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
    let posted_date = new Date(e.dateLastActivity)
    let formatted_date = `${posted_date.getDate()} ${months[posted_date.getMonth()]} ${posted_date.getFullYear()}`
    let tags = e.labels.map(e=>{
      return {

    return { title: e.name, slug: e.name.toLowerCase().replace(/[^\w ]+/g,'').replace(/ +/g,'-'), desc: e.desc, image:e.cover.scaled,time:formatted_date,tags };

export default trello;

Enter fullscreen mode Exit fullscreen mode

After a slight modification to index.json.js and [slug].json.js we can automatically get Trello items as blog posts.

import trello from "./_posts.js";

export async function get(req, res) {
  res.writeHead(200, {
    "Content-Type": "application/json",
  let data = await trello();
  let posts = data;
  posts = posts.map((post) => {
    return {
      title: post.title,
      slug: post.slug,
      time: post.time,
      tags: post.tags

Enter fullscreen mode Exit fullscreen mode
import trello from './_posts.js';

const lookup = new Map();

export async function get(req, res, next) {
    // the `slug` parameter is available because
    // this file is called [slug].json.js
    const { slug } = req.params;
    let data = await trello()
    data.forEach(e => {
        lookup.set(e.slug, JSON.stringify(e));
    if (lookup.has(slug)) {
        res.writeHead(200, {
            'Content-Type': 'application/json'

    } else {
        res.writeHead(404, {
            'Content-Type': 'application/json'

            message: `Not found`


Enter fullscreen mode Exit fullscreen mode