← All projects

Full-stack · Security · Team project

TaxAlly

An AI-assisted tax management platform that helps individuals, sole traders and small businesses through UK Self Assessment. Built by a team of five in my final year. I owned authentication, account registration and privacy consent, and the financial Insights dashboard.

  • Next.js
  • React
  • TypeScript
  • Django REST Framework
  • PostgreSQL
  • JWT
  • Docker
  • Jenkins

Overview

TaxAlly brings a user's income, transactions and tax position into one place. Users record transactions, see their Income Tax, National Insurance and dividend tax calculated against the UK bands with reliefs applied, explore what-if scenarios, get alerts, and ask an AI tax assistant built on Claude with retrieval over embedded guidance (Voyage AI embeddings in PostgreSQL with pgvector).

The Next.js front end talks to a Django REST Framework API. Everything runs in Docker containers (PostgreSQL, Django, Next.js), and a Jenkins pipeline tests, lints, security-scans and deploys it.

My role & team

We were a team of five, working from issue-linked feature branches with merge requests into a shared development branch. I made over 70 commits and owned these areas end to end:

  • Authentication: the login and registration API and front end, JWTs held in HttpOnly cookies, CSRF protection, a cookie-based token refresh so sessions survive a page reload, and protected routes across the app.
  • Registration & privacy: the sign-up flow with client- and server-side validation, a per-user privacy and preferences model, consent-gated account creation, and the privacy policy page.
  • Financial Insights: the Insights API and dashboard: income broken down by tax year starting on 6 April, annualised Income Tax and National Insurance, and charts plotting tax alongside transaction data.
  • Testing & setup: backend unit tests and API end-to-end tests with pytest for login, registration and Insights, plus the starter repository and the project README.

Security

  • Tokens out of JavaScript's reach: access and refresh JWTs live in HttpOnly, SameSite cookies rather than browser storage, with a 60-minute access token and 7-day refresh token.
  • CSRF protection on login, registration and logout, using Django's CSRF token alongside the cookie-based session.
  • Validation and sanitisation on both sides: the browser and the API each check every field. Emails are normalised and pattern-checked, inputs are trimmed and length-limited, new passwords need upper case, lower case and a number, and the server rejects sign-ups without the required consents. Errors come back as clear messages, not raw failures.
  • Strong password hashing with Argon2, using a raised cost of 100 MB memory and four iterations.
  • Team-wide: TOTP multi-factor authentication, and a pipeline stage running Safety and Bandit on the Python code and npm audit on the front end.

What I'd improve next

  • Make the Safety and Bandit stages fail the build on high-severity findings; at the moment they report without blocking.
  • Move rate limiting to a shared cache such as Redis, so limits hold across multiple server workers.
  • Add unit tests for the Insights calculations at tax-year boundaries and with missing data, which is where we found and fixed null annualised values late on.

TaxAlly's code is in a private university repository. I'm happy to walk through it in an interview.