Opens an external site in a new window
Mental Health Awareness Month
“Community”
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links
  • Profile
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links

SvelteKit PWA: Installable App with Offline Access # SvelteKit PWA: Installable App with Offline Access #

blurry low resolution placeholder image SvelteKit PWA
  1. Home Rodney Lab Home
  2. Blog Posts Rodney Lab Blog Posts
  3. SvelteKit SvelteKit Blog Posts
<PREVIOUS POST
NEXT POST >
LATEST POST >>

SvelteKit PWA: Installable App with Offline Access #

Updated 3 years ago
6 minute read
Gunning Fog Index: 5.7
8 comments
Content by Rodney
blurry low resolution placeholder image Author Image: Rodney from Rodney Lab
SHARE:

🚀 What is a PWA? #

Before we get going on seeing how to build a SvelteKit PWA, let’s run it back a little and first look at what a PWA is. A Progressive Web App (PWA)  is an app built to work with HTML, JavaScript, and CSS but with the functionality of a native app. Features include responsiveness and offline availability, as well as the possibility to install the app. You can test a site's PWA capability in Lighthouse .

blurry low resolution placeholder image SvelteKit PWA: Lighthouse screenshot showing PWA with a check mark.
SvelteKit PWA: Lighthouse screenshot

For all of those mentioned features to work, we need to add some additional superpowers to our SvelteKit app. These include icons of various sizes and a manifest file which contains the app name, colours and some other properties. As well as those items, we also need to define a service worker  to perform background caching and do the groundwork to make the app available offline.

In this post, we will look at how to use the PWA functionality in the MDsveX starter blog. After that, we will look at what is under the hood, so you can set up an existing project as a PWA. If that all matches what you were looking for, why don't we get cracking?

🧱 Create a SvelteKit PWA using the MDsveX Starter #

I have just added PWA functionality to the MDsveX starter . All you need to do is customize the website configuration file with the site's name and theme colours, then run a script to generate all the different icon sizes automatically. Here is exactly what you need to do in five simple steps. If you are looking for a more general SvelteKit Tutorial or how to get started with SvelteKit I have a couple of posts you will appreciate.

