Svelte Share Buttons: using Web Share API with Fallback
Tags: webdev, svelte, javascript
Published: 2022-04-13 16:11:15

---
title: "Svelte Share Buttons: using Web Share API with Fallback"
published: "true"
description: "Svelte share buttons: adding social share buttons to your Svelte app for mobiles and Safari using the native Web Share API with fallbacks."
tags: "webdev, svelte, javascript"
canonical_url: "https://rodneylab.com/svelte-share-buttons/"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dj8irwmfjkrb4ixqj40h.png"
---

## 🤗 What is the Web Share API?

In this post we see how you can add **Svelte share buttons** to your Svelte-based app.  We will follow a **roll-your-own** approach here using inbuilt browser APIs, rather than adding extra packages or dependencies. We will work in **SvelteKit** though our Svelte components can just as easily be used in **Slinkity** or **Astro** Svelte apps.

We add buttons, to a blog starter, which let site visitors share blog posts with their friends and followers on **WhatsApp**, **Telegram** and **Twitter** as well as **Facebook**. That functionality works in any browser, relying on just JavaScript. As well as that, we make use of the relatively new **Web Share API**.  On the visitor’s mobile; this will bring up a menu, making it easy to share your site on any suitable apps they have installed.  We are going for a **progressive enhancement** approach.  This means mobile (and Safari on desktop) will show the Web Share API button, while browsers yet to support it will show our share buttons instead.

## 🧱 What we&rsquo;re Building

I mentioned we are working in SvelteKit <a href="https://rodneylab.com/sveltekit-blog-starter/">using the MDsveX blog starter</a>.  If Astro is your preferred tool for building Svelte sites, <a href="https://github.com/rodneylab/astro-blog-markdown" rel="follow noopener noreferrer">start with the Astro Svelte Markdown starter</a> instead.  Of course, if you have an existing Svelte app, you can create a feature branch and add this functionality there.  Anyway to start let&rsquo;s clone a repo:

```shell
git clone https://github.com/rodneylab/sveltekit-blog-mdx.git sveltekit-share-buttons
cd sveltekit-share-buttons
pnpm install
cp .env.EXAMPLE .env
pnpm run dev
```

With that done, we will start by adding the fallback share button functionality.  We will run through adding Twitter in detail, then sketch over adding other networks.  If you want to add a popular network not mentioned, drop a comment below and I will see what I can do.  Equally feel free to submit a pull request to the repo if you code up support for a well-known network, not already implemented.

## 🧩 Initial Share Button Component

To get the ball rolling, let&rsquo;s create a `src/lib/components/ShareButtons` folder and inside it add an `index.svelte` file.  This file will ultimately contain the logic for the Web Share progressive enhancement as well as the fallbacks. **Progressive enhancement** expresses a similar sentiment to *graceful degradation*.  The idea is we want to support a new feature which does not currently enjoy wide support.  We have a baseline which supports all (or most) devices, then the progressive enhancement offers the new feature, but only where the user device supports it.

To get going, paste this code into the new file:

```html
<script>
  import Twitter from '$lib/components/ShareButtons/Twitter.svelte';
  import website from '$lib/config/website';

  const { siteUrl } = website;

  export let slug;
  export let title;

  const url = `${siteUrl}/${slug}`;
</script>

<aside aria-label="Share buttons" class="container">
  <div class="wrapper">
    Share: <div class="buttons">
        <Twitter {url} {title} />
    </div>
  </div>
</aside>
```

Here is some optional styling which you can paste at the end of the file:

```html
<style lang="scss">
  .container {
    display: flex;
    flex-direction: row;
    margin-top: $spacing-12;
    width: $max-width-full;
  }
  .wrapper {
    display: flex;
    flex-direction: row;
    margin-left: auto;
    font-weight: $font-weight-bold;
    font-size: $font-size-2;
  }
  .buttons {
    margin-left: $spacing-4;
  }

  button {
    background: transparent;
    border-style: none;
    transition: all 0.2s ease-in-out;
  }

  @media (prefers-reduced-motion: reduce) {
    button {
      transition: all 2s ease-in-out;
    }
  }

  button:focus,
  button:hover {
    transform: scale(1.1);
  }
</style>
```

This will not work yet &mdash; we need to create the Twitter share button component.  Nonetheless, let&rsquo;s add the `ShareButton` component to our blog post template now:

