Programming – closingtags </>
Categories
Javascript Programming Svelte SvelteKit

JS Party podcast

I recently had the pleasure of being a guest on the fantastic JS Party podcast. It was great chatting with Nick and Adrienne about what goes into writing a technical book. If you’ve ever been curious about writing your own book, this episode is a must-listen!

JS Party 314: Take a look, it’s in a book – Listen on Changelog.com

If podcasts aren’t your thing, I’ve previously written about what the process of writing a book was like for me.

Categories
HTML5 Javascript Linux PHP Programming Python

Remote Debugging Web Apps on iOS from Linux

Debugging #WebApps on #iOS is a super easy if you have a Macbook. If you’re on #Linux, it’s not. This post documents how I got around that limitation by using #OpenSource utilties and tools.

Categories
CSS HTML5 Javascript Programming SvelteKit WordPress

Accessibility for Lazy Developers

I’m lazy and you probably are too. This post talks about a few easy-to-use tools that even the laziest of developers can use to ensure their application is accessible to all.

#a11y #accessibility #automation

Categories
Javascript Programming Svelte SvelteKit

Enabling Persistent Storage in IndexedDB

Exploring how to mark #IndexedDB storage as persistent for an offline first #PWA built with #SvelteKit

Categories
CSS Javascript Programming Svelte SvelteKit

Tailwind CSS + SvelteKit = ❤️ && 💔

In an effort to promote my upcoming book, I created the website https://sveltekitbook.dev. It has all of the information one may want to know before purchasing a copy. Of course, the book is about #SvelteKit so I had to build the site using #SvelteKit. I decided to take the opportunity to learn the latest technology web developers can’t shut up about; #TailwindCSS.

Categories
Javascript Programming Svelte SvelteKit

Why I Quit Writing

In my last post, I prefaced it by saying that I haven’t been posting here often because I’ve been busy. In reality, I only missed a single post back in May so I guess you could say that I haven’t actually quit writing.
(But you’ve already clicked the link and are reading the post so the bait worked, right? Might as well stick around for the rest.) 😎
In fact, I’ve doubled down on the writing because the latest project that has been keeping me so incredibly busy has been…
…writing my first book!
SvelteKit Up and Running
That’s right! An entire book made out of paper and ink like they used to have back in the ye olden days. Of course, there will be digital copies for you technology enthusiasts as well. The book is titled SvelteKit Up and Running: Building High Performance Web Apps with a Next Generation Framework. It is obviously about SvelteKit, the highly performant web application meta framework from the creators of Svelte. I wrote it because I wanted to give others the resource I wish I had when I was learning how to build web apps with Svelte and SvelteKit.
Whether you’re new to JavaScript development and are wondering which framework to pick up first, or are a seasoned developer tired of the bloat that comes with other popular frameworks; this book will teach you the concepts behind the project leading the field in revolutionizing JavaScript development. The examples found throughout the book are concise, practical, and easy to follow along with while still effectively demonstrating how to leverage the various techniques necessary for implementing features commonly found in web applications.
Pre-order

As of this writing, the book is currently trending #3 on Amazon! How wild is that?

If you’re interested in getting a copy (and I hope you are), it’s available for pre-order now at https://packt.link/bVAyJ! The book is scheduled for release on July 28th, 2023.
Want more?
If you’re curious about what it takes to write a book, the process behind it, how I got started, and lessons I learned, then be sure to subscribe to this site’s RSS feed, follow me on Telegram, or find me in the Fediverse. I’ll be posting more updates as well as outlining my experience throughout the entirety of this project!

Categories
Programming Security

Recovering Corrupted .docx Files

Did you know that files with the extension .docx are really just .zip packages?

#LibreOffice #Word #Office

Categories
Javascript Programming Security Server Svelte

2022 Recap

I know its cliché to ask it but I’m going to anyways; where did the year go? It feels like just yesterday, I was writing about setting up a Node & MongoDB with Docker Compose.

#2022 #Recap #FullStack #WebDev

Categories
Automation CSS HTML5 Javascript Linux Mobile PHP Programming Security Server Svelte WordPress

BUY! BUY! BUY!

