Akshay Jayan
← All projects
Case studyDraft

Hoot

A cross-platform desktop music player with offline playback and a custom theme system.

Role
Design Engineer, independent project
Period
Independent project
Status
Shipped
01 — Overview

Overview

A downloadable desktop music player built with React and Electron — offline playback, playlist management, and a custom theme system, packaged as a standalone app rather than a web page.

02 — Problem

The problem

Most web-based music players assume a live connection and a browser tab that stays open. A desktop-native player needed to own its own window, work fully offline, and feel like an application rather than a website.

03 — Design process

Design process

Built the interaction model around a persistent playback state that survives navigation between screens — the player bar never unmounts, matching how a native media app behaves rather than how a typical React route transition does.

04 — Architecture

Architecture

Electron shell around a React renderer, with playback state and file-system access isolated behind a main-process boundary so the UI layer stays focused on interaction, not file I/O.

05 — Engineering decisions

Engineering decisions

Electron over a PWA

True offline file access and a persistent background player were simpler to guarantee with a native shell than to reproduce reliably through service-worker caching.

06 — Trade-offs

Trade-offs

Distribution weight

Shipping an Electron bundle costs a larger download than a web page — accepted in exchange for the offline guarantees a web build could not make.

07 — Challenges

Challenges

A theme system that reaches native chrome

Making custom theming feel consistent across both the in-app UI and the parts of the window Electron itself controls.

08 — Outcome

Outcome

A shipped, downloadable release with offline playback, playlist management and custom theming.

09 — Technology

Technology

ReactElectronTypeScript
10 — Images

Images

Hoot desktop music player interface preview
11 — Motion

Motion

Transport controls and playlist transitions use short, springy feedback — the kind of motion that makes a native-feeling player feel responsive, not decorative animation layered on top.

12 — Lessons learned

Lessons learned

  • Persistent playback state belongs above the router, not inside a page — a media player is closer to an OS-level widget than a route.