remotion-dev/github-unwrapped: a year in review video generator built on Remotion and Lambda
Your coding year in review
At a glance
- What is it?
- github-unwrapped is a TypeScript platform that turns a GitHub user's activity into a personal year in review video, rendered with Remotion on AWS Lambda and served from a Vite and Express web app, with MongoDB caching both the rendered videos and the GitHub API responses. It is offered as a template to fork, and the README is unusually clear that the code is MIT while the Remotion framework itself needs a paid licence for companies.
- Who is it for?
- Adopt this repository as a starting point if you want to ship a personalised video product, because it solves the awkward parts of that shape, the render queue, the caching, the credential rotation and the duplicate render problem, and it is explicitly offered as a template to fork.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 109 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the platform is
The pitch is a single line, your coding year in review, and the description gives the shape. It is a platform that generates a year in review video for each GitHub user, built with Vite 5, Remotion and AWS Lambda, and it runs live at GitHubUnwrapped.com.
The interesting part is not the video. It is that generating one video per user is a completely different engineering problem from generating one video. A single render is a batch job. A render for every visitor is a queue, a cache, a rate limit problem and a set of credentials that have to be rotated, and that is what the repository is actually about.
The stack is worth naming because the pieces are chosen for their specific properties. Remotion renders the video, React is the language the video is written in, and the AWS Lambda integration spreads the rendering work across serverless functions in the cloud. The web app itself is a Vite front end with an Express server, MongoDB holds the rendered videos and the cached GitHub responses, and Sentry and Discord carry the monitoring.
A template to fork, and one branch per year
The README invites you to fork the repository and use it as a template for your own year in review for your users, and it flags the legal disclaimers at the bottom of the document before you start.
The versioning scheme is unusual and worth understanding. The 2024 edition is on the `main` branch, the 2023 edition is on a `2023` branch, and the 2022 and 2021 editions live in their own separate repositories, `github-unwrapped-2022` and `github-unwrapped-2021`.
So the project has not been maintained as one evolving application. Each year is a snapshot, because a year in review for 2024 is a different composition, a different set of scenes and a different data pipeline, and trying to make one codebase serve all of them would be more work than starting again from the previous year's snapshot.
That is a deliberate architectural choice with a real consequence. If you fork it, you are forking a specific year's implementation, and the improvements made for the next edition will not flow into your fork. The README is honest about that by the way it presents the branches.
The environment file shows the whole shape of the system
The `.env.example` is the most efficient way to understand what the service needs, because every entry is a decision.
# GitHub App credentials for logging in with GitHub
CLIENT_SECRET=
VITE_CLIENT_ID=
# MongoDB credentials
DB_HOST=
DB_NAME=
DB_PASSWORD=
DB_USER=
# Monitoring credentials
DISCORD_CHANNEL=
DISCORD_TOKEN=
# 6 GitHub tokens for load balancing API requests.
# If you have fewer, enter the same multiple times.
GITHUB_TOKEN_1=
GITHUB_TOKEN_2=
GITHUB_TOKEN_3=
GITHUB_TOKEN_4=
GITHUB_TOKEN_5=
GITHUB_TOKEN_6=
# The domain of the website
VITE_HOST=http://localhost:8080
# Sentry credentials
SENTRY_DSN=
# AWS credentials for running Remotion Lambda with load balancing.
# If you have fewer, enter the same multiple times.
AWS_KEY_1=
AWS_SECRET_1=
AWS_KEY_2=
AWS_SECRET_2=
AWS_KEY_3=
AWS_SECRET_3=
AWS_KEY_4=
AWS_SECRET_4=Six GitHub tokens and four AWS key pairs, each with a comment that says if you have fewer, enter the same multiple times. That is not padding, it is the shape of the rate limit problem. The GitHub GraphQL API has a per token rate limit, and AWS Lambda has a concurrency limit, and both are handled by having several credentials and rotating between them.
The GitHub App credentials are separate from the personal access tokens, and they are for logging in with GitHub, so that a user can connect their own account to the site. The monitoring pair is a Discord channel and token, which is where the operational logs go, and the Sentry DSN is where the exceptions go.
Deploying the functions, and rotating the credentials
The deployment step for the render functions is a single command:
npx tsx deploy.tsand the README notes that some AWS regions are disabled by default, with a link to the Remotion troubleshooting page for the error you get if your region is one of them.
The credential rotation is the part that is genuinely non-obvious. Remotion Lambda reads the standard AWS environment variables, `REMOTION_AWS_ACCESS_KEY_ID` and `REMOTION_AWS_SECRET_ACCESS_KEY`, so to use several accounts the project uses its own variables, `AWS_KEY_1` and `AWS_SECRET_1`, and rotates the standard ones around the render, in `src/helpers/set-env-for-key.ts`.
That is a small file doing a small thing, and it is the piece that makes the multi account strategy work. The alternative would be a patch in the Remotion package or a wrapper around every call site, and the environment variable approach keeps the rest of the code unchanged.
For GitHub the same pattern applies with the personal access tokens, and the setup note explains the scope question clearly. You create a personal access token in your user settings, no need to grant any scopes, because the GraphQL API needs to be authenticated to get public information, and you set it as `GITHUB_TOKEN_1`. Additional tokens are rotated in the same way.
The application code is TypeScript throughout, and the tooling in `package.json` reflects that. The development server is `tsx watch src/server/index.ts` under a development environment variable, the production build runs ESLint, then `node build.mjs`, then the Sentry source map injection, and the deployment script for the Lambda functions is `tsx deploy.ts`.
How the scaling is actually done
The README has a section on scaling strategy, and it contains the two ideas that make the whole thing work for thousands of simultaneous renders.
The first is caching the video whenever possible. Before each render, a MongoDB database lock is created to avoid multiple renders for the same GitHub user being accidentally created. So the database is not only a cache of finished videos, it is the coordinator that stops two requests for the same user from kicking off two renders and two Lambda invocations for the same work.
The second is distributing the renders across an array of AWS regions and accounts, to prevent hitting the Lambda concurrency limit. That is a rate limit problem rather than a throughput problem, and the solution is more quotas rather than more capacity in one place.
The MongoDB instance is described as a free MongoDB Atlas Cloud instance in the setup notes, and the README says the database is used for caching the videos and the GitHub API responses. Caching the API responses as well as the videos is the other half of the cost control, since the GraphQL queries that assemble a user's year are the expensive part and the same user asks for the same data repeatedly.
The deployment of the web app itself is the least remarkable part and worth mentioning for completeness. You connect your repository to Render and set the environment variables there as well, and the local workflow is `npm run dev` for the web app and `npm run remotion` to open the Remotion Studio and edit the video template.
Two licences and an audio clearance, and they are not the same thing
The licence section of the README is the most consequential part of the document for anyone considering a fork, and it has three separate statements.
The code in the repository is licensed under MIT. The Remotion framework, which is a dependency of the project, is a different matter, because companies need to obtain a paid licence, with the terms in the Remotion repository. And the audio was licensed for GitHubUnwrapped.com from SmartSound, so if you create a derivative project you must contact them for licensing.
That last one is the detail that catches people. A year in review video is mostly text and music, and the music is licensed, not open. The MIT licence on the code does not give you the right to publish a video with someone else's soundtrack, and the README is explicit that a derivative project needs a new licence from the audio owner.
The credits section also names GitHub and For One Red for their support in realising and promoting the project, which is worth knowing if you are building something adjacent, because the people who built the year in review format for GitHub have opinions about how it should be done.
What this repository is not
The first wrong case is a team that wants a maintained platform. This is a snapshot of one year's implementation, branched by year, and the improvements for the next edition do not flow into your fork. If you want a product that improves monthly, this is a starting point, not a dependency.
The second is a commercial deployment without a Remotion licence. The code is MIT and the framework is not, and the audio needs a separate clearance, so the cost of a fork is not the engineering.
The third is a use case that is not a video. Everything here is organised around rendering a Remotion composition, so if the goal is to publish a page or send a message, the render pipeline, the Lambda functions and the credential rotation are all cost with no benefit.
The fourth is a data privacy question. The service reads a user's GitHub activity and produces a shareable video of it. The setup notes make a point of the token scope, that no scopes are needed because the GraphQL API only needs to be authenticated to get public information, which is a careful choice, but the resulting video is a public artefact about someone's work, and a deployment has to decide what it does with that.
On the state of the project, the repository is not archived and the last push was on 2026-07-06, with no releases. The dependency versions place it in a specific generation, with Remotion at 4.0.240, Vite 5, React 18, Express 4 and MongoDB 6.3, and the tree has a `remotion/` directory for the compositions, a `public/` directory, a `types/` directory, a `vite/` directory, a `build.mjs` for the build, and helper scripts for the SVG pipeline such as `optimize-svgbin.ts` and `precompute-gradients.mjs`.
Editorial conclusion
Adopt this repository as a starting point if you want to ship a personalised video product, because it solves the awkward parts of that shape, the render queue, the caching, the credential rotation and the duplicate render problem, and it is explicitly offered as a template to fork. Do not adopt it as a finished service without reading the two licence notes, because the code is MIT but the Remotion framework requires a paid licence for companies and the audio has to be relicensed with SmartSound for a derivative work. Verify first that the Remotion licence covers your use, that the GitHub data you fetch is acceptable to expose in a shareable video, and that your AWS accounts and regions are set up for the Lambda concurrency limit the project distributes renders across.
Frequently asked questions
What is the github-unwrapped platform?
It is a platform that generates a year in review video for each GitHub user, built with Vite 5, Remotion and AWS Lambda, and it runs live at GitHubUnwrapped.com. The video is rendered on AWS Lambda, the web app is Vite with an Express server, and MongoDB caches both the rendered videos and the GitHub API responses.
How do I fork the project and run it locally?
Clone it, run `npm i`, rename `.env.example` to `.env` and fill in the values, deploy the Lambda functions with `npx tsx deploy.ts`, then start the web app with `npm run dev` and open the Remotion Studio with `npm run remotion` to edit the template. To deploy the site you connect the repository to Render and set the same environment variables there.
Why does the project need six GitHub tokens and four AWS key pairs?
For load balancing against rate limits. The GitHub GraphQL API has a per token limit and AWS Lambda has a concurrency limit, so the project rotates between several credentials, and the environment file says that if you have fewer you should enter the same ones multiple times. The rotation happens in `src/helpers/set-env-for-key.ts` for AWS.
How does the project avoid rendering the same video twice?
Before each render a MongoDB database lock is created to avoid multiple renders for the same GitHub user being accidentally created. The database therefore acts both as the cache for finished videos and as the coordinator for in flight work.
What are the licensing terms for a fork of github-unwrapped?
The code is MIT licensed, but the Remotion framework that the project depends on requires companies to obtain a paid licence, and the audio was licensed for GitHubUnwrapped.com from SmartSound, so a derivative project must contact them for licensing. The README points to the legal disclaimers at the bottom of the document before you fork.
Official sources
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.
[](https://hysenlabs.com/projects/remotion-dev-github-unwrapped)Was this useful?