← Back to course

Local Storage

Local Storage

Welcome back.

In the previous lesson, you learned forms and validation.

Forms collect user data.

Validation checks if that data makes sense.

Very useful.

Very responsible.

Very “please do not type banana as your email.”

Today we teach JavaScript something very interesting.

Memory.

Not real human memory.

JavaScript will not remember your birthday and bring cake.

But it can remember small pieces of data in the browser.

This is called local storage.

Local storage lets JavaScript save data even after the page is refreshed.

That means your page can remember things like:

Before local storage, JavaScript forgets everything when the page reloads.

After local storage, JavaScript becomes slightly less forgetful.

Still chaotic.

But improving.

What You Will Learn

In this lesson, you will learn:

By the end of this lesson, your JavaScript page will remember simple data.

Not everything.

Not secrets.

Not passwords.

But enough to feel useful.

Like a tiny notebook inside the browser.

What Is Local Storage?

Local storage is a browser feature that lets websites store small amounts of data.

The data stays in the browser even after:

Example:

localStorage.setItem("name", "Viktor");

This saves the value "Viktor" with the key "name".

Then we can read it later:

const name = localStorage.getItem("name");

console.log(name);

Output:

Viktor

The browser remembered the value.

Very nice.

Very convenient.

Slightly magical.

But still just JavaScript.

Important Warning

Do not store sensitive data in local storage.

Do not store:

Local storage is not secure storage.

It is useful for simple data.

A theme preference?

Good.

A task list?

Fine.

A password?

No.

Absolutely no.

Security is not a decorative plant.

It matters.

Create the Project

Create a folder for this lesson:

mkdir javascript-lesson10
cd javascript-lesson10
touch index.html
touch script.js

Your project should look like this:

javascript-lesson10/
  index.html
  script.js

Open the folder in your editor.

Today we will save data in the browser.

The browser is about to become a tiny notebook.

Hopefully not a messy one.

Write the HTML

Open index.html and add this:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Local Storage</title>
</head>
<body>
  <h1>Local Storage</h1>

  <button id="saveButton">Save Name</button>
  <button id="loadButton">Load Name</button>

  <p id="message">Nothing loaded yet.</p>

  <script src="script.js"></script>
</body>
</html>

This gives us:

Simple.

Small.

Ready to remember something.

Which is more than I can say about some browsers after 38 open tabs.

Saving Data with setItem

Open script.js and add:

const saveButton = document.getElementById("saveButton");
const loadButton = document.getElementById("loadButton");
const messageElement = document.getElementById("message");

function saveName() {
  localStorage.setItem("name", "Viktor");
  messageElement.textContent = "Name saved.";
}

saveButton.addEventListener("click", saveName);

Refresh the browser.

Click Save Name.

The message should say:

Name saved.

This line is important:

localStorage.setItem("name", "Viktor");

It means:

Save the value "Viktor" using the key "name".

Local storage works with key-value pairs.

A key is like a label.

A value is the data.

Like a drawer label and the thing inside the drawer.

Very organized.

Suspiciously organized.

Reading Data with getItem

Now add this function:

function loadName() {
  const savedName = localStorage.getItem("name");
  messageElement.textContent = `Saved name: ${savedName}`;
}

loadButton.addEventListener("click", loadName);

Now your full script.js looks like this:

const saveButton = document.getElementById("saveButton");
const loadButton = document.getElementById("loadButton");
const messageElement = document.getElementById("message");

function saveName() {
  localStorage.setItem("name", "Viktor");
  messageElement.textContent = "Name saved.";
}

function loadName() {
  const savedName = localStorage.getItem("name");
  messageElement.textContent = `Saved name: ${savedName}`;
}

saveButton.addEventListener("click", saveName);
loadButton.addEventListener("click", loadName);

Click Save Name.

Refresh the page.

Click Load Name.

The name is still there.

JavaScript remembered it.

The page refreshed.

The data survived.

Small miracle.

No backend.

No database.

