View all projects

FEATURED PROJECT

Playlist Manager

A full-stack web application for organising and managing video playlists from different platforms across the internet.

playlist.chantellecs.com
Playlist Manager dashboard

Overview

Playlists is a project I built to explore full-stack web development and create a practical application around something I use regularly.

The application allows users to save videos from supported platforms into playlists, organise those playlists into collections, and manage their saved content from one place.

I built the frontend, backend API, database structure, authentication, validation, testing, and deployment pipeline.

Features

Create and manage video playlists

Load video link previews

Add videos from YouTube and TikTok

Search across playlists and videos

Reorder videos within playlists

Edit video titles and descriptions

Choose playlist cover images

Secure user authentication and resource ownership

Currently developing

Collections for organising playlists into groups

Search across collections

Upcoming features

Rich text editor for video notes

Instagram support

Technology

The project uses a Next.js frontend and an Express REST API, with PostgreSQL as the primary database and Redis for short-lived data.

Next.jsTypeScriptTanStack QueryTailwind CSSExpressZodOpenAPIPrismaPostgreSQLRedisDocker

Architecture

The frontend is built with Next.js and communicates with a separate Express REST API. TanStack Query is used to manage server state, including fetching, caching, mutations, and loading and error states.

The backend uses Prisma to interact with PostgreSQL. The database models relationships between users, playlists, videos, and collections while using database constraints to enforce relationships and uniqueness.

Redis is used for short-lived data that does not need to be persisted in PostgreSQL. Docker is used during development to run the project's supporting services locally.

Development and testing

The application is maintained across separate development, testing, and production environments. Integration and end-to-end tests use isolated test containers for postgres and redis to prevent test data from affecting other environments.

The development environment uses Dockerised dependencies to keep local development consistent, including services such as PostgreSQL, Redis, and a local mail server. This allows features involving external services such as email to be developed and tested locally without relying on production services.

Responsive Design

I designed the application to adapt across different screen sizes, with layouts, grids, and controls adjusting between mobile devices and large desktop monitors.

playlist.chantellecs.com
Playlist Manager mobile interface
playlist.chantellecs.com
Playlist Manager desktop interface

API design and type safety

I use Zod to define and validate API schemas in the backend. These schemas are also used to generate the project's OpenAPI documentation, keeping the API specification close to the validation rules used by the application.

The OpenAPI specification is then used to generate TypeScript types for the frontend. This gives the frontend a typed representation of the API contract instead of maintaining request and response types separately.

This approach helps keep the frontend and backend aligned as the API changes, while also providing validation at the API boundary and useful documentation for the available endpoints.

Authentication and security

Authentication uses short-lived access tokens and refresh tokens stored in secure HTTP-only cookies. Refresh tokens are rotated when they are used, with reuse detection to invalidate compromised sessions. Email verification, password reset and user login require two factor authenticated via a code sent to the users email.

API requests also verify that resources belong to the authenticated user before allowing them to be accessed or modified. Input is validated with Zod before it reaches the application logic.

Technical challenges

Authentication sessions

I implemented refresh-token rotation and reuse detection to manage longer-lived sessions while keeping access tokens short-lived.

Video metadata

Adding a video requires retrieving metadata from the supported platform. The backend validates the supplied URL and platform before retrieving the relevant metadata rather than allowing arbitrary remote requests.

Client-side server state

The application has several related pieces of server state, such as playlists and collections. I used TanStack Query to handle caching and mutations while keeping the UI synchronised after changes.

Database design

PostgreSQL is used as the primary database because the application has several connected resources. Users can have multiple playlists, playlists contain videos, and playlists can belong to multiple collections. Prisma is used to model these relationships and provide typed database access from the TypeScript backend.

What I learned

This project gave me experience building a complete application rather than working on an isolated feature. I worked across the frontend, backend, database, authentication, testing, and deployment.

It also gave me a better understanding of how decisions in one part of an application affect the rest of the system, particularly around API design, database relationships, authentication, and client-side state.

The project is still something I continue to improve as I find areas where the design or implementation can be made clearer.