```html
<script>
  import BannerImage from '$lib/components/BannerImage.svelte';
  import SEO from '$lib/components/SEO/index.svelte';
  import ShareButtons from '$lib/components/ShareButtons/index.svelte';
  import readingTime from 'reading-time';
```

```html
<BannerImage {imageData} />
<h1>{title}</h1>
<ShareButtons {slug} {title} />
```

With that basic wiring up done, we will next create the Twitter share button component.  The other components work in a similar way, though the Twitter API supports the most customisation, so it provides a good starting point.

## 🐦 Twitter Share Button Component

This button will be part of the fallback; as such, we will not show it on devices which support the Web Share API.  Currently on MacOS, Safari **does** support the API, so test this part in Firefox and Chrome.  The Twitter code, together with the other share button components are based off the <a href="https://github.com/nygardk/react-share">nygardk/react-share</a> GitHub repo by Klaus Nygård.

```html
<script>
  import TwitterIcon from '$lib/components/Icons/Twitter.svelte';

  export let hashtags = []; // array of hashtags exclude '#' e.g. ['svelte', 'askRodney']
  export let quote = undefined;
  export let related = []; // array of Twitter users (including '@')
  export let title; // text in Tweet
  export let url;
  export let via = ''; // include '@' e.g. '@askRodney'

  const TWITTER_BLUE = '#00aced';

  const baseUrl = 'https://twitter.com/share';
  const parametersObject = {
    url,
    ...(hashtags.length > 0 ? { hashtags: hashtags.join(',') } : {}),
    quote,
    text: title,
    ...(related.length > 0 ? { related: related.join(',') } : {}),
    ...(via.length > 0 ? { via: via.slice(1) } : {}),
  };

  const params = Object.entries(parametersObject)
    .filter(([, value]) => value ?? false)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
    .join('&');

  const urlWithParameters = params === '' ? baseUrl : `${baseUrl}?${params}`;

  function handleClick() {
    const config = {
      height: 550,
      width: 400,
      location: 'no',
      toolbar: 'no',
      status: 'no',
      directories: 'no',
      menubar: 'no',
      scrollbars: 'yes',
      resizable: 'no',
      centerscreen: 'yes',
      chrome: 'yes',
    };
    return window.open(
      urlWithParameters,
      '',
      Object.keys(config)
        .map((key) => `${key}=${config[key]}`)
        .join(','),
    );
  }
</script>

<button on:click={handleClick}
  ><span class="screen-reader-text">Share on Twitter</span><TwitterIcon
    colour={TWITTER_BLUE}
    width={48}
  /></button
>

<style lang="scss">
  button {
    background: transparent;
    border-style: none;
    transition: all 0.2s ease-in-out;
  }
  @media (prefers-reduced-motion: reduce) {
    button {
      transition: all 2s ease-in-out;
    }
  }

  button:focus,
  button:hover {
    transform: scale(1.1);
  }
  @media screen and (max-width: $desktop-breakpoint) {
    button {
      padding-left: $spacing-2;
      padding-right: $spacing-2;
    }
  }
</style>
```

In line `2` we import an iconify Twitter icon already used in the project.  It is fairly easy to add icons from dozens of libraries using iconify.  In fact this post is a follow-up to an <a aria-label="Open post on using SVG icons in Svelte Kit" href="https://rodneylab.com/sveltekit-svg-icons/">earlier post which tells you exactly how to gain access to over 100,000 SVG icons using a single package</a>.  So jump back there when you want to see how to add icons to your own project.

The Twitter API has most bells and whistles: you can include **hashtags**, **quotes** and **related accounts** as well as **a via** Twitter account.  I have added some comments in the code to explain how to use these.  Here, we&rsquo;ll just focus on adding the text (`title` prop) and URL.

### Twitter Customisations

Lines `14`&ndash;`21` (above) build up the query parameters for the URL which we need to send to Twitter to share the post.  Because this is a URL, some characters are not allowed and we have to encode them.  In line `25`, we make use of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent">`encodeURIComponent` to URL encode the keys and parameters</a> for us.

The `handleClick` code in lines `30`&ndash;`51` brings up a new window on Twitter&rsquo;s site which lets the visitor log in (if they are not already logged in) and share.  The sizes are sensible defaults which work on different sized devices, so you will probably not need to adjust these.

The other components will be similar, though with differing `baseUrl` (see line `13`).  For improved accessibility, include some screen reader text on all buttons (as in line `55`).  This will not be visible, though screen readers will announce it, helping screen reader users  know what the button does.

## 🔘 Other Network Buttons

We will skim over the other networks now, in fact, we will only point out details which are different. Then in the following section we will add them into the principal component and also wire up the Web Share API.

### Facebook

```html
<script>
  import FacebookIcon from '$lib/components/Icons/Facebook.svelte';
  export let hashtag = '';
  export let quote = '';
  export let url;

  const FACEBOOK_BLUE = '#3b5998';

  const baseUrl = 'https://www.facebook.com/sharer/sharer.php';
  const parametersObject = {
    u: url,
    ...(quote !== '' ? { quote } : {}),
    ...(hashtag !== '' ? { hashtag } : {}),
  };

  const params = Object.entries(parametersObject)
    .filter(([, value]) => value ?? false)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
    .join('&');

  const urlWithParameters = params === '' ? baseUrl : `${baseUrl}?${params}`;

  function handleClick() {
    const config = {
      height: 550,
      width: 400,
      location: 'no',
      toolbar: 'no',
      status: 'no',
      directories: 'no',
      menubar: 'no',
      scrollbars: 'yes',
      resizable: 'no',
      centerscreen: 'yes',
      chrome: 'yes',
    };
    return window.open(
      urlWithParameters,
      '',
      Object.keys(config)
        .map((key) => `${key}=${config[key]}`)
        .join(','),
    );
  }
</script>

<button on:click={handleClick}
  ><span class="screen-reader-text">Share on Facebook</span><FacebookIcon
    colour={FACEBOOK_BLUE}
    width={48}
  /></button
>

<style lang="scss">
  button {
    background: transparent;
    border-style: none;
    transition: all 0.2s ease-in-out;
  }

  @media (prefers-reduced-motion: reduce) {
    button {
      transition: all 2s ease-in-out;
    }
  }

  button:focus,
  button:hover {
    transform: scale(1.1);
  }

  @media screen and (max-width: $desktop-breakpoint) {
    button {
      padding-left: $spacing-2;
      padding-right: $spacing-2;
    }
  }
</style>
```

### Telegram

```html
<script>
  import TelegramIcon from '$lib/components/Icons/Telegram.svelte';

  export let url;
  export let title;

  const TELEGRAM_BLUE = '#49a9e9';

  const baseUrl = 'https://telegram.me/share/url';
  const parametersObject = {
    url,
    text: title,
  };

  const params = Object.entries(parametersObject)
    .filter(([, value]) => value ?? false)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
    .join('&');

  const urlWithParameters = params === '' ? baseUrl : `${baseUrl}?${params}`;

  function handleClick() {
    const config = {
      height: 550,
      width: 400,
      location: 'no',
      toolbar: 'no',
      status: 'no',
      directories: 'no',
      menubar: 'no',
      scrollbars: 'yes',
      resizable: 'no',
      centerscreen: 'yes',
      chrome: 'yes',
    };
    return window.open(
      urlWithParameters,
      '',
      Object.keys(config)
        .map((key) => `${key}=${config[key]}`)
        .join(','),
    );
  }
</script>

<button on:click={handleClick}
  ><span class="screen-reader-text">Share on Telegram</span><TelegramIcon
    colour={TELEGRAM_BLUE}
    width={48}
  /></button
>

<style lang="scss">
  @import '../../styles/variables';

  button {
    background: transparent;
    border-style: none;
    transition: all 0.2s ease-in-out;
  }

  @media (prefers-reduced-motion: reduce) {
    button {
      transition: all 2s ease-in-out;
    }
  }

  button:focus,
  button:hover {
    transform: scale(1.1);
  }

  @media screen and (max-width: $desktop-breakpoint) {
    button {
      padding-left: $spacing-2;
      padding-right: $spacing-2;
    }
  }
</style>
```

### WhatsApp

