Self-hosted service
ridhwaans/homehost avatar
ridhwaans/homehost

homehost reads your filenames as a database, and its last release predates its last commit by four years

self-hosted, Netflix-like app made for streaming

1,201 stars135 forksJavaScriptMIT

At a glance

What is it?
A two-package streaming front end where a movie file carries a TMDb identifier in its name and an album directory carries a Spotify one. Two things in the repository are worth reading before you rely on it: the compose file runs the development command and mounts no volume for the database file, and the newest published release is from October 2022 while the branch has been committed to since June 2026.
Who is it for?
homehost fits someone with a tidy collection on a home network who is willing to rename files so each one carries an identifier, and who wants a self-hosted interface rather than a commercial streaming service. It does not fit a large or shared library, because the rule that every item needs its own directory does not survive a folder of miscellaneous films, and the naming contract is only documented in the readme with no validation error described for a wrong identifier.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 115 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The newest tag is from 2022 and the branch has moved since

The release list reads 1.9.2 from October 2022, 1.9.1 from September of the same year, and v1.9 from July 2021. The manifest declares version 1.9.2, which matches the newest tag, so the published line and the declared version agree with each other and disagree with the branch. The last commit is dated June 11, 2026. That is close to four years of work that has never been released as a version, and for a project you install by cloning, the practical question is whether you want the newest tag or the newest commit. The naming is also inconsistent across the three: two tags have no prefix and one does. The development section adds a second promise in the same register, saying it works best in Chrome and that desktop, iOS and Android are coming. Neither statement is a bug, but together they place the project firmly in the category of something you run for yourself rather than something with a support commitment.

Every file carries an identifier, and every item needs its own directory

The naming conventions are the actual interface. For movies, the filename contains a TMDb movie identifier with an mp4 or mkv extension. For television, the show directory carries a TMDb show identifier and the episode files use a season and episode pattern. For music, the album directory carries a Spotify album identifier and the track files carry an optional disc number and a track number. Tracks with no Spotify match have a documented escape hatch, a directory called Unknown Album with no numbers in the filename. Two consequences follow. The first is that renaming is the price of admission, and the identifier is what the scanner uses to fetch metadata, so a mistyped identifier produces a file the library cannot describe. The second is a constraint stated in one sentence that shapes how you organise: each media item must be in a unique location and cannot share directory paths. That rules out a folder of unrelated films side by side, since every one of them would need its own directory, and it is a real constraint on anyone with an existing messy library. The shape for a film is this:

code
<movies_path>
- (subdirectory)?
  - (movie_file_name <TMDb-movie-ID>) (.mp4|.mkv)

Metadata comes from two APIs by identifier, and the index is generated

The database section describes a schema-first flow. A migrate command creates migrations from the schema, applies them, and generates the database client. Only then does homehost scan the media paths and add the files, and the documentation is explicit that you wait for an asynchronous job to finish generating metadata before anything is usable. The data itself lives in a SQLite file whose path is configured alongside the API keys, and there is a browse command that opens a local interface on port 5555 to inspect it, plus a command to clear all data and a narrower one to clear only the items marked unavailable. That narrower command, together with a server route for items that are not available, is the visible acknowledgement that identifier lookups fail sometimes. The metadata sources are named in the environment template: a film database key and a Spotify client identifier and secret, with links to both providers' developer pages for people who do not have credentials yet.

env
TMDB_KEY = '<api_key>'
SPOTIFY_CLIENT_ID = '<client_id>'
SPOTIFY_CLIENT_SECRET = '<client_secret>'

MOVIES_PATH = '/path/to/movies/directory'
TV_PATH = '/path/to/tv/directory'
MUSIC_PATH = '/path/to/music/directory'

DATABASE_URL = 'file:./data/media.db'
CLIENT_BASE_URL = 'http://localhost:3000'

The compose file runs the development command and keeps no database

There is a compose file, and it is worth reading closely. The server half is:

yaml
  server:
    build:
      context: ./packages/server/
    command: npm run start:dev
    ports:
      - 5000:5000
    dns:
      - 8.8.8.8

It builds the server package and the client package from their own directories, maps port 5000 for the server and 3000 for the client, and mounts your three media directories at the same paths inside the containers as on the host, which is a deliberate choice that avoids path translation. Two details are less comfortable. The command for both services is the development start, not the production one, so the compose file is a development environment that happens to be expressed as containers. And no volume is declared for the database, even though the server's environment template points at a SQLite file under a data directory inside the server package. Recreating the container therefore discards the index, and the documented remedy is to run the migrate command and wait for the scan again. The file also pins DNS to a public resolver for both services, which will not resolve internal hostnames and will fail outright on a network that requires its own resolver.

