tweakcn Documentation

A visual no-code theme editor for shadcn/ui components

10,459 stars TypeScript TypeScript 2 files ยท ~1,902 tokens #shadcn#shadcn-theme#shadcn-theme-editor#shadcn-ui#tailwindcss#tailwindcss-v4
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy tweakcn on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name tweakcn -p 3000:3000 --restart always postgres:15
Configured Services & Ports
โš™๏ธ app
image: build locally
๐Ÿ”Œ Ports: 3000:3000
โš™๏ธ db
image: postgres:15
๐Ÿ”Œ Ports: 5432:5432
docker-compose.yml
yaml (docker-compose.yml)
version: "3.8"

services:
  app:
    build: .
    ports:
      - "3000:3000"
    env_file:
      - .env.local
    depends_on:
      - db
    volumes:
      - .:/app
      - /app/node_modules
    command: >
      sh -c "npx drizzle-kit push && npm run dev"

  db:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: tweakcn
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Technical Documentation: jnsahaj/tweakcn

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

Overview (`README.md`)

tweakcn is a powerful Visual Theme Editor for tailwind CSS & shadcn/ui components. It comes with Beautiful theme presets to get started, while aiming to offer advanced customisation for each aspect of your UI

Motivation

Websites made with shadcn/ui famously look the same. tweakcn is a tool that helps you customize shadcn/ui components visually, to make your components stand-out. The goal is to build a platform where a user can discover endless customization options and then have the ability to put their own twist on it.

Current Features

You can find the full feature list here: https://tweakcn.com/#features

Run Locally

IMPORTANT: For contributions, please see CONTRIBUTING.md.

Prerequisites

  • Node.js 18+
  • npm / yarn / pnpm

Installation

  1. Clone the repository:
bash
git clone https://github.com/jnsahaj/tweakcn.git
cd tweakcn
  1. Install dependencies:
bash
npm install
  1. Start the development server:
bash
npm run dev
  1. Open http://localhost:3000 in your browser.

Contributors

Made with contrib.rocks.

Interested in Contributing?

Contributions are welcome! Please feel free to submit a Pull Request.

Star History


Oauth Api (`docs/oauth-api.md`)

OAuth 2.0 API

tweakcn exposes an OAuth 2.0 API so external apps can authenticate users and access their data.

Registering an app

Register an OAuth app via the CLI script:

bash
npx tsx scripts/create-oauth-app.ts \
  --name "My App" \
  --redirect-uris "https://myapp.com/callback" \
  --scopes "themes:read,profile:read" \
  --description "Optional description"

This outputs a client_id and client_secret. The secret is shown once and cannot be retrieved later.

Authorization flow

Standard OAuth 2.0 Authorization Code flow. PKCE is supported but optional.

1. Redirect the user to authorize

text
GET https://tweakcn.com/api/oauth/authorize
  ?client_id=CLIENT_ID
  &redirect_uri=https://myapp.com/callback
  &response_type=code
  &scope=themes:read profile:read
  &state=RANDOM_STRING

If the user is not signed in, they'll be shown a sign-in page. After signing in, they're redirected to your redirect_uri with an authorization code:

text
https://myapp.com/callback?code=AUTH_CODE&state=RANDOM_STRING

2. Exchange the code for tokens

bash
curl -X POST https://tweakcn.com/api/oauth/token \
  -d grant_type=authorization_code \
  -d client_id=CLIENT_ID \
  -d client_secret=CLIENT_SECRET \
  -d code=AUTH_CODE \
  -d redirect_uri=https://myapp.com/callback

Response:

json
{
  "access_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "themes:read profile:read"
}

3. Call the API

Pass the access token as a Bearer token:

bash
curl https://tweakcn.com/api/v1/themes \
  -H "Authorization: Bearer ACCESS_TOKEN"

4. Refresh tokens

Access tokens expire after 1 hour. Use the refresh token to get a new pair:

bash
curl -X POST https://tweakcn.com/api/oauth/token \
  -d grant_type=refresh_token \
  -d client_id=CLIENT_ID \
  -d client_secret=CLIENT_SECRET \
  -d refresh_token=REFRESH_TOKEN

5. Revoke tokens

bash
curl -X POST https://tweakcn.com/api/oauth/revoke \
  -d token=ACCESS_OR_REFRESH_TOKEN

Using with Better Auth's genericOAuth

tweakcn works as a provider with Better Auth's genericOAuth plugin:

typescript
// server
import { genericOAuth } from "better-auth/plugins";

export const auth = betterAuth({
  plugins: [
    genericOAuth({
      config: [
        {
          providerId: "tweakcn",
          clientId: process.env.TWEAKCN_CLIENT_ID,
          clientSecret: process.env.TWEAKCN_CLIENT_SECRET,
          authorizationUrl: "https://tweakcn.com/api/oauth/authorize",
          tokenUrl: "https://tweakcn.com/api/oauth/token",
          userInfoUrl: "https://tweakcn.com/api/oauth/userinfo",
          scopes: ["themes:read", "profile:read"],
        },
      ],
    }),
  ],
});
typescript
// client
import { genericOAuthClient } from "better-auth/client/plugins";

const authClient = createAuthClient({
  plugins: [genericOAuthClient()],
});

await authClient.signIn.oauth2({
  providerId: "tweakcn",
  callbackURL: "/dashboard",
});

API endpoints

All endpoints require Authorization: Bearer <access_token>.

`GET /api/oauth/userinfo`

OIDC-compatible userinfo endpoint. Returns flat user fields. Requires profile:read scope.

json
{
  "sub": "user_123",
  "name": "Jane Doe",
  "email": "[email protected]",
  "picture": "https://..."
}

`GET /api/v1/me`

Returns the authenticated user's profile. Requires profile:read scope.

json
{
  "data": {
    "id": "...",
    "name": "Jane Doe",
    "email": "[email protected]",
    "image": "https://..."
  }
}

`GET /api/v1/themes`

Returns all themes owned by the authenticated user. Requires themes:read scope.

json
{
  "data": [
    {
      "id": "...",
      "name": "My Theme",
      "styles": { ... },
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    }
  ]
}

`GET /api/v1/themes/:themeId`

Returns a single theme by ID. Only returns themes owned by the authenticated user. Requires themes:read scope.

Scopes

Scope Description
themes:read Read the user's saved themes
profile:read Read the user's profile (name, email, avatar)

PKCE support

For public clients (e.g. SPAs, mobile apps), use PKCE by adding code_challenge and code_challenge_method=S256 to the authorize request, then code_verifier when exchanging the code.

Error responses

All error responses follow the OAuth 2.0 spec:

json
{
  "error": "invalid_token",
  "error_description": "Invalid or expired access token"
}

--- METRICS ---