Building an Offline-First Application With Node.js and SQLite | by Arctype | Apr, 2022

Building an offline-first application with Node.js and SQLite

“Offline first” is an application development paradigm in which developers ensure that an app’s functionality is unaffected by a temporary loss of network connectivity. Progressive web applications, which feel like native applications but run like web applications, are often built on this paradigm.

This tutorial will teach you how to build an offline-first application with Node.js and an SQLite database. Let’s start with an introduction to progressive web apps.

Progressive web apps (PWAs) are web apps that use service workers, manifests, and other web-platform features and progressive enhancement to provide users with an experience comparable to native apps.

PWAs can sometimes outperform native apps in terms of efficiency. They operate on demand and are always available without consuming valuable smartphone memory or data. Users consume less data when choosing a PWA over a native version of the same application. They can still save the PWA to their home screen; it’s installable without the need for a full download.

To demonstrate the power of progressive web applications, we’ll be building a simple blog application.

Building an offline-first application with Node.js and SQLite

The user will be able to interact with it like other PWAs, such as the Twitter PWA. Let’s get right to it.

Let’s get our hands dirty. To get started, we’ll create our project folder with the command below:

mkdir PWA && cd PWA

Then, we’ll initialize a Node.js application with the commands below:

npm init -y

The above command creates a package.json file for the application.

Next, create the following folder structure in our project folder:

┣ 📂public
┃ ┣ 📂 css
┃ ┣ 📂icons
┃ ┣ 📂images
┃ ┣ 📂js
┃ ┗ 📜index.html
┗ 📜package.json

With our application setup, let’s install Express to create our Node.js server with the command below:

npm install express

Then, we’ll create a couple of folders and files in the public folder:

  • css/style.css file
  • js/app.js file

Next, create an index.js file in the project root directory with the following code snippets below:

In the code snippet, we import express to create our server and the path module. We configured our app to render our static files using the express.static method, which takes the path to the static folder (public), and then we created the root route of our application and rendered the index.html file. Then we configured the app to listen to port 8000.

With the server set up for our application, let’s create and connect our application to save our blog details. To get started, run the command below to install the sqlite3 dependency:

npm install sqlite3

Then, at the entry point of the index.js file, add the code snippet below to create and connect the application to an SQLite Database.

Next, we’ll create a list of blogs that we’ll store in our database and render later to the client-side with the code snippet below:

Each block post in our application will have an id, title, avatarand intro field.

Now, create a database table named blogs and save the blog details we just created above with the code snippet below:

In the code snippet, we created a table blogs using The method takes an SQL query as a parameter, then we loop through our array of blogs and insert them into the blogs table we just created using the js map function.

Now, let’s view the records we just created using Arctype. To view the records in your SQLite database using Arctype, follow the steps below:

  • Install Arctype
  • Run the application with node index.js to create a database
  • Launch Arctype, and click on the SQLite tab
Building an offline-first application with Node.js and SQLite
  • Click on the Select SQLite file button, and locate the db.sqlite file generated when you ran the server.
  • You should see the blogs table and the records we create as shown in the screenshot below:
Building an offline-first application with Node.js and SQLite

At this point, we have connected the application to an SQLite database and also inserted some records in the database. Now, open the index.html file and add the following code snippets below:

We created a simple markup with links to our manifest in the above file, which we’ll be creating in the next section, stylesand app.js files.

Then, we’ll create a blogs route in our index.js file to return the blogs to the client-side.

