| Mobile Light | Mobile Dark |
![]() |
![]() |
| Desktop Light | Desktop Dark |
![]() |
![]() |
| Active States Light | Active States Dark |
![]() |
![]() |
pnpm install
pnpm devBuild and preview the production version:
pnpm build
pnpm previewThis is a solution for the Frontend Mentor Todo App challenge. The goal is to build a responsive todo application with task management, filtering, theme switching, local persistence, and PWA support.
The app includes:
- Create new todos
- Delete individual todos
- Mark todos as completed or active
- Filter todos by
All,Active, andCompleted - Clear all completed todos
- Active todo counter
- Light and dark themes
- Theme persistence with
localStorage - Todo persistence with
localStorage - PWA manifest and service worker configuration through Vite
- Responsive layout for mobile and desktop
- Modern CSS with custom properties, logical properties,
clamp(), and native CSS nesting
src/
App.vue
main.ts
components/
Header/
TodoInput/
TodoList/
Footer/
composables/
useTheme.ts
useTodos.ts
types/
todo.ts
assets/
styles/
variables.css
global.css
main.cssThe project keeps UI and logic separated:
App.vuecoordinates the page and connects events to composables.useTodos.tsowns todo state, filtering, CRUD actions, and todo persistence.useTheme.tsowns theme state, theme persistence, anddata-themeupdates.- Components receive props and emit events instead of mutating global state directly.
The main flow is:
TodoInput emits create
App.vue calls createTodo from useTodos
useTodos updates todos and localStorage
TodoList emits toggle/delete/filter/clearCompleted
App.vue calls the matching useTodos function
computed values update the rendered list
Header emits toggleTheme
App.vue calls toggleTheme from useTheme
useTheme updates data-theme and localStorageThe UI is structured around meaningful HTML:
main.appwraps the application.header.headercontains the title and theme toggle.section.app__contentgroups the todo experience.form.todo-inputhandles task creation.section.todo-listidentifies the todo list region.ulandlirepresent the list of tasks.footer.todo-list__actionsgroups counter, filters, and clear action.- Buttons include accessible labels for icon-only actions.
More notes are available in What We Learned.
The project uses vite-plugin-pwa to generate the app manifest and service worker.
PWA assets live in public/:
public/
favicon-32x32.png
icon-192x192.png
icon-512x512.png
robots.txtTo inspect the PWA behavior, run a production preview:
pnpm build
pnpm previewThen open Chrome DevTools and check:
- Application > Manifest
- Application > Service Workers
- Lighthouse > PWA
Lipeh Fama





