Self-hosted service
jeffernn/joyflix avatar
jeffernn/joyflix

JoyFlix, a self-hosted Next.js streaming front end rebuilt from MoonTV

基于MoonTV(LunaTV)二次开发开箱即用的、跨平台的影视站(内置食用教程)

569 stars1,094 forksTypeScriptNOASSERTION

At a glance

What is it?
JoyFlix is a TypeScript and Next.js 14 video streaming site developed as a rework of MoonTV, with a detail page, streaming search, watch history, favourites and a rewritten player, and it can be deployed to Vercel, Netlify or Docker. It suits people who want to run their own front end against the video APIs they configure, and its own README says the project has stopped being maintained.
Who is it for?
Adopt JoyFlix if you want a self-hosted Next.js streaming front end with multi-account support, a configurable API layer and deployment to Vercel, Netlify or Docker from the same codebase. Do not adopt it expecting an actively maintained project, because the README states the project has temporarily stopped maintenance and that code reviews are no longer performed on pull requests.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 67 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

A full rewrite of MoonTV rather than a fork with patches

JoyFlix is described as a video platform built on top of MoonTV, in the Chinese as a second development of MoonTV, and the README is more specific than that, calling it a complete rework that includes the underlying backend, the front end UI and the interaction logic. The repository description gives the same picture, calling it a ready to use cross-platform film and television site with a built-in tutorial.

The technical stack table lists Next.js 14 with the App Router, Tailwind CSS 3, TypeScript 4, ArtPlayer with HLS.js for playback, and Docker plus Vercel for deployment. The package.json agrees and adds detail, with next at 14.2.23, React at 18.2, tailwindcss and framer-motion for the interface, and both artplayer and vidstack as player libraries alongside hls.js.

Two additional packages explain how the data layer works. cheerio and he are present, which is a server side HTML parser and an HTML entity library, and the README describes the detail page as using server side crawler techniques with third-party API calls and a fallback chain of three different mechanisms to keep data retrieval stable. A config.json at the repository root holds that configuration, and a proxy.worker.js in the root handles the image proxying.

The scope of the rework is listed as sixteen numbered items in the README, and the ones with a functional consequence are the detail page with its three-way fallback, the browsing history that survives a return from the detail page including the scroll position, streaming search, a rewritten favourites page, targeted mobile and desktop layouts, a remember me option and a show password option on the login page, content preloading to cut the perceived delay, and a fix for a memory leak.

Storage decides whether you get accounts and sync

The deployment section in the README has a storage support matrix, and it is the single most consequential decision in the setup.

localstorage is supported and tested on Docker, Vercel and Netlify. Native Redis is supported on Docker only. Upstash Redis is supported on Vercel and Netlify only, and not on Docker.

The README then states the thing that matters, that apart from the localstorage approach, all the other approaches support multiple accounts, record synchronisation and an administration page. So the default deployment, which is the one that works everywhere, is also the one without user accounts, and adding accounts means picking a Redis and matching it to your host.

The environment variables make that concrete. For Upstash on Vercel or Netlify, you create a Redis instance at Upstash, copy the HTTPS endpoint and token, add UPSTASH_URL and UPSTASH_TOKEN to the project's environment variables, and set NEXT_PUBLIC_STORAGE_TYPE to upstash, along with USERNAME and PASSWORD for the superuser account, then redeploy. The redis client and the @upstash/redis client are both in the dependency list, which is how one codebase serves both the Docker and the serverless case.

The Vercel and Netlify flows are otherwise near identical. Fork the repository, import it into the platform, set a PASSWORD environment variable, deploy with the defaults, and edit config.json in your fork if you want to change it. Every push to the main branch triggers a rebuild on both platforms.

The image proxy default breaks posters, and the fix is in the settings

The README carries a warning that is worth reading before you deploy, because the symptom is confusing otherwise.

The default uses an image proxy pointing at the Douban boutique CDN, and because of an API fetch problem this causes some images to load incorrectly. The documented fix is to change the image proxy to a direct connection in the application settings after deployment, or to set it to direct at deployment time through an environment variable. The README is candid about why it is left as is, saying it was too lazy to change the default and asking people to change it manually.

That is a small detail with a large blast radius. Posters are the first thing a user sees on a streaming grid, and a broken image proxy produces a grid of empty boxes that looks like a broken deployment rather than a misconfiguration.

The same pattern of doing configuration at runtime rather than at build time shows up in the Docker image, where the build stage forces dynamic rendering so that runtime environment variables are read. The Dockerfile rewrites the runtime declaration in route.ts files from edge to nodejs during the build, sets DOCKER_ENV, and injects force-dynamic into the root layout, and the runtime stage then copies the standalone output, the scripts directory, start.js, the public directory, the static assets and config.json into a node:20-alpine image that runs as a non-root nextjs user on port 3000.