SvelteKit PWA using the MDsveX Starter #

  1. We are using the MDsveX starter . Start by cloning the repo and installing packages. I use pnpm, though if you prefer npm, just swap out pnpm for npm in the commands below:
        
    git clone https://github.com/rodneylab/sveltekit-blog-mdx.git my-new-mdsvex-blog
    cd my-new-mdsvex-blog
    pnpm install
    cp .env.EXAMPLE .env
    pnpm run dev
    After cloning the repo and installing packages, these commands create a `.env` file from the template provided and fire up the dev server. You can change the server port in `package.json` if you already have an app running on port 5173 (the default port).
  2. src/lib/config/website.js. This file contains data which are used for SEO as well as the parameters needed for our Progressive Working App. More sensitive data can be pulled from the .env file when required. Having said that, for the progressive app customization, we shouldn’t have anything secret. Go ahead and customize the file (lines 7–11):
    src/lib/config/website.js
    javascript
        
    1 const facebookPageName = import.meta.env ? import.meta.env.VITE_FACEBOOK_PAGE : '';
    2
    3 const website = {
    4 author: 'Rodney Johnson',
    5 ogLanguage: 'en_GB',
    6 siteLanguage: 'en-GB',
    7 siteTitle: 'SvelteKit Blog Mdx',
    8 siteShortTitle: 'SvelteKit Blog',
    9 description: 'SvelteKit MDsvex Blog Starter - starter code by Rodney Lab to help you get going on your next blog site', icon: 'static/icon.png',
    10 backgroundColor: '#1b4079',
    11 themeColor: '#d62828',
    12 // TRUNCATED...
    13 }
  • Next, you will need a set of favicons. There are five files needed for wide support across legacy and modern browsers and devices:
    • icon.svg — SVG favicon (used by modern devices) — typically you can start with this and generate the others from it,
    • apple-touch-icon.png: 180px × 180px,
    • favicon.ico: for legacy devices,
    • icon-192.png: used with manifest.json for Android devices,
    • icon-512.png: also for Android devices.
    You can generate these yourself from an SVG using free and open source tools. Alternatively, use an online service like Favicon Generator. Replace the icons in `static` with your fresh favicons.
  • As ever, we need to check that all of this is working before we deploy. This is easy to do with Lighthouse in the Chrome Developer Tools. First, build the site and generate a preview site (stop the dev server first if this is running):
        
    pnpm build
    pnpm preview
    Finally, in Chrome Browser, go to `localhost:4173`. Next go to the View menu and find Developer then click Developer Tools find Lighthouse (you might need to expand the list, it is in the same menu as Elements and Console). Once you have Lighthouse open, click Generate Report. It might take a couple of minutes to run. You should have a big, green tick (check mark) under PWA when the results do show up. Note to get 100 for Best Practices in the latest version of Chrome you will need to set Content Security Policy to enable mode. By default, it is set to report only mode in the template. It is really easy to switch modes, just edit two lines in src/hooks.js:
    src/hooks.js
    javascript
        
    85 // 'Content-Security-Policy-Report-Only': csp,
    86 'Content-Security-Policy': csp,
    You just comment out line 85 and uncomment line 86.
  • blurry low resolution placeholder image SvelteKit PWA: Lighthouse screenshot showing PWA with a check mark.
    SvelteKit PWA: Lighthouse screenshot: PWA check

    I hope you find that helpful and see how easy it can be to set up a PWA in SvelteKit. If you are interested, we will have a quick look under the hood next to see what makes the PWA work.

    🔧 What’s under the Hood? #

    There are a few elements needed to create a SvelteKit PWA successfully. In this section, we look at them one, by one.

    Manifest and Icons #

    The manifest.webmanifest used by the PWA is created in the server endpoint file src/routes/mafifest.webmanifest/+server.js. This file creates a static manifest (export const prerender = true in line 3 takes care of this):

        
    import website from '$lib/config/website';
    export const prerender = true;
    export const GET = function get({ setHeaders }) {
    const { backgroundColor, description, siteShortTitle, siteTitle, themeColor } = website;
    const manifest = {
    name: siteTitle,
    short_name: siteShortTitle,
    description,
    start_url: '/',
    background_color: backgroundColor,
    theme_color: themeColor,
    display: 'standalone',
    icons: [
    { src: '/icon-192.png', type: 'image/png', sizes: '192x192' },
    { src: '/icon-512.png', type: 'image/png', sizes: '512x512' },
    ],
    };
    setHeaders({
    'content-type': 'application/json',
    });
    return new Response(JSON.stringify(manifest));
    };

    HTML head #

    There are two elements which you need to add to your page HTML head section on all pages. First, is the theme colour which the browser uses to change the address bar to match your site's colour theme . Finally, there is an icon which iOS uses as the Home Screen icon when the user installs your app:

        
    1 <script>
    2 import website from '$lib/config/website';
    3 const { themeColor } = website;
    4 </script>
    5
    6 <svelte:head>
    7 <meta name="theme-color" content={themeColor} />
    8 <link rel="apple-touch-icon" href="%sveltekit.assets%/apple-touch-icon.png" />
    9 </svelte:head>

    This component is included in page layout templates. Because we wrap these elements in a <svelte:head> element, SvelteKit works them in the HTML head section of our page.

    Service Worker #

    The final element is the service worker, which does all the heavy lifting for us in terms of caching data needed for the app to be available offline.

    src/service-worker.js — click to expand code.
    src/service-worker.js
    javascript
        
    1 // based on https://github.com/tretapey/svelte-pwa/blob/master/public/service-worker.js
    2 import { build, files, version } from '$service-worker';
    3
    4 const worker = self;
    5 const CACHE_NAME = `static-cache-${version}`;
    6
    7 const to_cache = build.concat(files);
    8
    9 worker.addEventListener('install', (event) => {
    10 console.log('[ServiceWorker] Install');
    11
    12 event.waitUntil(
    13 caches.open(CACHE_NAME).then((cache) => {
    14 console.log('[ServiceWorker] Pre-caching offline page');
    15 return cache.addAll(to_cache).then(() => {
    16 worker.skipWaiting();
    17 });
    18 }),
    19 );
    20 });
    21
    22 worker.addEventListener('activate', (event) => {
    23 console.log('[ServiceWorker] Activate');
    24 // Remove previous cached data from disk
    25 event.waitUntil(
    26 caches.keys().then(async (keys) =>
    27 Promise.all(
    28 keys.map((key) => {
    29 if (key !== CACHE_NAME) {
    30 console.log('[ServiceWorker] Removing old cache', key);
    31 return caches.delete(key);
    32 }
    33 }),
    34 ),
    35 ),
    36 );
    37 worker.clients.claim();
    38 });
    39
    40 self.addEventListener('fetch', (event) => {
    41 console.log('[ServiceWorker] Fetch', event.request.url);
    42 if (event.request.mode !== 'navigate') {
    43 return;
    44 }
    45 event.respondWith(
    46 fetch(event.request).catch(() => {
    47 return caches.open(CACHE_NAME).then((cache) => {
    48 return cache.match('offline.html');
    49 });
    50 }),
    51 );
    52 });

    Note in line 5 we use the build version in our cache name. This helps us identify when the cached data is stale. Let me know if you would like more detailed explanations on anything here. I based this code on Pedro Sonzini Astudillo's  Svelte service worker.

    🙌🏽 Open Graph SEO in SvelteKit: Wrap Up #

    That's it for this post. We have seen:

    • what a PWA is,
    • how to create a SvelteKit PWA using the MDsveX starter,
    • what's under the hood in the starter's PWA code.

    As always, suggestions for improvements, together with requests for explanations and feedback, are more than welcome. Also, let me know what other features you would like implemented on the starter.

    🙏🏽 SvelteKit PWA: Feedback #

    Have you found the post useful? Would you like to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a couple of dollars, rupees, euros or pounds, please consider supporting me through Buy me a Coffee.

    Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram . Also, see further ways to get in touch with Rodney Lab. I post regularly on SvelteKit as well as other topics. Also, subscribe to the newsletter to keep up-to-date with our latest projects.

    Thanks for reading this post. I hope you found it valuable. Please get in touch with your feedback and suggestions for posts you would like to see. Read more about me …

    blurry low resolution placeholder image Rodney from Rodney Lab
    TAGS:
    SVELTEKIT

    Likes:

    Likes

    • xylys profile avatar
    • Bill Tihen profile avatar
    Likes provided by Mastodon & X via Webmentions.

    Related Posts

    blurry low resolution placeholder image Open Source Favicon Generation & Optimization in 2024

    Open Source Favicon Generation & Optimization in 2024

    optimization
    <PREVIOUS POST
    NEXT POST >
    LATEST POST >>

    Leave a comment …

    Your information will be handled in line with our Privacy Policy .

    Comments

    • Selase

      Hello Rodney, thanks for putting this together. l am yet to install this but very excited about it. Have you tried implementing other PWA features like background sync, offline mode, and push notifications? I would like to hear from you. Regards.

      4 years ago
      • Rodney

        Hi Selase, thanks for getting in touch and for your feedback and ideas! So, the code in the service worker above provides the offline mode. Did you get this to work OK? Nice idea on push notifications, I suppose if they are used sparingly, they can be a good addition to some apps, I will definitely look into writing some content on this. Background sync is also a nice idea, I will see if I can create a video or post on that too. Thanks again for the feedback and happy coding!
        4 years ago
      • Selase

        I did install it. Appeared to pack quite a lot of features. I don't see the service worker running when i inspect it in the browser though. The page also appears to flicker quite often. Let me know when you decide to put some material together on the other topics i mentioned.
        4 years ago
    • Parables Boltnoel

      I think you should change "Blake" and "[email protected]" to "Full Name" and "Email" respectively. That was just by the way, I love how you presented the topic. Excellent post. Looking forward to seeing some great content from you.

      4 years ago
    • Khoa

      Hello, can you explain why I can't see the manifest generation script in the repo even though you said I need to run a command?

      3 years ago
      • Rodney

        Hey Khoa, thanks for reaching out. I updated the underlying repo and instructions referenced the old repo. Should all be in sync now though! Let me know if you still have issues.
        3 years ago
    • Chola

      Great read, what about those of us who'd like to add it to an existing project.

      3 years ago
    • Victor Vickie

      Hi, I recently got into sveltekit and found your blogs informative. I am developing an e-commerce website for my dad. its for local usage, so i have planned to make my site PWA, can i follow the logic provided here for my project https://github.com/VICTORVICKIE/E-Commerce-Client

      3 years ago

    Ask for more

    1 Nov 2022 — Astro Server-Side Rendering: Edge Search Site
    3 Oct 2022 — Svelte eCommerce Site: SvelteKit Snipcart Storefront
    1 Sept 2022 — Get Started with SvelteKit Headless WordPress

    Copyright © 2020 – 2025 Rodney Johnson. All Rights Reserved. Please read important copyright and intellectual property information.

    • Home
    • Profile
    • Plus +
    • Newsletter
    • Contact
    • Links
    • Terms of Use
    • Privacy Policy
    We use cookies  to enhance visitors’ experience. Please click the “Options” button to make your choice.  Learn more here.