svelte-monetization - A minimal and lightweight wrapper for the Web Monetization API 💸
Robert
Posted on May 12, 2020
I've been wanting to learn Svelte and GitHub actions during this period of self-isolation and when I saw the Grant For The Web x DEV hackathon announcement, it sounded like the best time to check these items off my list.
My plan of learning Svelte and GitHub Actions is to create a plugin and publish it to NPM on every push using GitHub Actions.
What I built
I created a minimal and lightweight wrapper for the Web Monetization API in Svelte which will enable developers easily create reusable web monetized content. Thus, developers can concentrate on core application logic.
I cloned a good template for creating Svelte components that includes Rollup and Testing using svelte-testing-library + Jest.
Inside the src/Component.svelte file, where the magic happens, I've added the code below.
<script>import{onMount}from"svelte";letisLoading=true;letisMonetized=false;onMount(()=>{if(!document.monetization){// No web monetization polyfill is installed (e.g. Coil).isLoading=false;isMonetized=false;return;}// Check the value of document.monetization.state// to see if a user is web monetized.const{state}=document.monetization;if(state==="stopped"){// Not currently sending micropayments, nor trying to.isLoading=false;isMonetized=false;}// Determine when Web Monetization has started actively payingdocument.monetization.addEventListener("monetizationstart",event=>{isLoading=false;isMonetized=true;});});</script><slot{isLoading}{isMonetized}/>
With the code above, we can now use this component in our Svelte projects like below.
<script>importSvelteMonetizationfrom"svelte-monetization";</script><!-- Set up your payment pointer --><svelte:head><metaname="monetization"content="$coil.xrptipbot.com/701298d5-481d-40ff-9945-336671ab2c42"/></svelte:head><SvelteMonetizationlet:isLoadinglet:isMonetized>
{#if isLoading}
<div>Loading message here</div>
{:else if isMonetized}
<div>Monetized/premium content here</div>
{:else}
<div>Show ads here</div>
{/if}
</SvelteMonetization>
There are two things that I want to notice:
The <svelte:head> element. This allows us to insert elements inside the <head> of our document.
The let directive in the SvelteMonetization component. We use this to expose our isLoading and isMonetized states from the Component.svelte so that we can use it to conditionally render some markup.
Easy peasy, right? How about Web Monetization browser events? Should we implement our own?
Thanks to Svelte component events, we can refactor our code to dispatch browser events from the monetization API.
<script>import{onMount,createEventDispatcher}from"svelte";// createEventDispatcher must be called when the component is first instantiatedconstdispatch=createEventDispatcher();letisLoading=true;letisMonetized=false;onMount(()=>{if(!document.monetization){isLoading=false;isMonetized=false;return;}const{state}=document.monetization;if(state==="stopped"){isLoading=false;isMonetized=false;}// Since monetization events always start with the monetization word,// we can just loop over the event names to make our code shorter.constevents=["start","progress","pending","stop"];events.forEach(name=>{document.monetization.addEventListener("monetization"+name,event=>{dispatch(name,event.detail);if(name==="start"){isLoading=false;isMonetized=true;}});});});</script>
How can we listen to events in our SvelteMonetization element? Just add an on directive plus the name of the event.
<script>import{onMount}from"svelte";importSvelteMonetizationfrom"svelte-monetization";functionhandleProgress(event){// you can use this to save micropayments// to your own databaseconsole.log("progress",event.detail);}</script><SvelteMonetizationlet:isLoadinglet:isMonetizedon:progress={handleProgress}>
{#if isLoading}
<div>Loading message here</div>
{:else if isMonetized}
<div>Monetized/premium content here</div>
{:else}
<div>Show ads here</div>
{/if}
</SvelteMonetization>
Deployment
Next, we want to automatically publish a new version of our package when creating a new release on GitHub. So it's now a good time to learn and use GitHub Actions.
Now we need to configure the steps of the job, this is what it does:
Get access to the repository files.
Install Node.js, with the version 12 and using the registry URL of npm, this could be changed to a custom registry or the GitHub registry.
Run the npm ci command to install the package dependencies.
Run the npm publish command, this command is also run with the environment variable NODE_AUTH_TOKEN whose value is a secret configured in the repository called NPM_AUTH_TOKEN.
Finally, we can install the component in our Svelte applications by running