Skip to content

jsrobson/Index-ToDo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Index To-Do Application

A full-stack To-Do application with a FastAPI back-end and a vanilla HTML/CSS/JS front-end. Features JWT authentication, per-user card ownership, paginated task lists, and a layered back-end architecture separating models, schemas, services, and routers.


Features

  • User registration and login with JWT-based authentication
  • Full CRUD operations on To-Do cards, scoped to the authenticated user
  • Ownership enforcement — users can only access and modify their own cards
  • Paginated card listing with skip / limit query parameters
  • Input validation via Pydantic v2
  • SQLite database with SQLAlchemy/SQLModel ORM
  • Plain HTML/CSS/JS front-end — no framework, no build step
  • Comprehensive test suite — unit, service, and integration tests

Tech Stack

Layer Technology
Back-end framework FastAPI
ORM SQLModel + SQLAlchemy
Validation Pydantic v2
Authentication JWT via python-jose + passlib/bcrypt
Database SQLite (swappable via DATABASE_URL)
Front-end HTML, CSS, Vanilla JS
Testing pytest + httpx

Project Structure

app/
├── core/
│   ├── config.py         # Settings loaded from .env
│   ├── security.py       # Password hashing and JWT creation
│   ├── dependencies.py   # FastAPI dependency: get_current_user
│   └── logging.py        # Logger configuration
├── db/
│   ├── database.py       # SQLAlchemy engine
│   ├── init_db.py        # Table creation and seed data
│   └── session.py        # get_session dependency
├── errors/
│   └── card.py           # Domain exceptions: CardNotFoundError etc.
├── models/
│   ├── card.py           # Card SQLModel table
│   └── user.py           # User SQLModel table
├── routers/
│   ├── card.py           # Card endpoints
│   └── user.py           # User endpoints (register, login, me)
├── schemas/
│   ├── auth.py           # Token response schema
│   ├── card.py           # CardCreate, CardRead, CardUpdate, CardReplace
│   └── user.py           # UserCreate, UserRead
├── services/
│   ├── card.py           # Card business logic
│   └── user.py           # User business logic and domain exceptions
└── main.py               # App initialisation, lifespan, exception handlers
static/
├── index.html            # Single-page front-end
├── style.css             # Design system and component styles
└── app.js                # API client, state management, DOM rendering
tests/
├── conftest.py           # Shared fixtures: engine, session, user
├── test_card_model.py
├── test_card_schema.py
├── test_card_services.py
├── test_card_router.py
├── test_user_model.py
├── test_user_schema.py
├── test_user_services.py
└── test_user_router.py

Getting Started

1. Clone the repository

git clone https://github.com/your-username/index-todo.git
cd index-todo

2. Create a virtual environment

python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

3. Install dependencies

pip install -r requirements.txt

4. Configure environment variables

cp .env.example .env

Open .env and set SECRET_KEY to a secure random value:

openssl rand -hex 32

5. Run the API server

uvicorn app.main:app --reload

The API will be available at http://127.0.0.1:8000.
Interactive API docs are at http://127.0.0.1:8000/docs.

6. Open the front-end

Open static/index.html directly in your browser. No build step or additional server required.


Front-End

The front-end is a single-page application built with plain HTML, CSS, and JavaScript — no framework or bundler. All three files live in static/.

Views:

  • Login / Register — tabbed auth form with inline validation and error feedback
  • Card list — paginated task list with filter (all / active / completed), per-card edit and delete, and a completion toggle
  • Card form — create and edit tasks with title, notes, tag, due date, and completed state
  • Profile — displays username, account status, and user ID pulled from GET /users/me

Notable details:

  • Session token is stored in sessionStorage — the user stays logged in on page refresh
  • Login uses application/x-www-form-urlencoded as required by the OAuth2 password flow
  • Pagination fetches limit + 1 items to detect next-page availability without a separate count request
  • All API errors surface via a non-blocking toast notification

API Overview

Authentication

Method Endpoint Description
POST /users/ Register a new user
POST /users/login Login and receive a JWT token
GET /users/me Get the current authenticated user

Cards

All card endpoints require a valid Authorization: Bearer <token> header.

Method Endpoint Description
POST /cards/ Create a new card
GET /cards/?skip=0&limit=20 List cards for the current user (paginated)
GET /cards/{id} Get a single card
PUT /cards/{id} Full replacement of a card
PATCH /cards/{id} Partial update of a card
DELETE /cards/{id} Delete a card

Authentication Flow

  1. Register via POST /users/
  2. Login via POST /users/login — returns an access token
  3. Include the token in subsequent requests:
    Authorization: Bearer <your_token>
    

Running Tests

pytest

Run with verbose output:

pytest -v

Run a specific test file:

pytest tests/test_card_router.py -v

Architecture Notes

Layered architecture — HTTP concerns live in routers, business logic in services, and data structure in models and schemas. Services raise domain exceptions (CardNotFoundError, CardAlreadyCompletedError, UserAlreadyExistsError) which are caught by exception handlers in main.py and converted to HTTP responses.

Ownership enforcement — Card ownership is verified at the router layer via a get_card_for_user helper, keeping the service layer free of HTTP concerns.

PaginationGET /cards/ accepts skip and limit query parameters, with a server-side hard cap of 100 items per request regardless of what the client requests.

Test isolation — Integration tests use FastAPI's dependency_overrides to inject an in-memory database session and bypass JWT auth. Each test runs in a transaction that is rolled back on teardown, keeping tests fully isolated without recreating the schema.


Environment Variables

Variable Required Default Description
SECRET_KEY Yes JWT signing key
DATABASE_URL No sqlite:///./app.db Database connection string
DEBUG No false Enables SQL query logging
ACCESS_TOKEN_EXPIRE_MINUTES No 60 Token lifetime in minutes

About

To-Do web application using FastAPI and simple front-end tools.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors