Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
153f506
chore: setup stable dev environment + update routes to logical names
sr2echa May 1, 2026
691f8cf
refactor: integrate BetterAuth
sr2echa May 2, 2026
1985bbe
fix: improve session token extraction
sr2echa May 2, 2026
ed4c14e
chore: enhance UX and optimize performance + introduce zod schemas
sr2echa May 2, 2026
e296c0a
chore: enhance UX and implement enhancements + introduced Zod Schemas
sr2echa May 2, 2026
2cd3490
feat: r2 object store for assets
sr2echa May 3, 2026
2bb5796
chore: update docker and actions
sr2echa May 3, 2026
874378c
refactor: codebase hardening
sr2echa May 3, 2026
9ca22c9
refactor: enhance ChatBox hydration logic
sr2echa May 3, 2026
2228cf4
Delete .claude/settings.local.json
sr2echa May 3, 2026
0632979
refactor: optimize asset upload handling and improve rate limiting logic
sr2echa May 3, 2026
8dd9d5a
feat: add Redis support for rendering queue and enhance render status…
sr2echa May 3, 2026
216078e
feat: implement ripple edit functionality for scrubber resizing and s…
sr2echa May 3, 2026
e6bff7b
feat: add playback rate and volume control to scrubber component
sr2echa May 3, 2026
19aa88b
feat: enhance rendering options, ui
sr2echa May 3, 2026
1fb58ea
refactor: improve UI consistency across panels
sr2echa May 3, 2026
28ca7ac
feat: enhance export panel with rendering status and quality descript…
sr2echa May 3, 2026
277539d
feat: add waveform visualization for audio clips in scrubber component
sr2echa May 3, 2026
379e702
feat: implement scrubber management features in ChatBox component
sr2echa May 3, 2026
dc2e48f
feat: add keyframe management and navigation features to timeline com…
sr2echa May 4, 2026
cba2ec7
feat: enhance timeline component with improved scrubber functionality…
sr2echa May 4, 2026
420222e
some ui changes
sr2echa May 20, 2026
738ef15
some more ui changes
sr2echa May 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
node_modules
build
.react-router
build
dist
out
coverage
*.log
.env
.git
.gitignore
.env
.env.*
!.env.example
README.md
docker-compose.yml
Dockerfile*
docker-compose.dev.yml
Dockerfile*
.github
.vscode
.idea
*.bak
*.tmp
*.temp
23 changes: 20 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Local/Docker Postgres: postgresql://videoeditor:videoeditor@localhost:5432/videoeditor
# Supabase Session Pooler: postgresql://postgres.REF:password@aws-0-REGION.pooler.supabase.com:5432/postgres
DATABASE_URL=
VITE_GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
JWT_SECRET= # for the jwt secret, you can use `openssl rand -hex 32` to generate a random string
DATABASE_SSL= # Set to "true" when using Supabase or any remote DB that requires SSL. Omit for local/Docker Postgres.

REDIS_URL= # redis://localhost:6379/0 (required for render queue)

BETTER_AUTH_SECRET= # openssl rand -hex 32
BETTER_AUTH_URL= # https://trykimu.com (production) or http://localhost:5173 (dev)
GOOGLE_CLIENT_ID= # Google OAuth client ID
GOOGLE_CLIENT_SECRET= # Google OAuth client secret
GEMINI_API_KEY=

# NODE_ENV=production # Set to "production" to disable uvicorn hot-reload

# Cloudflare R2 object storage
R2_ACCOUNT_ID= # From Cloudflare dashboard → R2 → Overview
R2_ACCESS_KEY_ID= # R2 API token access key
R2_SECRET_ACCESS_KEY= # R2 API token secret key
R2_ASSETS_BUCKET=
R2_RENDERS_BUCKET=

25 changes: 14 additions & 11 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,60 +8,63 @@

jobs:
frontend:
name: Frontend ESLint and TS
name: Frontend ESLint, TS, Format, Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: "pnpm"

- name: Install deps
run: pnpm install --frozen-lockfile

- name: Generate router types & TS typecheck (tsc)
run: pnpm run typecheck --noEmit
run: pnpm run typecheck

- name: ESLint
run: pnpm eslint . --ext .ts,.tsx --fix
- name: ESLint (read-only)
run: pnpm eslint . --max-warnings 0

- name: Prettier format (auto-fix)
run: pnpm format
- name: Prettier format check
run: pnpm format:check

- name: Build (production SSR bundle)
run: pnpm run build