I’ve been writing on this blog for nearly 9 years and I’ve learned so much since I started. The style and the content have come a long ways and I cringe every time I read old posts thoroughly enjoy seeing how I’ve grown as a developer. I’ve interacted with people that I never would have had the chance to otherwise. It’s been a wonderful learning experience.
While my intentions have always been for this site to exist as a sort of journal/wiki/knowledgebase/playground, I’ve always secretly wanted to become a billionaire tech influencer. And now you can help me achieve that goal by buying my merchandise!
BUY! BUY! BUY!
By purchasing merchandise from my shop, you can support this site financially, by giving me real money that you’ve earned for your “hard work.” While donations are always appreciated, I understand that you may want something in return; something tangible, something you can see and smell, something to keep you comfortable while you cry yourself to sleep. And since nobody actually donates to strangers on the internet, I opened a shop.

All of the designs are completely original and there are many, many more to come. The pricing is affordable for all budgets and will only expand with more options. Be sure to check posts here often by following the social media channels or the RSS feed. There may just be coupon codes hidden in future posts 😉.
So if you’re ready to showcase the fact that you know what HTML is and like the look of monospaced fonts, then you should go checkout the new closingtags merch shop. Once you’ve got the closingtags swag (closingswag 🤔), be prepared to have people you barely know ask if you “work with computers” or to tell you about their genius new app idea.
Don’t forget to buy, buy, buy!

Categories
Javascript Programming Svelte

Svelte stores in IndexedDB

I know that I just wrote a post about using Svelte Stores with localStorage but very shortly after writing that (and implementing it in my own app 🤦), I came across this blog post from Paul Maneesilasan which explained the benefits of using IndexedDB:

So, the primary benefits to using a datastore like indexedDB are: larger data storage limits (50MB), non-blocking operations, and the ability to do db operations beyond simple read/writes. In my case, the first two alone are enough to switch over.
https://www.paultman.com/from-localstorage-to-indexeddb/
Since I had some fresh ideas for my own app about storing lots of data that could potentially would definitely go over the Web Storage 5-10MB limit, I dug even deeper into the research. In the end, I too decided to make the switch.
Sexy Dexie
The documentation for IndexedDB can be overwhelming. It’s great how thorough it is, but I found it difficult to read. After spending a few hours trying to understand the basics, getting bored, looking at memes, and finally remembering what I was supposed to be doing, I came across a package called Dexie. Dexie is a wrapper for IndexedDB, which means that it will make calls to the database for me; for instance Table.add(item) will insert the item object on the specified table. This greatly reduced my need to build that functionality myself. Since I hate reinventing the wheel (and my brain can only learn so many things in a day), I opted to use this package to manage the database. Plus, Dexie has a handy tutorial for integrating with Svelte and makes managing database versions a breeze.
While the Dexie + Svelte tutorial is great, including Dexie in each and every component that gets and sets data (like the tutorial does) would be cumbersome. It would be far simpler to use Svelte stores across components, and have the stores talk to IndexedDB via Dexie.
Custom Stores
Since IndexedDB; and therefore Dexie, utilize asynchronous APIs, a few things need to be done differently to integrate with Svelte stores. Firstly, we can’t just “get the values” from the database and assign them to a writable store (like we did in the localStorage example) since we’ll be receiving a Promise from Dexie. Secondly, when the data is updated in the store, we also need to update the data in the database; asynchronously.
This is where custom stores come in. In a custom store, we can create our very own methods to manage getting and setting data. The catch is that the store must implement a subscribe() method. If it needs to be a writable store, then it also needs to implement a set() method. The set() method will be where the magic happens.
To get started, follow Dexie’s installation instructions (npm install dexie) and create a db.js file to initialize the database. I’ve added a couple methods to mine to keep database functionality organized:
Note that is generic code sampled from helth app so references to water, calories, and sodium are done in the context of a health tracker.
import { Dexie } from ‘dexie’;
// If using SvelteKit, you’ll need to be
// certain your code is only running in the browser
import { browser } from ‘$app/environment’;

export const db = new Dexie(‘helthdb’);

db.version(1).stores({
journal: ‘date, water, calories, protein, sodium’,
settings: ‘name, value’,
});

