Site index
Arrow keys to navigateEnter to open / Esc to close
Writing index
Field note / Frontend engineering

Building a modern todo app with Zustand, Firebase, and Next.js

A real-time todo app with authentication, CRUD operations, and predictable global state, built with Next.js, Firebase, and Zustand.

1 min readnext.jsfirebasezustandfullstack
On this page
Building a modern todo app with Zustand, Firebase, and Next.js

A todo app is the smallest app that still needs auth, persistence, real-time updates, and optimistic UI. That makes it a good place to get the architecture right.

Separate server state from UI state

This is the rule that keeps the codebase clean.

  • Firebase holds the todos. That is server state.
  • Zustand holds the filter, the draft text, and the selection. That is UI state.

Mixing them creates synchronisation bugs.

type UiState = {
  filter: "all" | "active" | "done";
  draft: string;
  setFilter: (filter: UiState["filter"]) => void;
  setDraft: (draft: string) => void;
};

export const useUiStore = create<UiState>((set) => ({
  filter: "all",
  draft: "",
  setFilter: (filter) => set({ filter }),
  setDraft: (draft) => set({ draft }),
}));

Subscribe to real-time updates

useEffect(() => {
  const unsubscribe = onSnapshot(
    query(collection(db, "todos"), orderBy("createdAt", "desc")),
    (snapshot) => {
      setTodos(snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() })));
    },
  );
  return unsubscribe;
}, []);

Always return the unsubscribe function. This is the most common Firebase leak.

Optimistic updates that roll back

The UI should update before the network confirms, then correct itself on failure.

const previous = todos;
setTodos([optimistic, ...todos]);
try {
  await addDoc(collection(db, "todos"), optimistic);
} catch {
  setTodos(previous);
}

Accessible interactions

  • Toggle with a real checkbox, not a styled div
  • Announce changes with an aria-live region
  • Keep delete behind an undo window

Optimistic UI is a promise. Make sure you can keep it.

Model server state and UI state separately, subscribe carefully, and the rest follows.

Continue reading

Related articles

Modal interface

Accent system

Choose a palette. The selection is saved on this device.

Accent color themes

28 palettes available

Modal interface

A note worth keeping

A randomly selected thought from the inspiration archive.