All Lab Projects
Pulse logo

Pulse

Auth-gated video discovery app powered by the Pexels Videos API

2026React 19TypeScriptViteReact Router v6Zustand v5TanStack Query v5FormikYupAxiosreact-playermedia-chromeSCSSBEMi18next

What I Built

  • Auth-gated SPA: Formik + Yup login form validates credentials before storing the session in a Zustand v5 slice with Persist middleware, protecting all routes across page reloads
  • Video feed and keyword search against the Pexels Videos API via a typed Axios client; orientation, size and locale filters applied as query params without resetting the TanStack Query cache key unnecessarily
  • Custom video player composed with react-player inside a media-chrome shell, providing accessible, style-agnostic playback controls without overriding native browser UI
  • Playlist navigation and per-video quality selector on the detail page; TanStack Query manages caching and stale-while-revalidate semantics across all API requests
  • SCSS/BEM architecture across all components with design tokens for colour, spacing and transitions defined in a single _variables.scss
  • EN/ES internationalisation via react-i18next with lazy-loaded JSON locale files; language preference persisted to localStorage
  • Pexels API attribution implemented per their terms of service: footer attribution link and per-video author credit on every content-bearing screen

How It Works

  1. 1On first load the app checks Zustand's persisted storage for a valid session; if absent, all routes redirect to the login gate.
  2. 2Formik manages the login form; Yup validates email format and required fields before the auth service compares them against environment-variable credentials and Zustand stores the session.
  3. 3The featured feed and search pages query the Pexels API via Axios, with results cached and paginated by TanStack Query.
  4. 4Each video card navigates to a detail page where react-player renders the video inside a media-chrome shell with a quality selector sourced from the Pexels video files array.
  5. 5Changing the search query or filters updates the TanStack Query key, triggering a new request while the previous cached data is shown as a skeleton during the transition.