Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
75 changes: 75 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Cursor Rules for Kimu Video Editor

project:
name: "Kimu Video Editor"
language: "TypeScript/React (React Router) + Python FastAPI"
package_manager: pnpm

conventions:
- Prefer central Zod schemas in app/schemas/**; do not define inline schemas in components or routes.
- Always validate external boundaries: AI responses, API inputs/outputs, localStorage, drag-and-drop payloads.
- Keep UI components presentational; move parsing/validation to hooks or route loaders/actions when possible.
- Use named exports and barrel files under app/schemas for discoverability.

imports:
zod:
source: "zod"
identifier: "z"
schemas:
source: "~/schemas"

editor:
formatting:
- Match existing indentation and code style.
- Avoid reformatting unrelated code during edits.
typescript:
- Prefer explicit types for exported APIs; avoid any.
- Use narrow schemas and safeParse for user/LLM data.

testing:
- Add schema unit tests when adding complex schemas.
- Validate response shapes in API route tests.

commit_messages:
- Use scope tags: feat(schemas), refactor(chat), fix(api), chore(tooling).

typescript_guidelines:
- Always enable strict type checking
- Export interfaces and types from dedicated type files
- Leverage a common module for shared types and utilities when possible
- Use proper type imports from @types packages when available
- Follow framework conventions for typing (e.g., Remix loaders/actions, React types)
- DO NOT use the any type
- Prefer importing types from packages before declaring your own
- Avoid type casting; prefer precise types and narrowing
- Prefer inferring types from Zod schemas using z.infer instead of manual type definitions
- For Zod schemas, prefer .nullish().transform((val) => val ?? undefined) over .optional() for null handling; do not combine .nullish() with .default()

project_structure:
overview:
- Frontend (Remix/React) lives under app/
- Backend (FastAPI) lives under backend/
- Centralized Zod schemas live under app/schemas/** with barrel exports in app/schemas/index.ts
- Database/sql migrations under migrations/
- Shared UI primitives under app/components/ui/**
- Timeline/editor components under app/components/timeline/**
- Chat/AI components under app/components/chat/**
- Hooks under app/hooks/**
- Utilities under app/utils/** and app/lib/**

code_organization_rules:
- Keep feature-specific code within its respective directory (timeline, chat, media, etc.)
- Place all Zod schemas under app/schemas/** (components/, apis/, domain files) and import from there (no inline schemas in components/routes)
- Maintain consistent file naming:
- index.ts for barrel exports
- types.ts or types/index.ts for type definitions when schema inference is not applicable
- Remix routes:
- Validate params in loaders/actions with Zod
- Validate request bodies and response payloads (APIs under app/routes/api.*)
- Components:
- Keep presentational; parse/validate data in hooks or route loaders
- Import schemas from app/schemas/components/**
- APIs:
- Import request/response schemas from app/schemas/apis/**
- Validate inputs (safeParse) and outputs (parse) at boundaries
- Prefer z.infer<typeof Schema> to derive TS types from Zod
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
NODE_ENV= # production | development
VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=
DATABASE_URL=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_CLIENT_SECRET=
PROD_DOMAIN= # trykimu.com
2 changes: 1 addition & 1 deletion Dockerfile.frontend
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ COPY . .
RUN pnpm run build

# Expose port
EXPOSE 3000
EXPOSE 5173

# Start the application
CMD ["pnpm", "run", "start"]
173 changes: 143 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,168 @@
<samp>

<h1>Kimu</h1>
<p>Copilot for Video Editing.</p>
<br />

> [!NOTE]
> The application is under active development. This is an early MVP. Please join the [Discord server](https://discord.gg/GSknuxubZK) if you're going to run it.

<br />

<p align="center">
<img src="public/screenshot-app.png" alt="React Video Editor Screenshot">
<img width="3200" height="804" alt="image" src="https://github.com/user-attachments/assets/08149933-609a-4556-8ab4-4ef2622a9c8f" />

</p>
<p align="center">An open-source alternative to Capcut, Canva, and RVE.</p>
<p align="center">A friendly AI powered open-source alternative to Capcut, Canva.<br><samp>
<a href="https://discord.gg/24Mt5DGcbx"> Discord</a> &nbsp; <a href="https://x.com/trykimu"> Twitter</a> &nbsp; <a href="https://trykimu.com"> Website</a></p>
</samp>

## ✨Features

- 🎬Non Linear Video Editing
- 🔀Multi-track Support
- 👀Live Preview
- 📤Export Video
<table>
<tr>
<td>
<img src="https://github.com/user-attachments/assets/c504e379-110d-4286-b2b7-7676aa186112" />
<h2 align="center">Advanced Multi‑Track Editing</h2>
<p align="center">Edit across unlimited tracks with precise control, snapping, and effortless layer management.</p>
<br>
</td>
<td>
<img width="1600" height="1000" alt="image" src="https://github.com/user-attachments/assets/94f05873-2f52-46ad-831a-55936f7999da" />
<h2 align="center">Real‑Time Preview</h2>
<p align="center">See every change instantly with low‑latency playback—no waiting, no rendering.</p>
<br>
</td>
<td>
<img src="https://github.com/user-attachments/assets/3f464355-d290-4586-aead-f9a1a3c58d63" />
<h2 align="center">Fast Export</h2>
<p align="center">Render high‑quality videos quickly and export exactly where you need them.</p>
<br>
</td>
</tr>
<tr>
<td>
<img src="https://github.com/user-attachments/assets/32920f51-4faf-442f-92fc-50d4809cd290" /><h2 align="center">Vibe AI Assistant</h2>
<p align="center">Describe your idea and let Kimu generate edits, timing, and layouts automatically.</p>
<br>
</td>
<td>
<img src="https://github.com/user-attachments/assets/0527e006-8438-466e-83ef-b05d7f98604b" />
<h2 align="center">Smart Media Library</h2>
<p align="center">Organize by type, tags, and sentiment—search and filter your assets in seconds.</p>
<br>
</td>
<td>
<img src="https://github.com/user-attachments/assets/dae66fb2-3e53-46ce-8fe0-10e62ac3cf70" />
<h2 align="center">Cloud‑Synced Projects</h2>
<p align="center">Keep timelines and assets in sync across devices so you can pick up right where you left off.</p>
<br>
</td>
</tr>
</table>
<p align="center">transitions, offline datastore, OAuth based security, change control
<br> and much more...</p>
</samp>

## 💻 Development

<strong> 🐳 <ins>Docker</ins> <code>Recommended</code> </strong>

**Quick Start:**

```bash
docker compose -f docker-compose.yml \
-f docker-compose.dev.yml up -d
```

**Ports:**

<samp>

- Frontend: `5173`
- Backend : `8000`
- FastAPI : `3000`

</samp>
<br>

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

<samp>For local development without Docker:</samp>

## 🐋Deployment
```bash
# Install dependencies
pnpm install

# Start services
pnpm run dev # Frontend (port 5173)
pnpm dlx tsx app/videorender/videorender.ts # Backend (port 8000)
uv run backend/main.py # FastAPI (port 3000)

# Note: You'll need GEMINI_API_KEY for AI features
```
git clone https://github.com/robinroy03/videoeditor.git
cd videoeditor
docker compose up

`Requirements`

<samp>

- Node.js 20+
- Python 3.9+
- PostgreSQL
- pnpm

</samp>
</details>

## 🚀 Production

**Quick Start:**

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

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

```bash
PROD_DOMAIN=yourdomain.com docker compose up -d
```
pnpm i
pnpm run dev (frontend)
pnpm dlx tsx app/videorender/videorender.ts (backend)
uv run backend/main.py
flip `isProduction` to `false` in `/app/utils/api.ts`

You will also require a GEMINI_API_KEY if you want to use AI.
or alternatively edit `docker-compose.yml`

**Ports:**

- HTTP: `80`
- HTTPS: `443`

## ⚙️ Environment Configuration

Create a `.env` file for custom settings:

```env
# Domain Configuration
PROD_DOMAIN=yourdomain.com

# Database
DATABASE_URL=postgresql://user:pass@localhost:5432/videoeditor

# Authentication (Google OAuth)
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret

# AI Features (Optional -> /backend)
GEMINI_API_KEY=your_gemini_api_key

# Supabase (Optional)
VITE_SUPABASE_URL=your_supabase_url
VITE_SUPABASE_ANON_KEY=your_supabase_key
```

## 📃TODO
**Environment Variables Explained:**

- `PROD_DOMAIN`: Your production domain (host only, e.g., `yourdomain.com`)
- `DATABASE_URL`: PostgreSQL connection string
- `GOOGLE_CLIENT_ID/SECRET`: Google OAuth credentials for authentication
- `GEMINI_API_KEY`: Required for AI-powered video editing features
- `VITE_SUPABASE_*`: Optional Supabase integration for additional features

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.
<br>

## ❤️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>
50 changes: 42 additions & 8 deletions app/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
@custom-variant dark (&:is(.dark *));

@theme {
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-sans:
"Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
}

html,
Expand Down Expand Up @@ -202,6 +203,27 @@ body {
max-width: 100%;
}

/* Ultra-thin scrollbar specifically for chat tabs strip */
.chat-tabs-scroll::-webkit-scrollbar {
height: 0px; /* hide horizontal bar */
}
.chat-tabs-scroll::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 9999px;
}
.chat-tabs-scroll::-webkit-scrollbar-track {
background: transparent;
}

/* Hide scrollbar utility (cross-browser) */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}

/* Prevent horizontal overflow in chat areas */
.chat-container * {
max-width: 100%;
Expand Down Expand Up @@ -332,11 +354,14 @@ body {
@keyframes glow-pulse {
0%,
100% {
box-shadow: 0 0 20px rgba(37, 99, 235, 0.1),
box-shadow:
0 0 20px rgba(37, 99, 235, 0.1),
0 0 40px rgba(37, 99, 235, 0.05);
}
50% {
box-shadow: 0 0 30px rgba(37, 99, 235, 0.2), 0 0 60px rgba(37, 99, 235, 0.1);
box-shadow:
0 0 30px rgba(37, 99, 235, 0.2),
0 0 60px rgba(37, 99, 235, 0.1);
}
}

Expand Down Expand Up @@ -489,7 +514,16 @@ body {
}

@keyframes indeterminate-slide {
0% { left: -40%; width: 40%; }
50% { left: 20%; width: 60%; }
100% { left: 100%; width: 40%; }
}
0% {
left: -40%;
width: 40%;
}
50% {
left: 20%;
width: 60%;
}
100% {
left: 100%;
width: 40%;
}
}
Loading
Loading