Coding with Jesse

Statically generating a blog with Svelte + Sapper

December 18th, 2019

I've been working on rewriting my blog since forever. In fact, here's a video I made back in 2015 introducing and my plans to rebuild my PHP blog using the latest and greatest web technologies. In 2015, this meant I was going to make a REST API with Node.js, and build a React frontend. So that's where I started.

Fast-forward three-and-a-half years, and the site still wasn't done. I hadn't spent that much time on it really, so it just had a REST API and an administration area for writing and editing blog posts. I had done a tiny bit of the public side using React but it was still in rough shape.

That's about the time I fell in love with Svelte and decided I wanted to use Svelte for everything. In July, I started migrating my blog from React to Svelte + Sapper. (I enjoy rewriting React code using Svelte so much, I would do it all day if I could!)

Static Site Generation

Sapper by default comes with a Node.js web server, which serves dynamic server-side rendered markup that gets re-hydrated in the browser. Alternatively, you can choose to use the Sapper "export" feature to generate a static web site that works with any web hosting, no Node.js needed.

My administration area using the REST API is not part of this static website; the admin will only run on my local computer, using a local database. The site does not need user authentication or any kind of session state, and it only changes when I write new posts, so I decided that a static website would be perfect, at least for now.

What was easy & awesome?

My experience with Sapper was mostly positive. Often I was surprised at how easy things were. Here are some of those surprises.

1. Getting started

Getting started with Sapper is really easy. The Sapper sample template already has a blog as its example code, and comes with all the build and testing infrastructure that you'll need to get a Sapper website up and running.

2. Rollup

I really enjoyed working with Rollup, also created by Rich Harris, the creator of Svelte & Sapper. If you don't want to use Rollup, you can also choose to use Webpack or another build tool, if that's what you're into.

3. Static site generation

The static generation worked great! It starts at your homepage and crawls your site like a spider, looking for new links in any <a> tags it can find. This meant that my secret administration area was excluded, which was exactly what I wanted anyway. It creates directories and index.html files, to create all the URLs you've defined.

4. Static websites are fast!

Once the static site was live, it didn't take long to achieve a perfect lighthouse score! I honestly did not think that was possible, but here we are:

Just redesigned my blog as a static-generated site using Svelte + Sapper, ended up with a perfect lighthouse score!

5. Routes without a router

The way routes work in Sapper is really easy and powerful. You put Svelte components inside the src/routes/ folder to define new routes. If you want a URL like /blog/my-post, you can make a Svelte component in src/routes/blog/[slug].svelte and use the slug to dynamically look up the blog contents in order to render the page. This syntax for dynamic routes is so awesome that even Next.js was inspired to do the same.

I wasn't sure if I'd be able to keep the search box on my blog, since there would be no database to search. Turns out all I needed to do was have the search page use the /blog/all.json route as a data source. I passed the search terms as a query parameter like /blog/search?terms=example The search page parsed the URL to get the search terms, then filters the blog posts client-side to render the results. Might seem ridiculous to have a single JSON file with all the blog posts in it, but on my blog the all.json is only 142kb which is smaller than some JavaScript frameworks! I might write a blog post going into more detail about this client-side search, if anybody is interested?

7. Deployment

Deploying a static site is easy. I use shared hosting so I wrote a bash script that does the following: 1) npm run export to generate the static site, 2) zip up the static files into a zip file, 3) upload the zip file to my web server with scp, 4) ssh into the server and unzip the zip file into the correct folder, 5) delete the zip file. I don't need a complex CI system, though maybe I'll set that up down the road. For now, running a bash script after each blog post is fine for me.

What was hard & confusing?

Learning any new tool has its ups and down. There were some concepts that I didn't understand correctly, and that led me to make mistakes, causing a few bugs and broken pages. Here are some of the things I learned in the process.


It took me a while to figure out that all the API calls needed to be "JSON API" calls inside server routes that would later generate .json files. Confused already? Let me walk through an example.

When you're viewing a page of the blog, and you click a link to another article, the Sapper client-side code will fetch the contents for that page asynchronously. It can't access the actual REST API so it needs to get the data from a static file, and the best approach for that is to have static .json files in your static site.

For the src/routes/blog/[slug].svelte component I mentioned above, I created a related src/routes/blog/[slug].json.js file that acted as a "server route" that will cause Sapper to export a /blog/my-post.json file for each post.

For more on this, including code examples, check out the Sapper documentation about Server routes.

2. Every page needs to be discovered with a crawler

As I mentioned above, Sapper uses a web crawler to start at your homepage, and dig through looking for links to pages. This means that any pages you might have needs to be linked from an <a> tag. You cannot have any truly secret pages.