```html
<script>
  import { browser } from '$app/env';
  import WhatsappIcon from '$lib/components/Icons/Whatsapp.svelte';
  import { isMobileOrTablet } from '$lib/utilities/device';

  const WHATSAPP_GREEN = '#25D366';

  export let url;
  export let title;

  const baseUrl =
    browser && isMobileOrTablet()
      ? 'https://api.whatsapp.com/send'
      : 'https://web.whatsapp.com/send';
  const parametersObject = {
    text: title ? title + ' ' + url : url,
  };

  const params = Object.entries(parametersObject)
    .filter(([, value]) => value ?? false)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
    .join('&');

  const urlWithParameters = params === '' ? baseUrl : `${baseUrl}?${params}`;

  function handleClick() {
    const config = {
      height: 550,
      width: 400,
      location: 'no',
      toolbar: 'no',
      status: 'no',
      directories: 'no',
      menubar: 'no',
      scrollbars: 'yes',
      resizable: 'no',
      centerscreen: 'yes',
      chrome: 'yes',
    };
    return window.open(
      urlWithParameters,
      '',
      Object.keys(config)
        .map((key) => `${key}=${config[key]}`)
        .join(','),
    );
  }
</script>

<button on:click={handleClick}
  ><span class="screen-reader-text">Share on Whatsapp</span><WhatsappIcon
    colour={WHATSAPP_GREEN}
    width={48}
  /></button
>

<style lang="scss">
  button {
    background: transparent;
    border-style: none;
    transition: all 0.2s ease-in-out;
  }
  @media (prefers-reduced-motion: reduce) {
    button {
      transition: all 2s ease-in-out;
    }
  }

  button:focus,
  button:hover {
    transform: scale(1.1);
  }

  @media screen and (max-width: $desktop-breakpoint) {
    button {
      padding-left: $spacing-2;
      padding-right: $spacing-2;
    }
  }
</style>
```

There is not already a WhatsApp icon in the starter.  Add this code, or create your own using your preferred icon set:

```html
<script>
  import Icon, { addCollection } from '@iconify/svelte/dist/OfflineIcon.svelte';

  export let label = 'Whatsapp icon';
  export let colour = 'inherit';
  export let ariaHidden = false;
  export let width = 48;

  addCollection({
    prefix: 'simple-icons',
    icons: {
      whatsapp: {
        body: '<path fill="currentColor" d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967c-.273-.099-.471-.148-.67.15c-.197.297-.767.966-.94 1.164c-.173.199-.347.223-.644.075c-.297-.15-1.255-.463-2.39-1.475c-.883-.788-1.48-1.761-1.653-2.059c-.173-.297-.018-.458.13-.606c.134-.133.298-.347.446-.52c.149-.174.198-.298.298-.497c.099-.198.05-.371-.025-.52c-.075-.149-.669-1.612-.916-2.207c-.242-.579-.487-.5-.669-.51a12.8 12.8 0 0 0-.57-.01c-.198 0-.52.074-.792.372c-.272.297-1.04 1.016-1.04 2.479c0 1.462 1.065 2.875 1.213 3.074c.149.198 2.096 3.2 5.077 4.487c.709.306 1.262.489 1.694.625c.712.227 1.36.195 1.871.118c.571-.085 1.758-.719 2.006-1.413c.248-.694.248-1.289.173-1.413c-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214l-3.741.982l.998-3.648l-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884c2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413Z"/>',
      },
    },
    width: 24,
    height: 24,
  });

  // https://api.iconify.design/simple-icons.json?icons=whatsapp
</script>

<Icon icon="simple-icons:whatsapp" {ariaHidden} aria-label={label} color={colour} {width} />
```

Also for WhatsApp, there are different API URLs depending on whether the visitor is using a mobile device or not.  We make use of a utility function to check the type of device the user has.  Create this file if you added the WhatsApp share button code above to your app:

```javascript
/**
 * Returns true if the device is thought to be a mobile or tablet
 * @returns {boolean}
 */
export function isMobileOrTablet() {
  return /(android|iphone|ipad|mobile)/i.test(navigator.userAgent);
}
```

## 🔨 Pulling it all Together

We are going back to `src/lib/components/ShareButtons/index.svelte` now to tie the new buttons in.  Feel free to omit any networks you will not need on your app here.  

