diff --git a/README.md b/README.md
index d1c68b5..ea51cdd 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,56 @@
-# Todo
\ No newline at end of file
+# klar Todo App
+
+[https://talotodo.netlify.app/](https://talotodo.netlify.app/)
+
+
+**A Bauhaus-inspired Todo application built with React, Zustand, and Tailwind CSS.**
+
+
+## Key Features
+
+**Task Management**
+ Add, list, toggle (mark done/undo), and remove tasks with ease.
+
+**Global State**
+ Powered by Zustand for zero-prop-drilling and efficient updates.
+
+**Bulk Actions**
+ “Complete All” button to mark every task as completed instantly.
+
+**Empty-State UX**
+ Engaging empty-state screen to encourage task creation.
+
+**Responsive Design**
+ Mobile-first layout scaling gracefully from 320px to 1920px with Tailwind CSS.
+
+**Bauhaus! Zustand! Klar!**
+ Bauhaus-inspired styling, font and colors with custom CSS variables and utility classes for a minimalist aesthetic.
+
+**Dark/Light Theme**
+ Toggle between light and dark modes, with preferences persisted in local storage.
+
+**Persistence**
+ Todos and theme choice saved in local storage for continuity across sessions.
+
+**Timestamps**
+ Task creation dates formatted with Day.js.
+
+**Due-Date Support**
+ Optional due-date input with visual styling for overdue tasks.
+
+**Category Tags**
+ Add comma-separated tags to tasks, displayed as badges.
+
+**Advanced Filtering**
+ Filter tasks by status (All/Active/Completed), creation date, tags, and project.
+
+**Project Grouping**
+ Organize tasks under named projects.
+
+ **Drag-and-Drop**
+ Reorder tasks within each project group via drag-and-drop.
+
+**Accessibility**
+ Semantic HTML, ARIA roles, focus management, SEO friendly, and Lighthouse scores ≥95.
+
+WIP - WORK IN PROGRESS - it's called klar but it ain't klart yet! - WIP
diff --git a/index.html b/index.html
index f7ac4e4..44482d6 100644
--- a/index.html
+++ b/index.html
@@ -2,9 +2,14 @@
+
- Todo
+
+ klar
diff --git a/package.json b/package.json
index caf6289..da264e4 100644
--- a/package.json
+++ b/package.json
@@ -10,18 +10,25 @@
"preview": "vite preview"
},
"dependencies": {
+ "@hello-pangea/dnd": "^18.0.1",
+ "@tailwindcss/vite": "^4.1.7",
+ "dayjs": "^1.11.13",
"react": "^19.0.0",
- "react-dom": "^19.0.0"
+ "react-dom": "^19.0.0",
+ "zustand": "^5.0.5"
},
"devDependencies": {
"@eslint/js": "^9.21.0",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.3.4",
+ "autoprefixer": "^10.4.21",
"eslint": "^9.21.0",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.15.0",
+ "postcss": "^8.5.3",
+ "tailwindcss": "^4.1.7",
"vite": "^6.2.0"
}
}
diff --git a/public/moon.svg b/public/moon.svg
new file mode 100644
index 0000000..1609936
--- /dev/null
+++ b/public/moon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/sun.svg b/public/sun.svg
new file mode 100644
index 0000000..eb6fb59
--- /dev/null
+++ b/public/sun.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/App.jsx b/src/App.jsx
index 5427540..212db73 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,5 +1,91 @@
-export const App = () => {
+import React, { useEffect, useState } from 'react'
+import dayjs from 'dayjs'
+import { useTodos } from './store/useTodos'
+import { useTheme } from './store/useTheme'
+import Header from './components/Header'
+import TodoForm from './components/TodoForm'
+import FilterBar from './components/FilterBar'
+import TodoList from './components/TodoList'
+import EmptyState from './components/EmptyState'
+import Footer from './components/Footer'
+
+export default function App() {
+ const theme = useTheme((s) => s.theme)
+ const allTodos = useTodos((s) => s.todos)
+
+ // build the unique project list
+ const projects = Array.from(new Set(allTodos.map((t) => t.project)))
+
+ // full filter state
+ const [filters, setFilters] = useState({
+ status: 'all',
+ createdAfter: '',
+ tagFilter: '',
+ projectFilter:'all',
+ })
+
+ // apply dark/light theme
+ useEffect(() => {
+ document.documentElement.setAttribute('data-theme', theme)
+ }, [theme])
+
+ // helper to parse comma‐lists
+ const parseTags = (str) =>
+ str.split(',').map((t) => t.trim()).filter((t) => t !== '')
+
+ // derive the visible todos based on filters
+ const visibleTodos = allTodos
+ .filter((todo) => {
+ // project filter
+ if (
+ filters.projectFilter !== 'all' &&
+ todo.project !== filters.projectFilter
+ )
+ return false
+
+ // status filter
+ if (filters.status === 'active' && todo.done) return false
+ if (filters.status === 'completed' && !todo.done) return false
+
+ // created-after filter
+ if (filters.createdAfter) {
+ const created = dayjs(todo.createdAt)
+ const after = dayjs(filters.createdAfter)
+ if (created.isBefore(after, 'day')) return false
+ }
+
+ // tag filter
+ if (filters.tagFilter) {
+ const wantedTags = parseTags(filters.tagFilter)
+ const hasMatch = wantedTags.some((tag) =>
+ todo.tags.includes(tag)
+ )
+ if (!hasMatch) return false
+ }
+
+ return true
+ })
+
return (
-
+)
+}
\ No newline at end of file
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
new file mode 100644
index 0000000..591bb9d
--- /dev/null
+++ b/src/components/Footer.jsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import Stats from './Stats'
+
+export default function Footer() {
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
new file mode 100644
index 0000000..9a1ada7
--- /dev/null
+++ b/src/components/Header.jsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import ThemeToggle from './ThemeToggle'
+
+export default function Header() {
+ return (
+
+
klar
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/Stats.jsx b/src/components/Stats.jsx
new file mode 100644
index 0000000..35e1556
--- /dev/null
+++ b/src/components/Stats.jsx
@@ -0,0 +1,37 @@
+import React from 'react'
+import { useTodos } from '../store/useTodos'
+
+export default function Stats() { // Stats component
+ // Zustand store for todos
+ const todos = useTodos((s) => s.todos) // Get todos from Zustand store
+ const completeAll = useTodos((s) => s.completeAll) // Get completeAll function from Zustand store
+ const totalCount = todos.length // Total number of todos
+ const remainingCount = todos.filter((t) => !t.done).length // Number of remaining todos
+
+ // If no tasks, render nothing
+ if (totalCount === 0) return null
+
+ return (
+