To achieve this, I made a single route /blog/all that acts as a site index, with a link to every blog post, plus some extra links at the bottom just so Sapper will know about them. For example, I needed to include an extra link to my RSS feed and my Newsletter signup that weren't linked to with <a> tags anywhere else.

3. Vendor CSS was awkward

Of course I needed to have beautiful looking code examples on my blog, so I integrated Prism.js. I couldn't figure out how to import the prismjs-monokai.css vendor stylesheet into the Svelte component that needed it, so I ended up just using a <link> tag to load it from the template.html, similar to the global.css example file that comes with the Sapper template.

Seems there is a solution that uses a Rollup plugin to allow you to import stylesheets from the Svelte <script> block but I didn't go down this road (yet). Maybe doing an @import in a Svelte <style> block will be something we can do one day, but not today.


Unlike Svelte v3, which is very much ready for production, Sapper is technically still in early development, and hasn't yet reached version 1.0. Still, it was a joy to use, and for something like a blog I think it's perfect. I'm already using Sapper in two other production web applications, as I feel Sapper is mature enough for my needs.

Further reading

About Me

My name is Jesse Skinner. I'm a freelance web developer.

I'm a Canadian from Barrie, Ontario, an hour drive north of Toronto.

I was born in 1980, and I've had a computer since 1983. As a child, I read programming magazines and typed the BASIC code into my Coleco Adam. I went on to graduate from the University of Waterloo in 2004 with a "Bachelor of Mathematics" in Computer Science.

I've been working as a professional web developer since 2001. I've been doing freelance web development since 2006, specializing in JavaScript, CSS and HTML. Lately I've been using Svelte whenever possible.

I also write. I write regularly on Coding with Jesse. I wrote a book for O'Reilly called Unobtrusive Ajax. I've also given a number of talks.

Sometimes I stream on Twitch. I also record coding videos for YouTube.

Well, that's enough about me. What about you? Please feel free to get in touch.

The simplest Svelte component is an empty file

August 4th, 2019

I discovered something while refactoring my Svelte code that blew my mind: A Svelte component can be an empty file. How many other component frameworks can say that?

This was very useful during refactoring, because I could just create a placeholder file for the new component, import it and start using it:

import Empty from './empty.svelte';


Sure, it doesn't do anything, but it doesn't break either.

I think this is very symbolic of what makes Svelte so groundbreaking and powerful. Let's dig deeper and see what it can teach us about Svelte.

A Svelte component is a file

With Svelte, components and files have a one-to-one relationship. Every file is a component, and files can't have more than one component. This is generally a "best practice" when using most component frameworks. Perhaps this practice comes from the practice of having each class in a separate file in languages like Java or C++.

By enforcing this practice, Svelte can make some assumptions that simplify your code. That brings me to the next observation.

No boilerplate, just make a new file

In most component frameworks, you need to write some code to define your component. With React, the simplest component is an empty function. In other frameworks, you need to import a library and call a special function to define and create your component. With Svelte, you just create a new .svelte file.

The Svelte compiler will take each file and generate a component for it automatically. And that brings us to another important observation.

You don't need Svelte to use a Svelte component

In order to mount a React component, you need to import react-dom. Using a Vue component requires the Vue library. An Angular application absolutely requires loading the Angular framework.

Svelte, on the other hand, is a compiler. In a way, Svelte is more like a programming language than a library. When you're programming in JavaScript, you don't need to import something to use a for loop. Similarly, you don't need to import anything in your Svelte code to use Svelte's template syntax. Your Svelte files get compiled into Javascript and CSS. It's a very different approach.

You might guess that an empty file would compile into an empty JavaScript file, but every Svelte component comes with an API that allows you to use it outside of Svelte and mount it into the DOM. Here's what it looks like to use a compiled Svelte component:

import Empty from './empty.js';