Just the browser doing browser things.

What If the Data Does Not Exist?

If you try to read a key that does not exist, you get null.

Example:

const savedAge = localStorage.getItem("age");

console.log(savedAge);

Output:

null

null means:

There is nothing here.

So it is good to check before showing data.

Example:

function loadName() {
  const savedName = localStorage.getItem("name");

  if (savedName === null) {
    messageElement.textContent = "No name saved yet.";
    return;
  }

  messageElement.textContent = `Saved name: ${savedName}`;
}

Now the page behaves better.

If there is no saved name, it says so.

Very polite.

Very civilized.

Unlike random JavaScript errors at midnight.

Saving User Input

Hardcoding "Viktor" is fine for learning.

But usually we want to save what the user types.

Update index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Local Storage</title>
</head>
<body>
  <h1>Local Storage</h1>

  <label for="nameInput">Your name:</label>
  <input id="nameInput" type="text" placeholder="Type your name">

  <button id="saveButton">Save Name</button>
  <button id="loadButton">Load Name</button>
  <button id="removeButton">Remove Name</button>

  <p id="message">Nothing loaded yet.</p>

  <script src="script.js"></script>
</body>
</html>

Now update script.js:

const nameInput = document.getElementById("nameInput");
const saveButton = document.getElementById("saveButton");
const loadButton = document.getElementById("loadButton");
const removeButton = document.getElementById("removeButton");
const messageElement = document.getElementById("message");

function saveName() {
  const name = nameInput.value.trim();

  if (name === "") {
    messageElement.textContent = "Please type a name first.";
    return;
  }

  localStorage.setItem("name", name);
  messageElement.textContent = "Name saved.";
  nameInput.value = "";
}

function loadName() {
  const savedName = localStorage.getItem("name");

  if (savedName === null) {
    messageElement.textContent = "No name saved yet.";
    return;
  }

  messageElement.textContent = `Saved name: ${savedName}`;
}

function removeName() {
  localStorage.removeItem("name");
  messageElement.textContent = "Name removed.";
}

saveButton.addEventListener("click", saveName);
loadButton.addEventListener("click", loadName);
removeButton.addEventListener("click", removeName);

Now the user can type a name.

Save it.

Refresh.

Load it again.

Remove it.

This is real local storage usage.

Small.

Practical.

Useful.

Like a pocket notebook, but with more curly braces.

Removing Data with removeItem

This line removes one saved item:

localStorage.removeItem("name");

It removes the value stored under the key "name".

Only that item.

Not everything.

This is useful when the user wants to reset one setting.

Example:

localStorage.removeItem("theme");
localStorage.removeItem("username");
localStorage.removeItem("draft");

Specific.

Controlled.

No unnecessary destruction.

Very mature.

For JavaScript.

Clearing All Local Storage

There is also:

localStorage.clear();

This removes everything stored in local storage for that website.

Everything.

All keys.

All values.

Gone.

Use carefully.

Example:

function clearStorage() {
  localStorage.clear();
}

This is useful for reset buttons.

But do not use it randomly.

It is the digital equivalent of cleaning your desk with a flamethrower.

Effective.

But aggressive.

Local Storage Stores Strings

Important detail.

Local storage stores values as strings.

Example:

localStorage.setItem("age", 33);

const age = localStorage.getItem("age");

console.log(age);
console.log(typeof age);

Output:

33
string

Even though we saved a number, local storage gives us a string.

This matters.

If you need a number, convert it:

const age = Number(localStorage.getItem("age"));

JavaScript loves type surprises.

Keep your eyes open.

And maybe one eyebrow raised.

Saving Objects

Local storage cannot directly save objects.

This does not work the way you want:

const user = {
  name: "Viktor",
  role: "Student"
};

localStorage.setItem("user", user);

The result becomes something like:

[object Object]

Very unhelpful.

Very JavaScript.

To save an object, convert it to a string using JSON.stringify.

Example:

const user = {
  name: "Viktor",
  role: "Student"
};