backend:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
name: Backend Ruff and mypy
name: Backend Ruff, format, mypy
runs-on: ubuntu-latest
defaults:
run:
working-directory: backend
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Python (uv)
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
python-version: "3.12"

- name: Install deps (with dev extras)
run: uv sync --extra dev --dev
- name: Install deps (with dev group)
run: uv sync --dev

- name: Ruff check
run: uv run python -m ruff check .

- name: Ruff format (auto-fix)
run: uv run python -m ruff format .
- name: Ruff format check
run: uv run python -m ruff format --check .

- name: mypy
run: uv run mypy .

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
58 changes: 29 additions & 29 deletions Dockerfile.backend
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
# Backend Dockerfile
# Node "renderer" service — runs Remotion render jobs via a small Express server.
# Single stage: Chromium runtime deps and the Node app share the same image.

FROM node:22-bookworm-slim

WORKDIR /app

# Install Chrome dependencies
RUN apt-get update
RUN apt install -y \
libnss3 \
libdbus-1-3 \
libatk1.0-0 \
libgbm-dev \
libasound2 \
libxrandr2 \
libxkbcommon-dev \
libxfixes3 \
libxcomposite1 \
libxdamage1 \
libatk-bridge2.0-0 \
libpango-1.0-0 \
libcairo2 \
libcups2

# Install pnpm
RUN npm install -g pnpm