const empty = new Empty({
  target: document.body,
  props: {
      // if we had some, they'd go here

If we compile our empty component and bundle it with Svelte internals, it ends up being 2,080 bytes uncompressed, and 1,043 bytes gzipped. So the overhead for using Svelte ends up being only a kilobyte. Compare that to other frameworks that require 10x or 100x that many bytes just to mount an empty component!

Svelte is a new paradigm

At first glance, being able to use an empty file as a component seems like a silly, impractical gimmick. But looking deeper, I think it teaches us a lot about how Svelte differs from most if not all JavaScript component frameworks that came before it.

I imagine it will inspire other framework developers to take a similar approach and reap some of the same benefits. This is the kind of shift in thinking that changes things permanently. Svelte is not just a new framework, but a complete paradigm shift.

Is this thing on?

March 26th, 2019

Can you believe it has been four years since I last posted here, and eight years since I really wrote blog articles here? Is anybody still reading this? If so, I'm thinking about writing articles again. If not, well, I will probably write them anyway!

In the meantime, I've been streaming on Twitch for the past year. I stream at random once or twice a week, a few hours in the afternoon EST. There is an archive of videos if you want to watch past streams.

Hope to see you there! (If there is anyone out there??!)


May 1st, 2008

I succumbed to twitter. If anybody here twitters, feel free to follow me at @jesseskinner or leave your id in the comments.

Three years of The Future of the Web

April 6th, 2008

Three years ago today, I wrote my first post. I was just about to move to Berlin and was looking for a new job.

A lot has happened since then. I started freelancing a year later, and I couldn't have done it without this site. 100% of my clients come directly through my "hire me" page.

By the time this blog turns four, we should be living back in Canada, and I might set up a web development agency (in an office!)

That's enough about me! What're you guys up to these days?

See all the articles

February 12nd, 2008

I've just added a new page where you can see a listing of all the articles I've written (this article is my 181st). This might be an easier way to see older articles than going page by page or month by month. Check it out: All Articles

jQuery tutorial on

April 11st, 2007

I wrote a jQuery tutorial which was just put live on IBM DeveloperWorks today: Simplify Ajax development with jQuery.

I discuss a lot of the core functionality and philosophy of jQuery, including an introduction to writing plugins. So if you've heard of jQuery but haven't really decided if you want to use it, or if you've started to use it and want to see what it's capable of, I think you might enjoy the article.

I've been tagged

December 7th, 2006

Joe tagged me. So now I have to tell you 5 things that the blogosphere doesn't know about me.

I know, these things are totally boring, and you didn't come here to learn about my pets, so I'll try to keep them slightly interesting and on topic:

  1. I ran a number of BBSes from 1993-1995. They were called "The Dreaming" and "Pepperland", and my handles were "Morpheus", "Zippo" and "Fone Bone".

  2. When the Internet came out, I thought it was just another crappy network for "lamers", something like AOL or CompuServe, and hoped it would go away. After a while I gave up and jumped on the bandwagon.

  3. The first web page I made was in 1995 (Grade 10). It was a one-page psychedelic propaganda page for a hippie cult I was trying to start called "The Mellow Revolution". It was hosted on Tripod, but it doesn't exist anymore.

  4. My mom has one of the most successful quilt web sites on the Internet called Victoriana Quilt Designs. When I tell people this, they assume I made it for her. In fact, I only taught her how to use FrontPage one day and she did all the rest by herself (okay, I helped her integrate PayPal and add login security, but that's about it).

  5. I've climbed up and stood on one of the pyramids in Cairo. If you don't believe me, here's proof.

Well, I hoped I didn't bore you to death. Now I'm supposed to tag 5 other bloggers and see if they actually find out, give a crap, and follow through with a list. Tag, Emil Stenström, Roger Johansson, Tara Hunt, Mike Papageorge, and Dan Webb, you're it.

Freelancing Fulltime

August 9th, 2006

Big news: I'm quitting my job, moving back to Canada (with Svea of course) and taking the plunge into fulltime web development freelancing. This is something I've wanted to do for a long, long time (like seriously 10 years).

I'll be available to do any sized projects, from debugging CSS to adding Ajax functionality to full-blown database-driven web applications in PHP or Ruby on Rails. I love doing it all, and I love the variety. I think that's why freelancing is going to be very fun for me. I also plan to have more time to work on my own projects and get some very interesting things started. Stay tuned for more on that.

You can probably expect the content of this blog will start to include stuff about freelancing and self-employment. Hopefully I can help someone out by passing along any painful lessons learned. I'd also love to hear your stories and advice about going it alone.

Anyway, if you'd like me to help you out with JavaScript, Ajax, CSS or whatever else, drop me a line.

Holiday Time

June 29th, 2006

I hate to do posts like "Sorry I haven't posted in so long" or "I won't be posting for the next while" but... I won't be posting for the next while. I'm leaving tomorrow morning to go back to visit Canada for three weeks, and chances are I'll be pretty busy. But don't worry—I'll be back just in time to do Carnival of the Web #2. See ya!

Hire an Ajax Freelancer

May 17th, 2006

If you want Ajax on your web site, I'm your man.

Although I'm already available to do all types of web freelancing, I want to emphasize that I specialize as an advanced JavaScript, CSS and Ajax freelancer. I've been doing Ajax and other advanced JavaScript for over two years now, and it's really my favourite thing to do.

If you're not really sure what is possible, I can also offer suggestions on ways to improve the usability of your site while still following best practices, web standards and accessibility guidelines.

So if you want to use some animation, auto-complete, XMLHttpRequest or any of that other Ajax stuff on your web site, or if you are a web developer or designer who needs help with JavaScript, please contact me.

See you at JAX 2006

May 3rd, 2006

From Tuesday (May 9th) until Thursday (May 11th), I'll be attending JAX 2006, a Java conference in Wiesbaden, Germany. Not only will I learn all about what's new in the Java world, I'll be able to really test out my knowledge of German. (Eek!)

If any of you are going to be there by some freak chance, let me know so we can meet up. For the rest of you, I'll be sure to write about anything that relates to web development and the future of the web.

Ezine Articles

April 28th, 2006

I just submitted my first article to I just heard about this site a couple of days ago so I thought I'd try it out. Basically, it's a way to get articles read by a new audience. I won't get paid for it or anything, but ideally people will discover this blog and my writing if my articles get republished in various e-zines or newsletters, etc.

If you do some writing and want to try spreading your articles a bit further, it might be worth looking in to. I'll post again on here if anything incredible comes out of it (though I don't except much yet).

What's the point?

April 12nd, 2006

What's the point of this site? Well, the Big Picture is an outlet for me to write about my greatest passion: the Internet, the direction it's moving in, and the way it is changing the world. But at the same time, I work as a web developer, so this is also my forum for sharing different problems and tricks I come across, as well as touting the benefits of web standards and best practices.

The result is, I have articles like Setting a form field to null or undefined and Let's get personal on the same site. This means that people who don't do any JavaScript coding have to put up with my technical articles. And people who just want my tips and tricks have to put up with my, let's say, fluff articles.

Luckily, these both roughly fall under "The Future of the Web". If I started posting pictures of cats, or investing advice, or whatever, I might get more complaints. But even under the blanket of "The Future of the Web" I have some thinking to do about my target audience.

I don't really write the techie articles for regular readers so much, they're more geared at people searching the web on, say, "setting form field null javascript". Nor do I write the fluff stuff geared at search engines; they're mostly for the regulars.

So how do I solve this apparent dilema? I could create multiple RSS feeds for categories. I could spin off a second blog. I could drop one of the topics altogether. Or, I could just ignore the problem and let people skim over the topics they have no interest in.

Well anyway, I haven't solved the problem yet. I've thought about these options, but I haven't decided what I'll do. But I'm aware there is an apparent identity crisis looming.

How do you deal with identity and branding, and evolution over time? Do you put much thought into this before creating a site or blog, or do you just let it evolve over time and define itself? Where would you like to see this blog go?

Form field spammers

March 22nd, 2006

I didn't want to put my email address on the site, purely for spam reasons. I thought I could avoid spam by putting a contact form on the site instead. Now, I get more spam than I used to from comment spam bots using my contact form!

There is no escape, and I will have to accept this as a part of my destiny...

Check this out

February 16th, 2006

I just had a look at the WayBack machine for Turns out someone else had it before. Creepy.


October 23rd, 2005

I finally got around to adding comments to the site. Feel free to test them out if you like. No html is supported..that is, everything will be converted to HTML entities. There is no preview or edit. It's pretty basic stuff. I guess that's the problem with writing my own blog code.. I never get around to adding the most basic of features. At least now you can comment on the lack of features :)

And on an unrelated note, I put the design back to the original one. The new one was a bit too boring I think. I'm not sure when I'll change it again...

New Design

September 14th, 2005

So what do you think? I redesigned the web site, as I'm sure you'll notice. Unless it's your first time here, of course. It took me about 15 minutes to do the design. I was kind of bored of the other one so I thought I'd go for the terminal-window look. I should put some of my old ANSI art here next.. ha.

Free Horoscope Daily

September 11st, 2005

I just launched a real simple web site, Free Horoscope Daily with my father. It contains free, daily horoscopes, and nothing else. I was sick of all the clutter that ends up on horoscope web sites, and wanted to make one that was simple and good. It may grow in the future, but right now I like it how it is.

Please, I'd love to hear your feedback. Drop me an email if you have something to suggest or that you'd like to see.

First Post

April 5th, 2005

Hello there. We are living in a very exciting time. For the first time in human history, the entire earth is connected. We have the ability to share anything with anyone at anytime, easily and inexpensively. We face enormous potential with this technology, and we haven't begun to realise the full implications.

There are some amazing applications of the Internet that are just starting to emerge, some that have become very widespread. In the first days of the Internet, web pages seemed to be the ultimate purpose. Next came peer-to-peer file sharing. Now, we are starting to see a new generation of web applications, more powerful than today's desktop applications. What comes next is anybody's guess.