localStorage.setItem("user", JSON.stringify(user));

Now the object is saved as a JSON string.

JSON is a text format for data.

It looks like JavaScript objects.

But it is text.

Tiny difference.

Big importance.

Reading Objects

To read the object back, use JSON.parse.

Example:

const savedUser = localStorage.getItem("user");
const user = JSON.parse(savedUser);

console.log(user.name);
console.log(user.role);

Output:

Viktor
Student

Full example:

const user = {
  name: "Viktor",
  role: "Student"
};

localStorage.setItem("user", JSON.stringify(user));

const savedUser = localStorage.getItem("user");
const parsedUser = JSON.parse(savedUser);

console.log(parsedUser);

The pattern is:

JSON.stringify(data)

when saving.

JSON.parse(data)

when reading.

Stringify to store.

Parse to use.

Simple.

Powerful.

Slightly ceremonial.

Saving Arrays

Arrays also need JSON.stringify.

Example:

const tasks = ["Learn JavaScript", "Practice DOM", "Drink coffee"];

localStorage.setItem("tasks", JSON.stringify(tasks));

To read them:

const savedTasks = localStorage.getItem("tasks");
const tasks = JSON.parse(savedTasks);

console.log(tasks);

Output:

["Learn JavaScript", "Practice DOM", "Drink coffee"]

This is very useful.

Because many apps store lists.

Tasks.

Products.

Favorites.

Settings.

Small lists of things that users care about.

And sometimes lists of things users will forget anyway.

But the browser remembers.

Build a Persistent Task List

Now let us build a small task list that survives refresh.

Update index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Local Storage</title>

  <style>
    body {
      font-family: Arial, sans-serif;
      max-width: 700px;
      margin: 60px auto;
      padding: 0 24px;
      background-color: #f3f4f6;
      color: #111827;
    }

    .card {
      background-color: white;
      padding: 24px;
      border: 2px solid #e5e7eb;
      border-radius: 18px;
    }

    h1 {
      font-size: 42px;
    }

    input {
      width: 100%;
      margin-top: 8px;
      padding: 12px;
      border: 2px solid #d1d5db;
      border-radius: 12px;
      font-size: 18px;
      box-sizing: border-box;
    }

    button {
      margin-top: 14px;
      background-color: #2563eb;
      color: white;
      border: none;
      padding: 12px 18px;
      border-radius: 999px;
      font-weight: 700;
      cursor: pointer;
    }

    button:hover {
      background-color: #1d4ed8;
    }

    ul {
      padding-left: 24px;
      margin-top: 20px;
    }

    li {
      font-size: 20px;
      margin-bottom: 10px;
    }

    .message {
      margin-top: 16px;
      font-size: 18px;
      font-weight: 700;
    }
  </style>
</head>
<body>
  <h1>Local Storage</h1>

  <div class="card">
    <label for="taskInput">New task</label>
    <input id="taskInput" type="text" placeholder="Write a task">

    <button id="addTaskButton">Add Task</button>
    <button id="clearTasksButton">Clear Tasks</button>

    <p id="message" class="message">Tasks will appear below.</p>

    <ul id="taskList"></ul>
  </div>

  <script src="script.js"></script>
</body>
</html>

Now update script.js:

const taskInput = document.getElementById("taskInput");
const addTaskButton = document.getElementById("addTaskButton");
const clearTasksButton = document.getElementById("clearTasksButton");
const taskListElement = document.getElementById("taskList");
const messageElement = document.getElementById("message");

let tasks = [];

function saveTasks() {
  localStorage.setItem("tasks", JSON.stringify(tasks));
}

function loadTasks() {
  const savedTasks = localStorage.getItem("tasks");

  if (savedTasks !== null) {
    tasks = JSON.parse(savedTasks);
  }
}