```html
<script>
  import Facebook from '$lib/components/ShareButtons/Facebook.svelte';
  import Telegram from '$lib/components/ShareButtons/Telegram.svelte';
  import Twitter from '$lib/components/ShareButtons/Twitter.svelte';
  import Whatsapp from '$lib/components/ShareButtons/Whatsapp.svelte';
  import website from '$lib/config/website';

  const { siteUrl } = website;

  export let slug;
  export let title;

  const url = `${siteUrl}/${slug}`;
</script>

<aside aria-label="Share buttons" class="container">
  <div class="wrapper">
    Share: <div class="buttons">
        <Twitter {url} {title} /><Facebook {url} /><Whatsapp {url} {title} />
        <Telegram {url} {title} />
    </div>
  </div>
</aside>
```
I think it will be clear what we are doing here, but let me know if I have forgotten to explain something!

## 🕸 Web Share API

The final missing piece is the Web Share button.  We will add a `webShareAPISupported` boolean variable with a <a aria-label="Open Svelte tutorial on reactive declarations" href="https://svelte.dev/tutorial/reactive-declarations">reactive declaration</a>.  This needs access to the browser `navigator` object so will not work when the code is running server-side.  SvelteKit provides the `browser` variable defined in `$app/env` which we make use of here.  If you are working in Astro, check for `ssr` using this snippet:

```javascript
// ASTRO ONLY - IGNORE FOR SVELTEKIT
const ssr = import.meta.env.SSR;
```

Remember when `browser` in the SvelteKit code is `true`, `ssr` will be false (and vice verse).

Anyway, let&rsquo;s update the file:

```html
<script>
  import { browser } from '$app/env';
  import ShareIcon from '$lib/components/Icons/Share.svelte';
  import Facebook from '$lib/components/ShareButtons/Facebook.svelte';
  import Telegram from '$lib/components/ShareButtons/Telegram.svelte';
  import Twitter from '$lib/components/ShareButtons/Twitter.svelte';
  import Whatsapp from '$lib/components/ShareButtons/Whatsapp.svelte';
  import website from '$lib/config/website';

  const { siteTitle, siteUrl } = website;

  export let slug;
  export let title;

  $: webShareAPISupported = browser && typeof navigator.share !== 'undefined';

  $: handleWebShare;
  const handleWebShare = async () => {
    try {
      navigator.share({
        title,
        text: `Shared from ${siteTitle}`,
        url,
      });
    } catch (error) {
      webShareAPISupported = false;
    }
  };
  const url = `${siteUrl}/${slug}`;
</script>

<aside class="container">
  <div class="wrapper">
    Share: <div class="buttons">
      {#if webShareAPISupported}
        <button on:click={handleWebShare}
          ><span class="screen-reader-text">Share</span><ShareIcon width={48} /></button
        >
      {:else}
        <Twitter {url} {title} /><Facebook {url} /><Whatsapp {url} {title} />
        <Telegram {url} {title} />{/if}
    </div>
  </div>
</aside>
```

In line `17` we declare the `handleWebShare` function as reactive, using the dollar syntax.  This will let the interface update if, in line `26`, the function sets `webShareAPISuported` to `false`.

### What have we got here?

In lines `35`&ndash;`41`, we have a guard so if `webShareAPISupported` is `false`, the user will see the share buttons we previously defined.  On the other hand, if it is `true`, the user sees the share button which we will add in a moment.

When the use clicks or taps the share button, the `handleWebShare` function is invoked.  This is asynchronous so it is best practice to include `try`/`catch` blocks.  If for some reason the share fails, there is no issue! Remember we have our fallback, so just show the share buttons for the networks we added initially. Lines `20`&ndash;`24` have the core Web Share code.

### Sharing via the API

The <a aria-label="Read more about the Web Share A P I from web dot dev" href="https://web.dev/web-share/">Web Share API lets users share links, text and files</a>.  We focus on sharing text and links here.  To share a file, just add an extra `files` field to the share object.  We share both a link and some related text.  You can opt to share either one of these on its own and drop the other (some browsers do not yet support text though).  You see the API is fairly simple and there is not much more left to explain&hellip; the browsers do all the heavy lifting!  The final thing worth a mention is the check for support in line `15`.  To check the <a aria-label="Open M D N Web Share A P I docs" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API#browser_compatibility">latest browser support see MDN Web Share API docs</a>.

### Share Icon

Before we can test, we need to put the missing share icon into the project (feel free to swap this out, using your preferred collection):

