Building an Offline-Enabled To-Do List Web App
After getting huge success on my previous article. Here is a use case of building an Offline-Enabled Website.
In today's world, where connectivity isn't always guaranteed, creating web applications that work offline can greatly enhance user experience. In this tutorial, we'll walk through the process of building a simple To-Do List web app that functions both online and offline. We'll be using basic HTML, CSS, and JavaScript, along with a service worker for caching resources.
[!TIP]
See Source Code and Live Preview
Prerequisites
- Basic knowledge of HTML, CSS, and JavaScript
- A text editor
- A browser that supports service workers (most modern browsers)
Setting Up the Project
Let's start by setting up the basic structure of our project. Create the following files in a new directory:
index.html
styles.css
app.js
service-worker.js
The HTML Structure (index.html
)
Our main HTML file will contain the structure of our To-Do List web app. Here's a basic layout:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Offline To-Do List</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Offline To-Do List</h1>
<div class="form">
<input type="text" id="taskInput" placeholder="Add new task...">
<button onclick="addTask()">Add Task</button>
</div>
<ul id="taskList">
<!-- Tasks will be dynamically added here -->
</ul>
</div>
<script src="app.js"></script>
</body>
</html>
Styling (styles.css
)
Let's add some basic styles to make our app look presentable:
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.container {
max-width: 600px;
margin: 0 auto;
}
h1 {
text-align: center;
}
.form {
display: flex;
margin-bottom: 20px;
}
input[type="text"] {
flex: 1;
padding: 10px;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 10px;
}
.completed {
text-decoration: line-through;
color: #888;
}
Adding Functionality (app.js
)
Our JavaScript file will handle the logic for adding tasks, toggling completion, deleting tasks, rendering tasks, and saving tasks to localStorage
. It will also register the service worker.
let tasks = [];
// Check if there are tasks in localStorage
const storedTasks = localStorage.getItem('tasks');
if (storedTasks) {
tasks = JSON.parse(storedTasks);
renderTasks();
}
function addTask() {
const taskInput = document.getElementById('taskInput');
const taskText = taskInput.value.trim();
if (taskText !== '') {
tasks.push({ text: taskText, completed: false });
taskInput.value = '';
renderTasks();
saveTasks();
}
}
function toggleTask(index) {
tasks[index].completed = !tasks[index].completed;
renderTasks();
saveTasks();
}
function deleteTask(index) {
tasks.splice(index, 1);
renderTasks();
saveTasks();
}
function renderTasks() {
const taskList = document.getElementById('taskList');
taskList.innerHTML = '';
tasks.forEach((task, index) => {
const li = document.createElement('li');
li.innerHTML =
<span class="</span><span class="p">${</span><span class="nx">task</span><span class="p">.</span><span class="nx">completed</span> <span class="p">?</span> <span class="dl">'</span><span class="s1">completed</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">''</span><span class="p">}</span><span class="s2">" onclick="toggleTask(</span><span class="p">${</span><span class="nx">index</span><span class="p">}</span><span class="s2">)"></span><span class="p">${</span><span class="nx">task</span><span class="p">.</span><span class="nx">text</span><span class="p">}</span><span class="s2"></span>
<button onclick="deleteTask(</span><span class="p">${</span><span class="nx">index</span><span class="p">}</span><span class="s2">)">Delete</button>
;
taskList.appendChild(li);
});
}
function saveTasks() {
localStorage.setItem('tasks', JSON.stringify(tasks));
}
// Service Worker Registration
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(reg => {
console.log('Service Worker registered');
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
Service Worker (service-worker.js
)
The service worker file is responsible for caching the necessary files and handling requests when the app is offline:
const cacheName = 'offline-v1';
const cacheFiles = [
'/',
'/index.html',
'/styles.css',
'/app.js'
];
self.addEventListener('install', e => {
console.log('Service Worker: Installed');
e.waitUntil(
caches.open(cacheName)
.then(cache => {
console.log('Service Worker: Caching Files');
cache.addAll(cacheFiles);
})
.then(() => self.skipWaiting())
);
});
self.addEventListener('activate', e => {
console.log('Service Worker: Activated');
e.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cache => {
if (cache !== cacheName) {
console.log('Service Worker: Clearing Old Cache');
return caches.delete(cache);
}
})
);
})
);
});
self.addEventListener('fetch', e => {
console.log('Service Worker: Fetching');
e.respondWith(
fetch(e.request)
.then(response => {
const clone = response.clone();
caches.open(cacheName)
.then(cache => {
cache.put(e.request, clone);
});
return response;
})
.catch(() => caches.match(e.request).then(response => response))
);
});
Conclusion
By following this tutorial, you've learned how to create an offline-enabled To-Do List web app using basic web technologies. Users can add tasks, mark them as completed, and delete them - all while offline. The service worker ensures that the app functions seamlessly even without an internet connection by caching the necessary files.
Feel free to expand upon this project by adding more features like editing tasks, due dates, or even syncing with a backend server when connectivity is restored. This is just the beginning of what you can achieve with offline web applications!
Download This Article :- https://gist.github.com/SH20RAJ/574a952fe360ca170e81f7447626cc2a
Happy coding! 🚀
Top comments (9)
By the way, your example todo app is vulnerable via xss.
Still nice information
No way, while it’s offline… 🥂😂
😝
No means of vulnerability it's just a simple to-do app for demonstration purpose and it doesn't use any db or things thats requires security....
It's not a problem....
Still Thanks
nice app, take a look at mine 😃
hitesh-todolist.netlify.app/
Nice UI bro 🚀
But offline functionality isn't added, you should add it....
I like to use workbox
This is my app 😃
Some comments may only be visible to logged-in visitors. Sign in to view all comments.