The custom start script exists for the same reason, to preload the configuration before the server starts.

A three way fallback for fetching titles, and a search that streams

The detail page is the piece the README describes most concretely, and the mechanism is worth understanding because it is unusual.

It uses a server side crawler technique, and then three different retrieval mechanisms, described as a server side crawl, a third-party API call and a search through the backend API, in order, so that a failure in one still leaves data on screen. That fallback chain is a pragmatic answer to the fact that a streaming front end depends on sources it does not control.

The search side was reworked in the same spirit. Search got a popular recommendations feature that combines a database hot update with per-load real-time recommendations, so the page is not static. The search itself was changed to streaming, which the README says raises the response speed, and the ordering of the results and the aggregation logic were both rebuilt.

Other reworked areas listed in the README are the watch history recording logic, the favourites page, the loading page response, which got both speed and visual interest added, and the preferred source scoring mechanism, which was rebuilt to make sure the preferred source is valid to play from, with the stated goals of making the selection more scientific, more effective and faster.

The desktop and mobile interfaces were reworked separately rather than as one responsive layout, with the aim that each device gets the interaction logic that suits it. The player page was changed so the episode list can be inspected with a button or on hover, which the README says avoids long variety show titles breaking the episode selection.

Maintenance is paused, and pull requests are no longer reviewed

The first bullet in the feature list is the one an adopter has to weigh, and it is blunt. The project has temporarily stopped maintenance, and capable contributors are invited to send pull requests, with the requirement that the changes work, accompanied by a video or photo showing them running. The README adds that the code is no longer reviewed.

Everything else in the README is written in the voice of an active project, which makes this line easy to skim past. It is the difference between a fork you adopt and a fork you maintain yourself.

The rest of the contribution guidance is still there. The project says contributions are welcome, points people at an issue or a Telegram group, and asks that any code be reviewed and edited carefully by others.

The one contribution rule worth noting is a request not to publish videos or articles promoting the project on Bilibili, Xiaohongshu, WeChat public accounts, Douyin, Toutiao or other social platforms in mainland China, and a statement that no tech weekly or monthly type project or site is authorised to list the project. The repository licence field is one GitHub cannot classify, with a LICENSE file at the root, so the terms are in that file rather than in a standard identifier.

Editorial conclusion

Adopt JoyFlix if you want a self-hosted Next.js streaming front end with multi-account support, a configurable API layer and deployment to Vercel, Netlify or Docker from the same codebase. Do not adopt it expecting an actively maintained project, because the README states the project has temporarily stopped maintenance and that code reviews are no longer performed on pull requests. Before you deploy, read the image proxy warning and switch it to direct connections or set the environment variable to match, and note the release picture, where the repository publishes no tagged versions and the last push was on 2026-08-17.

Frequently asked questions

What is JoyFlix and what is it based on?

JoyFlix is a TypeScript and Next.js 14 video streaming site developed as a complete rework of MoonTV, covering the backend, the front end UI and the interaction logic. It uses ArtPlayer with HLS.js for playback and can be deployed to Vercel, Netlify or Docker.

Which storage backends does JoyFlix support and what do they add?

localstorage works on Docker, Vercel and Netlify, native Redis works on Docker only, and Upstash Redis works on Vercel and Netlify only. Apart from localstorage, all of them support multiple accounts, record synchronisation and an administration page, and the Redis options use the NEXT_PUBLIC_STORAGE_TYPE variable set to upstash along with UPSTASH_URL and UPSTASH_TOKEN.

Why do some images fail to load in JoyFlix?

The default image proxy points at the Douban boutique CDN, and an API fetch problem causes some images to load incorrectly. The fix is to change the image proxy to a direct connection in the application settings after deployment, or to set it to direct at deployment time through an environment variable.

Is JoyFlix still being maintained?

The README states the project has temporarily stopped maintenance, that contributors are welcome to send pull requests with evidence that the changes work, and that the code is no longer reviewed. There are no tagged releases and the last push to the main branch was on 2026-08-17.

How do I deploy JoyFlix to Vercel?

Fork the repository to your GitHub account, import it in Vercel through Add New and Project, set a PASSWORD environment variable, and deploy with the defaults. To customise, edit config.json in your fork, and every push to the main branch triggers a rebuild. You can also bind a custom domain to the assigned one.

Official sources

  1. Issues
  2. jeffernn/joyflix on GitHub
  3. README
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/jeffernn-joyflix.svg)](https://hysenlabs.com/projects/jeffernn-joyflix)