```html
<script>
  import Icon, { addCollection } from '@iconify/svelte/dist/OfflineIcon.svelte';

  export let label = 'Share icon';
  export let colour = 'inherit';
  export let ariaHidden = false;
  export let width = 24;

  addCollection({
    prefix: 'simple-line-icons',
    icons: {
      share: {
        body: '<path fill="currentColor" d="M864 704c-52.688 0-99.295 25.585-128.431 64.88l-421.36-214.72c3.664-13.455 5.792-27.535 5.792-42.16c0-18.303-3.216-35.807-8.88-52.175l423.76-205.616C763.97 294.016 810.897 320 864.001 320c88.367 0 160-71.649 160-160c0-88.368-71.633-160-160-160S704 71.633 704 160c0 12.431 1.567 24.464 4.24 36.08L278.4 404.657c-29.281-32.273-71.393-52.656-118.4-52.656C71.631 352 0 423.633 0 512c0 88.351 71.631 160 160 160c50.895 0 96.127-23.824 125.423-60.865l423.104 215.632C705.664 838.736 704 851.152 704 864c0 88.368 71.632 160 160 160s160-71.632 160-160s-71.632-160-160-160zm.002-639.999c53.008 0 96 42.992 96 96s-42.992 96-96 96s-96-42.992-96-96s42.992-96 96-96zm-704 544c-53.024 0-96-42.992-96-96s42.976-96 96-96c53.008 0 96 42.992 96 96s-42.992 96-96 96zm704 352c-53.008 0-96-42.992-96-96s42.992-96 96-96s96 42.992 96 96s-42.992 96-96 96z"/>',
      },
    },
    width: 1024,
    height: 1024,
  });

  // https://api.iconify.design/simple-line-icons.json?icons=share
</script>

<Icon icon="simple-line-icons:share" {ariaHidden} aria-label={label} color={colour} {width} />
```

## 💯 Svelte Share Buttons: Test

You should now be able to see the share buttons if you open any of the blog posts in a browser. To test on desktop, at the time of writing the WebShare API was not supported on Firefox and Chrome, so these are good for testing the fallback buttons.  Safari on desktop does support the Web Share API so is fantastic for testing that button.  Also try deploying your app to a staging environment to test a few mobile browsers.

## 🙌🏽 Svelte Share Buttons: Wrapup

**In this post we looked at**:

- how to add share buttons to a Svelte app with progressive enhancement,
- using the Web Share API to share from a Svelte app,
- adding fallback share icons with iconify.

I do hope there is at least one thing in this article which you can use in your work or a side project. Also let me know if you feel more explanation of the config is needed.

This post came from a request in a comment on another post, so do drop a comment below if there is something else you would like to see a video or post on.

You can see <a aria-label="Open the Rodney Lab Git Hub repo" href="https://github.com/rodneylab/sveltekit-share-buttons" rel="follow noopener noreferrer">the full SvelteKit code for this project on the Rodney Lab Git Hub repo</a>.  If you run into any issues, you can drop a comment below as well as reach out for a chat on <a aria-label="Jump into the Element Matrix chat room" href="https://matrix.to/#/%23rodney:matrix.org">Element</a>.  Also <a aria-label="Mention on Twitter" href="https://twitter.com/intent/user?screen_name=@askRodney">Twitter @mention</a> if you have suggestions for improvements or questions.

## 🙏🏽 Feedback

If you have found this video useful, see links below for further related content on this site. I do hope you learned one new thing from the video. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on Twitter, giving me a mention so I can see what you did. Finally be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please <a aria-label="Support Rodney Lab via Buy me a Coffee" href="https://rodneylab.com/giving/">consider supporting me through Buy me a Coffee</a>.

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 <a aria-label="Reach out on Twitter" href="https://twitter.com/messages/compose?recipient_id=1323579817258831875">@askRodney</a> on Twitter and also <a aria-label="Contact Rodney Lab via Telegram" href="https://t.me/askRodney">askRodney on Telegram</a>. Also, see <a aria-label="Get in touch with Rodney Lab" href="https://rodneylab.com/contact">further ways to get in touch with Rodney Lab</a>. I post regularly on <a aria-label="See posts on svelte kit" href="https://rodneylab.com/tags/sveltekit/">SvelteKit</a> as well as <a href="https://rodneylab.com/tags/seo" aria-label="See posts on search engine optimisation">Search Engine Optimisation</a> among other topics. Also <a aria-label="Subscribe to the Rodney Lab newsletter" href="https://rodneylab.com/about/#newsletter">subscribe to the newsletter to keep up-to-date</a> with our latest projects.