function showTasks() {
  taskListElement.innerHTML = "";

  for (const task of tasks) {
    const listItem = document.createElement("li");
    listItem.textContent = task;
    taskListElement.appendChild(listItem);
  }

  if (tasks.length === 0) {
    messageElement.textContent = "No tasks yet.";
  } else {
    messageElement.textContent = `You have ${tasks.length} task(s).`;
  }
}

function addTask() {
  const task = taskInput.value.trim();

  if (task === "") {
    messageElement.textContent = "Please write a task first.";
    return;
  }

  tasks.push(task);
  saveTasks();
  showTasks();

  taskInput.value = "";
}

function clearTasks() {
  tasks = [];
  saveTasks();
  showTasks();
}

addTaskButton.addEventListener("click", addTask);
clearTasksButton.addEventListener("click", clearTasks);

loadTasks();
showTasks();

Now test it.

Add a task.

Refresh the page.

The task stays.

Add another task.

Refresh again.

Still there.

Congratulations.

You built a small persistent app.

No backend.

No database.

Just local storage.

Small frontend magic.

Very satisfying.

How This Code Works

This array stores tasks in JavaScript:

let tasks = [];

This saves tasks to local storage:

function saveTasks() {
  localStorage.setItem("tasks", JSON.stringify(tasks));
}

This loads tasks from local storage:

function loadTasks() {
  const savedTasks = localStorage.getItem("tasks");

  if (savedTasks !== null) {
    tasks = JSON.parse(savedTasks);
  }
}

This shows tasks on the page:

function showTasks() {
  taskListElement.innerHTML = "";

  for (const task of tasks) {
    const listItem = document.createElement("li");
    listItem.textContent = task;
    taskListElement.appendChild(listItem);
  }
}

This adds a task:

tasks.push(task);
saveTasks();
showTasks();

Important pattern:

Update data.

Save data.

Show data.

This pattern appears everywhere.

Even in bigger apps.

Only with more files.

More frameworks.

And more emotional damage.

Common Mistakes

Forgetting JSON.stringify

Wrong:

localStorage.setItem("tasks", tasks);

Correct:

localStorage.setItem("tasks", JSON.stringify(tasks));

Arrays and objects need to be converted to strings before saving.

Otherwise JavaScript becomes weird.

More weird than usual.

Forgetting JSON.parse

Wrong:

const tasks = localStorage.getItem("tasks");

Correct:

const tasks = JSON.parse(localStorage.getItem("tasks"));

If you saved JSON, parse it when reading.

Stringify when saving.

Parse when loading.

Like packing and unpacking a suitcase.

Trying to Store Sensitive Data

Wrong idea:

localStorage.setItem("password", password);

Do not do this.

Passwords do not belong in local storage.

Local storage is not a safe.

It is more like a drawer in your room.

Useful.

But not where you keep gold bars.

Forgetting to Update the Page After Saving

If you only save the task:

tasks.push(task);
saveTasks();

but do not call:

showTasks();

the data is saved, but the page does not update.

The browser is not a mind reader.

Tell it what to show.

Practice

Create a small page that saves a favorite color.

The page should have:

When the user saves a color, store it in local storage.

When the user loads it, show:

Your favorite color is blue.

Bonus:

Change the page background to that color.

Careful with colors.

If the user types “pizza,” the browser may not understand.

Although spiritually, pizza is always a valid choice.

Mini Challenge

Create a notes app.

The page should have:

Rules:

This is a very practical challenge.

Many real apps start with this idea:

User writes something.

App saves it.

User returns later.

Data is still there.

Simple.

Useful.

Powerful.

Summary

Today you learned:

This is a huge step.

Your pages can now remember things.

Small things.

Useful things.

Browser things.

JavaScript has gained a tiny memory.

Very useful.

Very dangerous if misused.

Like giving a notebook to a raccoon.

Next Lesson

In the next lesson, we will learn the Fetch API.

Fetch lets JavaScript get data from other places.

APIs.

Servers.

JSON files.

Real data from the outside world.

Until now, most data lived inside our code.

Soon JavaScript will start talking to the internet.

Carefully.

Hopefully.