app.get("/blogs", (req, res) => {

In our public/js/app.js file, we’ll send a get request to the blog endpoint to get the blogs from our backend. Then we loop through the blogs, target the container class and display them with the following code:

We’ll also add some styling to our application in the public/css/style.css with the code snippet below:

Now open the package.json file and add the start script.

"start": "node index.js"

At this point, we’ve set up our application. But we cannot run our application when the server is not running or when there is no network connection for production. Let’s set that up in the next section.

We need to make our application compatible with all screen sizes. We’ll also add a theme color by adding the markup below in the head section of our index.html file.

<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#16a0d6e7"/>

We need to describe our app and how it should behave when installed on the user’s device. We can do this by creating a manifest.

Create a manifest file in the project root directory and add the following configurations:

"name": "Blogger"
"short_name": "Blogger"
"start_url": "/",
"display": "standalone",
"background_color": "#0e9c95",
"theme_color": "#16a0d6e7",
"orientation": "portrait",
"icons": []

In our manifest, we defined the following configurations:

  • name: This defines the app’s display name.
  • short_name: This defines the name that will be displayed under the app icon when installed.
  • start_url: This tells the browser the root URL of the application.
  • display: This tells the browser how to display the app.
  • background_color: This defines the background color of the application when installed.
  • theme_color: This defines the color of the status bar.
  • orientation: This defines the orientation to use during the app display.
  • icons: This defines the icons or images of different sizes to be used as our app home icons.

Creating our home screen icons manually can be a very complicated task, but not to worry. We’ll take advantage of a third-party module known as pwa-asset-generator to generate icons of different sizes from our main app icon inside the public directory with the command below:

#change directory to the public folder
cd public
#generate icons
npx pwa-asset-generator logo.png icons

The above command will create an icons folder inside the public folder with many icons for our application, along with some JSON on the terminal that we will paste into our icons array in the manifest.

Building an offline-first application with Node.js and SQLite

The icons array in our manifest should look like this:

Also, the command generated the markup links to the icons generated.

Building an offline-first application with Node.js and SQLite

Copy and paste the markup to the head section of the markup in the public/index.html file.

With our manifest created, let’s set up the service workers. A service worker is a piece of JavaScript code that your browser runs in the background in a separate thread to handle the cache for assets and data that you save for future requests to enable offline support for your application.

So, create a blogger.serviceWorker.js file in the public folder. For the service worker, there are many events (push, activate, install, fetch, message, sync), but for the demonstration in this tutorial, we’ll cover the install, activateand fetch events. Before that, we need to create an array to store all the assets we used in our application.

const assets = [

Then, we’ll listen to the install event to register and save our static files to the browser’s cache. This process takes some time to complete. To skip the wait, we’ll use skipWaiting().

Then, we need to clear the cache to remove the old assets whenever the service worker is updated. For that, we’ll listen to the activate code snippet below:

In the above code snippet, we use the waitUntil method on the service worker. This method waits for the action to finish, and then we check if the assets we are trying to clear are the assets of our current app before we delete them.

Next, we need the files stored in our cache to use them.

When a request is made on the page, PWA will check our cache and read from it if there is data in the cache rather than going to the network. Then, using the respondWith method, we override the browser’s default and make our event return a promise. When the cache is complete, we can return the cache corresponding to the evt.request. When the cache is ready, we can return the cache that matches the evt.request.

We have successfully set up our service worker. Now let’s make it available in our application.

Now, let’s register our service worker in our public/js/app.js file with the code snippet below:

Here, we check if our application’s browser supports service workers (of course, not all browsers support service workers), then register our service worker file.

Now, run the application with the command below:

npm start

Go to localhost:8000 in your browser to access the app.

Now, let’s check if we properly set up our PWA using a Google Lighthouse check. Right-click on your browser and select “inspect.” On the inspect tabs, select lighthouse and click on generate report. If everything went well with your application, you should see an output like the one in the screenshot below:

Building an offline-first application with Node.js and SQLite

We have successfully created our first application. You can also stop the server to test the application in offline mode.

Progressive web apps (PWA) use modern APIs to provide enhanced capabilities, dependability, and installability with a single codebase. They allow your end user to use your application regardless of whether or not they have an internet connection.

You should feel free to fork the repository and add additional features to the project.

Good luck!

Leave a Comment