start and start:prod fail in different ways

The root manifest runs the two packages separately and composes them. The development start runs the server and the client together under a concurrency helper with an instruction to kill the others if one fails, so a dead server takes the client down with it and you notice immediately. The production start chains the same two commands with a plain separator instead, so the client runs first and the server runs second regardless of what happened before it, and a failure in the first command does not stop the second. A third variant starts the client in production mode and the server in a demo mode. The ports differ too: development puts the server on 5000 and the client on 3000, while production has the server on 5000 with no separate client port named. There is no documented authentication anywhere in the page, and the routes are all listed without any access control, which is consistent with a tool described as being for a home network.

The route list follows three different naming conventions

The server routes are enumerated rather than described, and reading them is informative about how the code grew. Movies and television get a parallel set with the same suffixes, most popular, highest rated, recently added, genres, a genre parameter, random and an identifier, which is a well-organised surface. Music does not: albums have their own recently added and latest routes, artists have a popular variant, and songs have a recently added route, with identifiers named per resource. Then the naming shifts again for search, where the endpoints are named after the activity rather than the medium, one for watching and one for listening, and there is a separate library statistics route and an availability route. The streaming routes are a fourth convention, one per medium with different parameter styles: an identifier for movies, a show identifier with season and episode numbers for television, and an album identifier with disc and track numbers for music. The client exposes three paths, one per medium, so the messiness is entirely on the server side.

Three installs, husky without a hook, and a credits section with nothing in it

A few small things round out the picture. Installing runs npm three times, once at the root and once in each package, which is what a pre-workspaces layout looks like. The commit hook is configured through a staged-files runner invoked directly rather than through the usual Husky preparation step, and the manifest does not contain a Husky preparation script, so the hooks directory exists but nothing in the manifest installs it. The toolchain is several majors behind: the legacy shared config file and its ignore file sit next to the modern formatter config, and the development dependencies pin a linter on its eighth major, the formatter on its second, Husky on its eighth and the staged runner on its thirteenth. An update checker is installed as a dependency with no update script attached to it. The credits section is empty, holding nothing but a spacing character, and a separate disclaimer file sits at the root alongside a long disclaimer in the readme that covers fair use and takedown handling.

Editorial conclusion

homehost fits someone with a tidy collection on a home network who is willing to rename files so each one carries an identifier, and who wants a self-hosted interface rather than a commercial streaming service. It does not fit a large or shared library, because the rule that every item needs its own directory does not survive a folder of miscellaneous films, and the naming contract is only documented in the readme with no validation error described for a wrong identifier. Four things to check before you start: which release you are running, since the last tag is from 2022 and the readme also promises desktop and mobile clients that do not exist yet; whether your media can be reorganised to the documented shape; where the database lives, since the compose file does not mount a volume for it and recreating a container loses the index; and which ports you are publishing, since both services are mapped to the host and the client is a development server. The project is MIT licensed, works best in Chrome according to its own documentation, and its last commit is dated June 11, 2026.

Frequently asked questions

What is homehost?

A self-hosted streaming front end for a home media collection, with separate sections for movies, television and music. It scans directories you configure, matches each file to metadata using identifiers carried in the filename, and serves everything from its own API and a React client.

How do I install homehost?

Run `npm run install-packages`, which installs dependencies at the repository root and again in the server and client packages, then create the two environment files with a film database key, Spotify credentials, your three media paths and the client base URL. Create the database with `npm run db:migrate` and wait for the metadata scan to finish.

How does homehost know what my media files are?

From the filenames. Movie files carry a film database movie identifier, television show directories carry a show identifier with season and episode patterns inside, and music album directories carry a Spotify album identifier. Tracks with no Spotify match go in a directory called Unknown Album with no disc or track numbers.

Can homehost run in Docker?

There is a compose file that builds the server and client packages, maps ports 5000 and 3000, and mounts your media directories at the same paths inside the containers. Two caveats: it starts the development command rather than the production one, and it declares no volume for the SQLite database file.

Is homehost still maintained?

The branch is being committed to, with the last commit dated June 11, 2026, while the newest published release is 1.9.2 from October 2022 and an earlier one is tagged with a version prefix from 2021. The manifest still declares 1.9.2, so the working branch has moved a long way past the last release.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. ridhwaans/homehost on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ridhwaans-homehost.svg)](https://hysenlabs.com/projects/ridhwaans-homehost)