# Copy package files and install dependencies
# Remotion / Chromium runtime dependencies.
RUN apt-get update && apt-get install -y --no-install-recommends \
libnss3 \
libdbus-1-3 \
libatk1.0-0 \
libgbm-dev \
libasound2 \
libxrandr2 \
libxkbcommon-dev \
libxfixes3 \
libxcomposite1 \
libxdamage1 \
libatk-bridge2.0-0 \
libpango-1.0-0 \
libcairo2 \
libcups2 \
curl \
&& rm -rf /var/lib/apt/lists/*

RUN corepack enable

COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# Copy source code
COPY . .
RUN mkdir -p /app/out && chown -R node:node /app

# Create output directory for rendered videos
RUN mkdir -p /app/out
USER node

# Expose port
EXPOSE 8000

# Start the backend
CMD ["pnpm", "dlx", "tsx", "app/videorender/videorender.ts"]
# Renderer is deployed to a separate host; use `pnpm dlx tsx` so the binary is fetched on that
# system rather than baked into the image (keeps tsx out of node_modules at install time).
CMD ["pnpm", "dlx", "tsx", "app/videorender/videorender.ts"]
43 changes: 26 additions & 17 deletions Dockerfile.frontend
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
# Frontend Dockerfile
# Multi-stage frontend build. Builder installs full deps and produces the React Router SSR bundle;
# runtime ships only production deps + the built artifact.

# ─── Build stage ─────────────────────────────────────────────────────────────
FROM node:20.18-bookworm-slim AS builder

FROM node:20-bookworm-slim
WORKDIR /app

# Install pnpm
RUN npm install -g pnpm
# Install pnpm directly; Node 20's bundled corepack can fail signature verification in Docker.
RUN npm install -g pnpm@9.15.9

# Copy package files and install dependencies
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# Build-time args for Vite env injection
ARG VITE_SUPABASE_URL
ARG VITE_SUPABASE_ANON_KEY

# Expose VITE_* to the build step (and keep at runtime for client hydration if needed)
ENV VITE_SUPABASE_URL=$VITE_SUPABASE_URL \
VITE_SUPABASE_ANON_KEY=$VITE_SUPABASE_ANON_KEY

# Copy source code and build
COPY . .
RUN pnpm run build

# Expose port
# Drop dev deps so the next stage can copy a lean node_modules.
RUN pnpm prune --prod

# ─── Runtime stage ───────────────────────────────────────────────────────────
FROM node:20.18-bookworm-slim AS runtime

WORKDIR /app

RUN npm install -g pnpm@9.15.9

COPY --from=builder /app/package.json /app/pnpm-lock.yaml ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/build ./build
COPY --from=builder /app/public ./public

# Run as the unprivileged "node" user shipped in the base image.
USER node

EXPOSE 3000

# Start the application
CMD ["pnpm", "run", "start"]
CMD ["pnpm", "run", "start"]
121 changes: 105 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,35 +56,124 @@
<br> and much more...</p>
</samp>

## 🐋Deployment
## 💻 Development

<strong> 🛠️ <ins>Local Development</ins></strong>

Only postgres runs in Docker. All three services run directly on your machine — Vite handles proxying so no nginx is needed.

```bash
# Install dependencies
pnpm i
cd backend && uv sync && cd ..

# 1. Start postgres
docker compose -f docker-compose.dev.yml up -d

# 2. Start FastAPI (terminal 1)
cd backend && uv run uvicorn main:app --reload --port 3000

# 3. Start renderer (terminal 2)
pnpm dlx tsx app/videorender/videorender.ts

# 4. Start frontend (terminal 3)
pnpm dev
```
git clone https://github.com/robinroy03/videoeditor.git
cd videoeditor
docker compose up

Open **`http://localhost:5173`**. The Vite dev server proxies requests transparently:

<samp>

- `/backend/*` → FastAPI at `:3000`
- `/renderer/*` → Renderer at `:8000`
- `/*` → React Router SSR (Vite)

</samp>

`Requirements`

<samp>

- Node.js 20+
- Python 3.12+
- pnpm
- Docker (for postgres only)

</samp>

## 🚀 Production

Everything runs in Docker behind nginx. One command:

```bash
docker compose up -d
```

## 🧑‍💻Development
**With Custom Domain:**

```bash
PROD_DOMAIN=yourdomain.com docker compose up -d
```
docker compose -f docker-compose.dev.yml up
migrate the db (docker exec -i videoeditor-postgres-dev psql -U videoeditor -d videoeditor -f /dev/stdin < migrations/000_init.sql)
pnpm run dev (frontend)
pnpm dlx tsx app/videorender/videorender.ts (backend)
cd backend
uv run main.py

localhost:8080 for the server

nginx routes:

<samp>

- `/backend/*` → FastAPI
- `/renderer/*` → Renderer (video rendering)
- `/*` → Frontend (React Router SSR)

</samp>

**Ports:**

- HTTP: `80` (redirects to HTTPS)
- HTTPS: `443`

## ⚙️ Environment Configuration

Copy `.env.example` to `.env` and fill in your values:

```env
# Local/Docker Postgres (dev or self-hosted prod):
DATABASE_URL=postgresql://videoeditor:videoeditor@localhost:5432/videoeditor

# — OR — Supabase Session Pooler (cloud):
DATABASE_URL=postgresql://postgres.REF:password@aws-0-REGION.pooler.supabase.com:5432/postgres
DATABASE_SSL=true # required for Supabase; omit for local/Docker Postgres

# BetterAuth
BETTER_AUTH_SECRET= # generate with: openssl rand -hex 32
BETTER_AUTH_URL=https://yourdomain.com # http://localhost:5173 for dev

# Google OAuth
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret

# AI Features (optional)
GEMINI_API_KEY=your_gemini_api_key
```

**Environment Variables Explained:**

- `DATABASE_URL`: PostgreSQL connection string. Use the local Docker URL for dev/self-hosted prod, or the Supabase Session Pooler URL for cloud.
- `DATABASE_SSL`: Set to `"true"` when connecting to Supabase or any remote DB that requires SSL. Leave unset for local/Docker Postgres.
- `BETTER_AUTH_SECRET`: Random secret used to sign sessions — generate with `openssl rand -hex 32`.
- `BETTER_AUTH_URL`: The public URL of the app. Used by BetterAuth for OAuth callbacks.
- `GOOGLE_CLIENT_ID/SECRET`: Google OAuth credentials — register at [console.cloud.google.com](https://console.cloud.google.com).
- `GEMINI_API_KEY`: Required for AI-powered video editing features.

<br>

## 📃TODO

We have a lot of work! For starters, we plan to integrate all Remotion APIs. I'll add a proper roadmap soon. Join the [Discord Server](https://discord.com/invite/GSknuxubZK) for updates and support.
<samp> We have a lot of work! For starters, we plan to integrate all Remotion APIs. I'll add a proper roadmap soon. Join the [Discord Server](https://discord.com/invite/GSknuxubZK) for updates and support. </samp>

## ❤️Contribution

We would love your contributions! ❤️ Check the [contribution guide](CONTRIBUTING.md).
<samp> We would love your contributions! ❤️ Check the [contribution guide](CONTRIBUTING.md). </samp>

## 📜License

This project is licensed under a dual-license. Refer to [LICENSE](LICENSE.md) for details. The [Remotion license](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md) also applies to the relevant parts of the project.
<samp> This project is licensed under a dual-license. Refer to [LICENSE](LICENSE.md) for details. The [Remotion license](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md) also applies to the relevant parts of the project. </samp>

Loading
Loading