db.open().then((db) => {
// custom logic to initialize DB here
// insert default values
};

export const updateLatestDay = (date, changes) => {
if(browser) {
return db.journal.update(date, changes);
}
return {};
};

export const getLatestDay = () => {
if(browser) {
return db.journal.orderBy(‘date’).reverse().first();
}
return {};
};

export const updateItems = (tableName, items) => {
if(browser) {
// .table() allows specifying table name to perform operation on
return db.table(tableName).bulkPut(items);
}
return {};
}

export const getItems = (tableName) => {
// spread all of the settings records onto one object
// so the app can use a single store for all settings
// this table has limited entries
// would not recommend for use with large tables
if(browser) {
return db.table(tableName).toArray()
.then(data => data.reduce((prev, curr) => ({…prev, [curr.name]: curr}), []));
// credit to Jimmy Hogoboom for this fun reducer function
// https://github.com/jimmyhogoboom
}
return {};
}
I won’t go over this file because it’s self explanatory and yours will likely be very different. After you have a database, create a file for the stores (stores.js).
import * as dbfun from ‘$stores/db’;
import { writable } from ‘svelte/store’;

// sourced from https://stackoverflow.com/q/69500584/759563
function createTodayStore() {

const store = writable({});

return {
…store,
init: async () => {
const latestDay = dbfun.getLatestDay();
latestDay.then(day => {
store.set(day);
})
return latestDay;
},
set: async (newVal) => {
dbfun.getLatestDay()
.then(day => {
dbfun.updateLatestDay(day.date, newVal);
});
store.set(newVal);
}
}
}

function createNameValueStore(tableName) {
const store = writable({});

return {
…store,
init: async () => {
const items = dbfun.getItems(tableName);
items.then(values => {
store.set(values);
})
return items;
},
set: async (newVal) => {
dbfun.updateItems(tableName, Object.keys(newVal).map((key) => {
return {name: key, value: newVal[key].value}
}));
store.set(newVal);
}
}
}
export const today = createTodayStore();
export const settings = createNameValueStore(‘settings’);
Here’s break down what this does:

Import the db.js file and any extra functionality added to it.
Import { writable } from svelte/store since we’ve already established that I hate reinventing the wheel.
Create 2 functions; createTodayStore() and createNameValueStore(). Both functions are mostly identical except for the logic they call on the database.
Each function then creates their own store from writable with an empty object as the default value.
Both functions return an object that adheres to the store contract of Svelte by implementing all the functionality of writable, overriding set(), and adding a custom method init().
init() queries the database asynchronously, sets the value of the store accordingly, then returns the Promise received from Dexie.
set() updates the data within the database given to the store and then proceeds to set the store accordingly.
Export the stores.

Accessing the stores
Now that the stores have been created, accessing them isn’t quite as simple as it was when they were synchronous. With a completely synchronous store, svelte allowed access to the data via the $ operator. The stores from localStorage could be accessed or bound simply by dropping $storeName wherever that data was needed. With the new asynchronous stores, calling the custom init()method is mandatory before accessing the data; otherwise, the store won’t have any data! Here’s a simple Svelte component showing how to access the settings store data in the <script> tag and binding to the today store in the markup.
<script>
import { onMount, afterUpdate } from ‘svelte’;
import { today, settings } from ‘$stores/stores’;
import Spinner from ‘$components/Spinner.svelte’;

$: reactiveString = ‘loading…’;

onMount(() => {
settings.init()
.then(() => {
if(‘water’ in $settings) {
reactiveString = `water set to ${settings.water.value}`;
}
});
</script>

{#await today.init()}
<Spinner />
{:then}
<input type=”number” bind:value={$today.water} />
{:catch error}
<p>error</p>
{/await}
<p>{reactiveString}</p>

<Spinner /> source can be found here.
This instance of a reactive variable doesn’t make much sense unless it were tied to another value but the logic remains the same.
Accessing the today store value in the markup is made possible by use of Svelte’s {#await}.

el fin
Is this the best way connect Svelte stores to IndexedDB?
I have no idea. Probably not.
But it does seem to work for me. If you’ve got ideas on how it could be improved, leave a comment. I’m always open to constructive criticism. If you’re curious about the app this is taken from, I’ve previously written about it here. The source code for it can be found on GitHub.
And lastly, if you’ve enjoyed this post or found value in it, consider sponsoring me on GitHub.