Svelte Pwa Now

A PWA ready Svelte v3.0 starter template with Tailwind, Now integration and optional Typescript suppot

Svelte PWA Now starter ============= A simple Svelte starter template with:

  • Tailwind CSS (from
  • Rollup copy assets plugin to serve static folders (eg. data or images)
  • Now integration
  • Cypress for testing
  • PWA ready, including basic service worker and social sharing meta data boilerplate
  • Typescript support (switch to the implement-ts branch)

Getting started

Make sure Node.js is installed. Clone the repo and

npm install

Start by

npm run dev

and go to localhost:5000.

Build for production using

npm run build

and serve the dist folder.



Find out more about Tailwind CSS here. To extend Tailwind classes, go to tailwind.config.js and put in your customizations as an object under extend.

module.exports = {
  theme: {
    extend: {
      colors: {
        backgroundColor: "#f6f5f5",
        primaryColor: "#5bd1d7",
        secondaryColor: "#248ea9",
        accentColor: "#556fb5"
  variants: {},
  plugins: []

For example, the template comes with custom colors which can then be used in html like <div class="backgroundColor"></div>.

Be sure to indicate postcss to your style tags like this

<style type="text/postcss"></style>

to see proper syntax highlighting and parsing in VS code.

More details can be found here.

Now integration

The template includes optional integration with the Now hosting service. The easiest way to get started is to link your Github repo to Now, which allows all pushes to be built and served automatically. The included now.json tells Now to automatically run the rollup build command (via package.json) and serve the dist folder.

If applicable, be sure to include your custom web domain under alias to tell Now to automatically alias your output to your domain.

  "version": 2,
  "alias": "https://ADD-DOMAIN-NAME-HERE",
  "builds": [
      "src": "package.json",
      "use": "@now/static-build"
  "routes": [
      "src": "/(.*)",
      "headers": { "cache-control": "max-age=0,must-revalidate" },
      "dest": "dist/$1"

There is also a .nowignore file which tells Now to ignore specified files, similar to .gitignore.

More info on Now integration with Github can be found here.

If you do not need Now integration, feel free to remove now.json and .nowignore.

Cypress testing

Cypress is included in the template. Simply use npm run test to start cypress integration testing. More info about writing cypress tests can be found at

Rollup copy assets plugin

By default, Rollup does not copy static folders to dist when building. If you have folders with static assets like data files or images, put the folder path in rollup.config.js like so.

import copy from "rollup-plugin-copy-assets";

const production = !process.env.ROLLUP_WATCH;
export default {
  plugins: [
      assets: ["src/assets", "src/MORE-STATIC-FOLDERS"]

PWA boilerplate


The commonly required icons are at src/assets. Be sure to use the same filenames as they are referred to in the metadata at dist/index.html. Tip: Use Real Favicon Generator which automatically creates all the required icon sizes, and simply unzip the generated asset bundle into src/assets.

index.html metadata

The icons are all utilized in the <meta></meta> tags for Facebook, Twitter and Google indexing among others. Be sure to customize your app title and descriptions in all the tags.

Service worker

This template includes a basic service worker at dist/service-worker.js which simply checks against the currently held cache and loads from network if required. Feel free to further customize it for your needs.


Customize dist/manifest.json with your PWA's info for installation. Note that the manifest requires a 512x512 icon which is not generated by Real Favicon Generator. You have to manually create that one on your own using something like

Basic router

A very basic router is included as a renderless component at src/components/Router.svelte. It simply uses the browser History API to manage the browser history stack and updating the browser url. To use, you must manually do something like

          state1: newValue1,
          state2: newValue2
        "?state1=" + newValue1 + "&state2=" + newValue2

in the component where the state was updated, which will then change your browser window url to show the new state for your SPA.

The router also takes care of parsing incoming url parameters, which you must then manually pass to your state store (in this case src/store/store.js).

window.onload = function() {
    if ( > 0) {
      const params =;
      params.split("&").forEach(param => {
        const key = param.split("=")[0];
        const value = parseFloat(param.split("=")[1]);
        console.log(`Parameter of ${key} is ${value}`);


This article probably explains it much better.



Top categories

Loading Svelte Themes