A modern Trello-style Kanban UI built with Vue 3, TypeScript, Pinia, Vue Router, and Tailwind CSS v4. It talks to the companion trello-back Express + TypeORM + MySQL API over HTTP.
- Authentication (register / login / logout) with JWT
- Multiple projects per user (personal or owned by an organization)
- Organizations (list, create, delete)
- Dynamic task statuses (columns) per project — add, rename, reorder, delete
- Task CRUD with title, description, due date, importance (
URGENT / HIGH / MEDIUM / LOW) - Drag & drop for tasks (between/within columns) and columns themselves, with server-side persistence
- Typed HTTP client (axios) with auth token interceptor + auto-logout on 401
| Layer | Choice |
|---|---|
| Framework | Vue 3.5 (<script setup> + Composition) |
| Bundler | Vite 6 |
| Language | TypeScript 5 (strict) |
| State | Pinia 2 |
| Routing | Vue Router 4 (with auth guard) |
| Styling | Tailwind CSS 4 (CSS-first @theme) |
| HTTP | axios |
| Drag & drop | vue-draggable-plus |
| Icons | FontAwesome |
Make sure the backend is running first (default: http://localhost:4000/api).
cp .env.example .env
npm install
npm run devOpen http://localhost:5173. Register a new account, create an organization (optional), then create projects and tasks.
| Variable | Default |
|---|---|
VITE_API_URL |
http://localhost:4000/api |
npm run dev— start Vite dev servernpm run build— type-check + production buildnpm run preview— preview the production buildnpm run type-check— runvue-tsc
src/
├── components/ AppHeader, Modal, ConfirmDialog, BoardColumn, TaskCard, TaskModal
├── router/ Vue Router with auth guard
├── services/ api.ts (axios + token), auth, projects, organizations
├── stores/ auth, projects, organizations (Pinia)
├── types/ Shared TS types + enums (mirrors backend)
├── views/
│ ├── LoginView.vue
│ ├── RegisterView.vue
│ ├── ProjectsListView.vue
│ ├── ProjectView.vue
│ └── OrganizationsView.vue
├── App.vue Shell with AppHeader + `<router-view>`
├── main.ts Pinia + Router + FontAwesome bootstrap
└── style.css Tailwind v4 entry + brand theme tokens
- Auth flow. On login/register, the JWT is stored in
localStorageand installed as the defaultAuthorizationheader on the axios instance. The router'sbeforeEachguard callsauth.restore()(idempotent) — which fetches/auth/meto verify the token and populateuser. Any 401 anywhere in the app triggers an auto-logout + redirect to/login. - Data model. Types mirror the backend one-to-one (
Project,TaskStatus,Task,Organization,User,Importanceenum). The "columns" shown in the UI areTaskStatusrecords on the server. - Optimistic mutations. Updates go through Pinia actions that call the service, then update local state with the server response. Drag reorders fire
/tasks/reorderand/statuses/reorderand reconcile from the response.
- Categories CRUD UI (per project)
- Project members UI (invite / role change)
- Organization members UI
- Task assignment (
assignedUserId) picker
The backend exposes all of these — they can be added without further API work.