Full-Stack Project · 2026

DarkFrame

DarkFrame is a full-stack movie discovery app for horror and thriller films, built with React and TypeScript on top of a custom Node/Express REST API. Users can browse the movie collection and save favorites to their profile. The app also includes account creation and login.

React TypeScript Redux Toolkit Node.js Express MongoDB React Router JWT

A movie library that stays personal.

Real-Time Search

Search results update as users type, so finding a title feels immediate.

JWT Authentication

Account access is handled through JWT-based authentication. Protected views are only available to logged-in users.

Persistent Favorites & Profile Data

Favorite movies are stored in the database and stay connected to each profile across sessions.

Movie details & Metadata

Each title has its own detail view with genre information and director data. Additional metadata gives users more context while browsing.

API-Driven Frontend

The client reads and updates movie and user data through a custom REST API.

Shared State with Redux

Redux Toolkit manages shared movie and user state so updates stay consistent across the app.

Architecture and Stack

DarkFrame is built as a React and TypeScript single-page application. Redux Toolkit handles state that needs to be shared across the app, while UI-specific state stays inside individual components.

The frontend communicates with a separate Node/Express REST API. MongoDB stores the persistent data, while JWTs are used to manage authenticated sessions.

Frontend
React TypeScript Redux Toolkit React Router Bootstrap Parcel
Backend & API
Node.js Express MongoDB Atlas Mongoose REST API
Authentication & Security
JWT Passport express-validator
Tools & Deployment
Netlify Render Postman GitHub dotenv CORS / Morgan

Takeaways

Full-Stack Integration

Building both sides of DarkFrame gave me a clearer understanding of how frontend behavior depends on API design and persistent backend data.

Authentication & User Sessions

Building the login flow around protected routes gave me a much clearer understanding of JWT-based authentication, including how session state should survive a page refresh.

Migrating to TypeScript

DarkFrame started as a JavaScript project. I later migrated the existing frontend incrementally to TypeScript, which made assumptions in the original code much easier to spot.