ui.jln.dev: ten thousand shadcn/ui themes, and the stack that stores them
10000+ Themes for shadcn/ui.
At a glance
- What is it?
- A Next.js site that collects more than ten thousand themes for shadcn/ui, with Drizzle over libSQL or PlanetScale, NextAuth with Discord and GitHub providers, Upstash Redis over its REST API, and a Bun toolchain. The repository is small because the work is in the data, not the code.
- Who is it for?
- ui.jln.dev fits a developer who wants a shadcn/ui palette picked rather than designed, and who would rather choose from thousands of ready-made token sets than spend an afternoon on a colour ramp for a product. It is the wrong tool for a brand that needs a coherent design system, because a theme is a set of CSS variables and not a system, and the count of themes is not evidence of variety.
- 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 24 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 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A theme for shadcn/ui is a set of CSS variables
ui.jln.dev is a gallery of more than 10,000 themes for shadcn/ui, and it is worth being clear about what that means technically before looking at the stack, because it determines what the site is.
shadcn/ui is not a component library in the usual sense. It is a set of components that you copy into your own repository, built on Radix primitives, and the visual identity of those components comes from CSS variables, the design tokens that a theme sets. A theme in this gallery is therefore a set of variable values that a project can drop in, and the site's job is to make those sets browsable and copyable.
That explains the shape of the repository. The top level is a conventional Next.js application: `src/` for the application code, `public/` for static assets, `next.config.js`, `tailwind.config.ts`, `postcss.config.cjs` and `components.json`, the last being the shadcn configuration file that records where the components live in your project. The `drizzle/` directory and `drizzle.config.ts` hold the database schema, and `github/` holds the GitHub automation.
The dependency list is what you would expect for a shadcn site, with the whole Radix set pulled in component by component, from `@radix-ui/react-accordion` through `@radix-ui/react-menubar` and the rest, plus `@csstools/color-helpers` for colour manipulation and the author's own `@jlns/hooks`, `@jlns/utils` and `@jlns/zod` packages.
The project is MIT licensed, the primary language is TypeScript, the default branch is `main`, the site is at `ui.jln.dev`, and the last push was on 2026-10-01. There are no GitHub releases, which is consistent with a site rather than a library: the deployed artefact is the website.
The contact details are in the README as well, with a booking link, an X account and an email address at `[email protected]`, and the sponsor section credits Shadcn Studio, which sells shadcn blocks and templates.
Drizzle over libSQL or PlanetScale
The data layer is a theme table, and the tooling around it is the standard Drizzle set.
The environment file is short and tells you most of what the application talks to:
DATABASE_URL=""
DISCORD_CLIENT_ID=""
DISCORD_CLIENT_SECRET=""
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
NEXTAUTH_SECRET="secret"
NEXTAUTH_URL="http://localhost:3000"
UPSTASH_REDIS_REST_TOKEN=""
UPSTASH_REDIS_REST_URL=""
NEXT_PUBLIC_LEGAL_COMPANY_NAME="jlndev"
NEXT_PUBLIC_LEGAL_EMAIL="[email protected]"There is a single `DATABASE_URL`, and the dependencies contain both `@libsql/client` and `@planetscale/database`, which are the two drivers a Drizzle project typically has available, one for a libSQL database, whether local or hosted, and one for PlanetScale. The choice of which one is in use is therefore a deployment decision rather than a code decision, which is the usual reason to depend on both.
The Drizzle Kit commands are wired into the package scripts, which is where the workflow becomes visible:
"scripts": {
"build": "next build --webpack",
"db:push": "dotenv drizzle-kit push",
"db:studio": "dotenv drizzle-kit studio",
"db:studio:prod": "USE_PROD_DB=true drizzle-kit studio",
"db:seed": "bun ./src/scripts/seed.ts",
"db:update-star-count": "bun ./src/scripts/update-star-count.ts",
"dev": "next dev --webpack",
"lint": "eslint .",
"ts:check": "tsc --noEmit"
},`db:push` applies the schema without a migration, `db:studio` opens the Drizzle Studio browser, and `db:studio:prod` does the same against the production database with a `USE_PROD_DB` flag. Both are wrapped in `dotenv`, so the environment file is loaded for the command rather than relying on the shell.
Two seeding scripts matter for a site like this. `db:seed` runs `src/scripts/seed.ts`, which is presumably how the theme table is populated, and `db:update-star-count` runs `src/scripts/update-star-count.ts`, which keeps the GitHub star count of each theme repository up to date. That second script is the interesting one, because it means the site stores a number that is not its own data and has to be refreshed from somewhere else.
NextAuth with Discord and GitHub, and Redis over REST
Authentication is NextAuth, and the environment file shows the shape of it.
The dependencies include `@auth/core` and `@auth/drizzle-adapter`, so the sessions and the user records live in the same Drizzle database as the themes. The environment variables name two OAuth providers, `DISCORD_CLIENT_ID` with `DISCORD_CLIENT_SECRET` and `GITHUB_CLIENT_ID` with `GITHUB_CLIENT_SECRET`, alongside `NEXTAUTH_SECRET` and `NEXTAUTH_URL`. The two providers are the obvious ones for a site whose content is a catalogue of GitHub repositories, and the adapter is what lets a user sign in and then, for instance, star or publish a theme.
Two environment variables are for Upstash Redis, `UPSTASH_REDIS_REST_TOKEN` and `UPSTASH_REDIS_REST_URL`. The pair of a REST token and a REST URL means the application talks to Redis over HTTP rather than over the Redis protocol, which is the shape Upstash offers for serverless environments where a persistent TCP connection to a database is awkward. A theme gallery is exactly that kind of workload: many short requests, and a good deal of caching of things that do not change between requests, such as the theme list and its metadata.
The two `NEXT_PUBLIC_` variables at the end are the legal footer configuration, the company name and the email address, which are read on the client. The `NEXT_PUBLIC_` prefix is the marker for values that are compiled into the browser bundle, and it is the reason those two are public and the rest are not.
The `NEXTAUTH_SECRET` default value in the example file is the string `secret`, which is a placeholder and should be replaced before any deployment, and `NEXTAUTH_URL` points at `http://localhost:3000` for local development, which is the same port the site serves on.
Bun, webpack, ESLint, Prettier and tsc
The toolchain is short and mostly Bun and Next.
The package manager is pinned in the `packageManager` field as `[email protected]`, and the lockfile is `bun.lock`, so the project is a Bun project rather than a Node one. The scripts that touch the database run through `bun` explicitly, and the seed scripts are TypeScript files run with `bun`.
The interesting flag in the build scripts is `--webpack`. Both `next build --webpack` and `next dev --webpack` pass it, which selects the webpack bundler inside Next rather than the default. That is a deliberate choice for a project that cares about a specific bundler behaviour, and it is the kind of detail that matters to anyone reproducing the build.
The quality checks are three separate commands, each with its own configuration file in the root. `lint` and `lint:fix` run ESLint with the configuration in `.eslintrc.cjs`, which is the older configuration format rather than the flat config. `format:write` and `format:check` run Prettier over the JavaScript, TypeScript, markdown and JSON files with `prettier.config.js` and the gitignore as the ignore path. And `ts:check` runs `tsc --noEmit`, so the type check is a separate step from the build rather than something the build does implicitly.
The `analyze` script is the fourth one worth noticing. It runs the production build with `ANALYZE=true`, which is the usual way to switch on a bundle analyzer in a Next application, and the `.env.example` file shows the shape of the configuration the project expects.
The `CONTRIBUTING.md` file is linked from the README for anyone who wants to add a theme, which is the obvious way the catalogue grows.
Where a theme gallery is the wrong tool
The limits are worth stating plainly, because the headline number is impressive and the underlying unit is small.
A theme is a set of CSS variable values. It is not a type scale, not a spacing system, not a set of component states, and not a rule about which components exist. A project that adopts a theme from a gallery has picked a colour ramp and a set of radii and shadows, and it still has to decide what its buttons look like in every state, what its tables do at narrow widths, and what its focus rings are. The gallery supplies the first five percent of a design system and calls it a theme, and the naming is what makes it easy to over-trust.
The number itself is the other half of the question. Ten thousand themes is a quantity, and quantity here is a function of how cheap it is to generate a variation, not of how many distinct designs exist. A browse experience built around a large catalogue is therefore a search problem rather than a curation problem, and a developer who picks the first result that looks pleasant is making a decision about their product from a preview image that nobody has checked for contrast in a real interface.
The second limit is the site itself. It is a Next.js application with a database, an authentication system, a Redis cache and a seeding pipeline, and every one of those is infrastructure that somebody has to run and pay for. A team that wants one palette does not need any of it, and a team that wants a thousand palettes for its users does, which is a different requirement from the one the site serves.
The alternative approach is the one the shadcn ecosystem itself suggests, which is to define your tokens in a `globals.css` and adjust them by hand, or to keep a small set of themes in the repository and switch between them with a class on the root element. That is a few hundred lines of CSS that the team owns, it is reviewable, and it produces two or three coherent designs instead of ten thousand options. The difference in approach is that a gallery optimises for discovery and a project optimises for coherence, and only one of those is a design decision.
The licensing is fine to copy from. The repository is MIT licensed, and the shadcn components and Radix primitives it renders carry their own terms, which is the usual arrangement when you copy components into your own project rather than depending on them at runtime.
Editorial conclusion
ui.jln.dev fits a developer who wants a shadcn/ui palette picked rather than designed, and who would rather choose from thousands of ready-made token sets than spend an afternoon on a colour ramp for a product. It is the wrong tool for a brand that needs a coherent design system, because a theme is a set of CSS variables and not a system, and the count of themes is not evidence of variety. Before using it, check what a theme actually contains in the generated files rather than the preview, remember that the site is MIT licensed while the shadcn and Radix components it renders carry their own terms, and treat the theme as a starting point, because a palette that looks right in a preview has not been checked for contrast in a real interface.
Frequently asked questions
What is ui.jln.dev?
It is a gallery of more than 10,000 themes for shadcn/ui, published as a Next.js site at ui.jln.dev. The repository holds the site itself, with Drizzle for the database, NextAuth for sign-in, Upstash Redis for caching and the Radix primitives that shadcn builds on.
Which database does the ui.jln.dev site use?
The environment file expects a DATABASE_URL, and the dependencies include both @libsql/client and @planetscale/database. The schema is managed with Drizzle Kit through the db:push and db:studio scripts, and db:studio:prod opens the same studio against the production database.
How are the themes and their star counts populated?
The db:seed script runs src/scripts/seed.ts through Bun to populate the theme data, and a separate db:update-star-count script runs src/scripts/update-star-count.ts, which refreshes the GitHub star count shown for each theme from the repository it points at.
What checks run on the ui.jln.dev codebase?
ESLint with the configuration in .eslintrc.cjs, Prettier with prettier.config.js and separate format:write and format:check scripts, and a separate type check with tsc --noEmit as ts:check. The production build runs with next build --webpack and there is an analyze script that sets ANALYZE=true.
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/jln13x-ui-jln-dev)Was this useful?