Skip to main content

Featured

🏁 Day 30 — Final Project: JavaScript Portfolio App

🏁 Day 30 — Final Project: JavaScript Portfolio App Hey Guys Congratulations! You’ve reached Day 30 — the final step of the JavaScript Advanced Course. Keep Learning Today, you will build a complete, interactive Portfolio Web Application using pure JavaScript, DOM manipulation, LocalStorage, and responsive UI techniques. This project showcases all your skills and is perfect for your resume, GitHub, and job applications. 🎯 1. What We Are Building This final project is a fully interactive portfolio website built using HTML, CSS, and JavaScript only — no frameworks. Your portfolio will include: Navbar with smooth scrolling Animated hero section Projects section with filters Skills section with dynamic bars Contact form (with LocalStorage backup) Dark/Light theme switcher Scroll reveal animations Responsive layout for mobile & desktop This project demonstrates mastery of front-end fundamentals and modern JavaScript practices. 📁 2. Fold...

🧭 Day 21 — Mini Project: Notes App with LocalStorage

🧭 Day 21 — Mini Project: Notes App with LocalStorage

Build a small but practical Notes app that stores user notes locally. This project covers UI, event handling, storage, editing, deleting, and persistence.


📋 Project overview

Requirements:

  • Create, read, update, delete notes (CRUD).
  • Persist notes in localStorage so they survive refresh.
  • Support edit and delete actions, and simple search.
  • Minimal, responsive UI using vanilla JS and CSS.

🧱 HTML structure (starter)

<div class="notes-app">
  <input id="noteTitle" placeholder="Title">
  <textarea id="noteBody" placeholder="Write your note..."></textarea>
  <button id="saveBtn">Save</button>

  <input id="search" placeholder="Search notes...">

  <div id="notesList"></div>
</div>
  

⚙️ Core JavaScript (save, render, edit, delete)

const KEY = 'notes:v1';

function loadNotes() {
  return JSON.parse(localStorage.getItem(KEY) || '[]');
}

function saveNotes(notes) {
  localStorage.setItem(KEY, JSON.stringify(notes));
}

function renderNotes(filter = '') {
  const list = document.getElementById('notesList');
  list.innerHTML = '';
  const notes = loadNotes().filter(n => n.title.includes(filter) || n.body.includes(filter));
  notes.forEach(note => {
    const el = document.createElement('div');
    el.className = 'note';
    el.innerHTML = `
      <h3>${note.title}</h3>
      <p>${note.body}</p>
      <button data-id="${note.id}" class="edit">Edit</button>
      <button data-id="${note.id}" class="delete">Delete</button>
    `;
    list.appendChild(el);
  });
}

document.getElementById('saveBtn').addEventListener('click', () => {
  const title = document.getElementById('noteTitle').value.trim();
  const body = document.getElementById('noteBody').value.trim();
  if (!title && !body) return;
  const notes = loadNotes();
  const id = Date.now();
  notes.unshift({ id, title, body, updated: id });
  saveNotes(notes);
  renderNotes();
  document.getElementById('noteTitle').value = '';
  document.getElementById('noteBody').value = '';
});

// delegate edit/delete
document.getElementById('notesList').addEventListener('click', (e) => {
  const id = Number(e.target.dataset.id);
  if (e.target.classList.contains('delete')) {
    let notes = loadNotes().filter(n => n.id !== id);
    saveNotes(notes);
    renderNotes();
  } else if (e.target.classList.contains('edit')) {
    const notes = loadNotes();
    const note = notes.find(n => n.id === id);
    document.getElementById('noteTitle').value = note.title;
    document.getElementById('noteBody').value = note.body;
    // remove old one; save will add new version
    saveNotes(notes.filter(n => n.id !== id));
    renderNotes();
  }
});

document.getElementById('search').addEventListener('input', (e) => {
  renderNotes(e.target.value.trim());
});

renderNotes();
  

📐 UI & UX Tips

  • Show updated timestamp on each note for clarity.
  • Confirm delete with a toast or confirm dialog.
  • Keep the editable state minimal: edit in-place or open a modal for rich editing.
  • Debounce the search input for larger note sets.

🛡 Edge cases & robustness

  • Handle storage full errors—catch QuotaExceededError.
  • Sanitize UI output to avoid accidental HTML injection (use textContent when inserting user text into the DOM).
  • Provide export/import: allow user to download notes JSON and re-upload later.

✨ Enhancements & upgrades

  1. Offline sync: Keep local notes and sync with server when online.
  2. Attachments: Use IndexedDB for storing images or larger blobs.
  3. Tagging & filtering: Add tags and filter by tag or date.
  4. Encryption: Optionally encrypt notes before saving to localStorage when storing sensitive info (be aware of key storage problem).

📝 Practice tasks

  1. Add a "favorite" flag and sort favorites up top.
  2. Implement autosave: every few seconds, save the current draft to localStorage.
  3. Create import/export JSON UI so users can backup notes.

This Notes app is a great portfolio mini-project: it demonstrates DOM manipulation, state management, and persistence without any backend.

Comments