Project: Todo With Pinia

Introduction

This project builds a Todo app with Pinia, filtered views (all / active / completed), and optional localStorage persistence. No backend—focus on reactive UI, store design, and component structure before connecting APIs in later projects.

Prerequisites

Goals

FeatureSkill
Add / toggle / remove todosActions + immutable updates
Filters all / active / doneGetters or computed in store
Persist todoswatch + localStorage
Component splitList, item, filter bar

Store Design

src/stores/todos.ts:

Components

TodoInput.vue — emit or call store directly:

TodoItem.vue — props + events or store:

TodoFilter.vue:

TodoApp.vue:

Optional: Vitest Tests

Test store actions with createPinia()Testing Vue Components.

Test addTodo ignores empty strings and filteredItems respects filter.

Deliverables

  • Add, toggle, delete todos
  • Three filters work correctly
  • activeCount updates
  • Todos survive page refresh (localStorage)
  • Empty state message when no todos
  • Optional: transition on add/remove

Extensions

  • Edit todo inline (double-click → input)
  • Route query ?filter=active synced with store
  • Replace localStorage with FastAPI CRUD in a follow-up branch

FAQ

Store vs composable for todos?

Single feature can use composable; Pinia practice prepares multi-view apps.

crypto.randomUUID?

Modern browsers; fallback Date.now() + random for older targets.

Pinia persistence plugin?

pinia-plugin-persistedstate replaces manual save()—optional upgrade.

Why emit from TodoItem?

Keeps item presentational—parent or store handles logic; both patterns valid.

Next project?

Blog Reader with API.