2026-05-24 17:37:21 +03:30
# FlatRender — Project Memory
> **Rule:** Read this file before starting any task. Update it after every completed feature, bug fix, or architectural decision.
> Both Cursor AI and Claude Code use this as the project brain.
---
## 📌 Project Identity
| Key | Value |
|---|---|
| Project folder | `D:\Projects\flatrender` |
| Brand name | **FlatRender ** (package: `flatrender` ) — ✅ All UI updated to FlatRender |
| Products | Video Maker · Image Maker |
| Stack | Next.js 14 App Router · TypeScript · Tailwind CSS · shadcn/ui · Framer Motion |
| Canvas | React-Konva (Konva.js) — both Video Studio and Image Editor |
| State | Zustand (`studio-store.ts` , `image-editor-store.ts` ) |
| Auth + DB | Supabase (`@supabase/ssr` ) |
| Payments | Stripe |
| Video (browser) | ffmpeg.wasm in Web Worker (`src/workers/ffmpeg-trim.worker.ts` ) |
| Video (server) | nexrender + Adobe After Effects (`server/render-worker.ts` ) |
| Dev server | `npm run dev` → http://localhost:3000 |
| Render worker | `npm run render-worker` → http://localhost:3355 |
---
## ✅ Completed Features
### Landing Page (`/`)
- [x] `Hero` — gradient on “AI” (`from-blue-600 via-violet-500 to-blue-500` ), dual CTA, preview cards, blobs
- [x] `HeroPreviewCards` — Mixkit MP4 loops, play overlay fades on hover, Framer Motion stagger
- [x] `ProductsShowcase` — Video Maker + Image Maker cards with glassmorphism style
- [x] `TemplateGallery` — filter tabs, 8-card grid, `scroll-mt-20` for sticky nav anchor
- [x] `TemplateCard` — hover Mixkit video via `previewVideoUrl` , bottom "Use Template" CTA, `AnimatePresence` fade
- [x] `template-gallery-data.ts` — `previewVideoUrl` on video/social template entries
- [x] `HowItWorks` — 3-step process, alternating layout, scroll-triggered animations
- [x] `Pricing` — monthly/annual toggle, green “Save 20%” yearly badge, 3 tiers, Stripe checkout wired
- [x] `PricingCompareTable` — full feature comparison table, 5 sections, synced billing toggle, Pro column highlight
- [x] `Testimonials` — 6-card grid
- [x] `FAQ` — accordion, 2-column layout
- [x] `Navbar` — FlatRender logo, Video/Image Maker + Learn dropdowns (shadcn), Pricing link, Sign In / Try for Free; mobile sheet (`navbar-menu-data.ts` )
- [x] `Footer` — 4-column, dark background
### Product Pages
- [x] `/video-maker` — Hero, Features, UseCases, TemplateCarousel, CTA
- [x] `/image-maker` — Hero, BeforeAfter, Gallery, Features, UseCases, CTA
### Templates Page (`/templates`)
- [x] Renderforest layout: 260px category sidebar + carousel rows (`VideoTemplatesCategorySidebar` , `VideoTemplatesCarouselRow` )
- [x] Toolbar: search, Premium Only (Switch), All Sizes select (16:9 / 9:16 / 1:1 / 4:5), Sort by (local state)
- [x] Sidebar filters panel (collapsed): Premium + size; `?category=` from navbar
- [x] `VideoTemplatesPageContent` — client-side filtering via `video-templates-catalog.ts`
- [x] Template detail `/templates/[id]` — `TemplateDetailContent` (preview, styles, Create Now, examples row); `generateStaticParams` from catalog
### Auth (`/auth`)
- [x] Sign In / Sign Up tabs
- [x] Email + password (react-hook-form + zod)
- [x] Google OAuth button
- [x] Supabase auth integration
- [x] OAuth callback route (`/auth/callback` )
- [x] Sign-out route (`/auth/sign-out` )
- [x] `SupabaseSetupNotice` — shown when env vars missing (dev-friendly)
### Dashboard (`/dashboard`)
- [x] `DashboardShell` — layout wrapper
- [x] `DashboardSidebar` — logo, nav links, user avatar + plan badge
- [x] `DashboardTopBar` — search + "New Project" dropdown
- [x] `NewProjectMenu` — Video / Image / Trimmer options
- [x] `DashboardProjectsSection` — projects grid from Supabase; `isLoading` shows 6-card skeleton grid
- [x] `DashboardProjectsContent` — async Supabase fetch (Suspense on `/dashboard` )
- [x] `SkeletonProjectCard` — pulse placeholders matching `ProjectCard` layout
- [x] `DashboardPlanBadge` — async plan fetch; sidebar `Suspense` + `DashboardPlanBadgeSkeleton`
- [x] `DashboardSidebarNav` — client nav (pathname-aware)
- [x] `DashboardEmptyState` — illustration + CTA
- [x] `ProjectCard` — thumbnail, type badge, status, 3-dot menu
- [x] `/dashboard/settings` — settings page
### Video Creation Studio (`/studio/video/[projectId]`)
- [x] `VideoStudioLayout` — icon dock (56px) + fixed 220px tool panel + full-width canvas/timeline (no right `PropertiesPanel` ); `StudioMobileGate` below 768px; `useStudioProjectPersistence` (3s debounced save; dev 404 → `localStorage` `flatrender-project-{id}` )
- [x] `StudioSidebarDock` — Audio / TTS / Colors / Transitions / Font / Watermark + Guide + Keyboard (toasts); blue active bar; scenes via timeline strip only
- [x] `WatermarkSidebarContent` — upload placeholder, 3× 3 position grid, opacity slider
- [x] Sidebar panels — `AudioSidebarContent` , `ColorsSidebarContent` , `TransitionsSidebarContent` (Random / No Transition tiles, apply all scenes), `FontSidebarContent` , `WatermarkSidebarContent`
- [x] `scene-browser-data.ts` , `SceneBrowserCard` , shadcn `Tabs` for media filter
- [x] `/studio/video/new` — Renderforest-style onboarding (Select Scenes / AI / presets) before editor
- [x] `VideoProjectNewContent` , `TEMPLATE_GALLERY_ITEMS` (picsum thumbnails); preset click → `/templates/[id]` ; catalog includes onboarding preset ids
- [x] `SceneBrowserModal` — full-screen library (categories, Video/Photo tabs, search, 28 scenes); onboarding + studio “Browse Scenes”
- [x] `StudioMobileGate` + `useIsMobile` — desktop-only gate for video/image studio (`matchMedia` max-width 767px)
- [x] `ResizableStudioPanel` — drag-to-resize left/right panels
- [x] `StudioTopBar` — breadcrumb (My Projects → name), `StudioTopBarSaveBadge` (Local / Saved ✓ / dot), centered undo/redo + toolbar, `StudioTopBarTextControls` when text layer selected, Export dropdown → `RenderModal` presets
- [x] `PropertiesPanel` — still used by image editor; not mounted in video studio layout
- [x] `dev-project-storage.ts` — dev-only localStorage fallback when Supabase returns 404
- [x] `render-presets.ts` — full / 720p preview / GIF export presets for `RenderModal`
- [x] Scenes managed via timeline `SceneThumbnailStrip` only (no left sidebar scenes panel): 120× 80px blocks, rename, browse (`SceneBrowserModal` ), duplicate/delete on hover
- [x] `SceneTransitionPicker` — None / Fade / Slide / Zoom popover on outgoing scene
- [x] `scene-transitions.ts` — Framer Motion `animate()` playback (300ms fade, slide-left, zoom)
- [x] `DraggableSceneItem` + `SceneItemActions` — live Konva `thumbnailUrl` previews
- [x] `AddSceneMenu` — blank / from template
- [x] `CanvasEditor` — React-Konva Stage (1280× 720), scaled to container
- [x] Text layers (draggable, resizable, rotatable)
- [x] Image layers
- [x] Video clip layers
- [x] Shape layers (rect, circle, line, arrow)
- [x] Transformer (resize handles, rotation, min 8px guard)
- [x] Click empty area → deselect
- [x] Circle drag fix (center-origin correction)
- [x] `CanvasLayerNode` router → `TextLayerNode` , `ImageLayerNode` , `ShapeLayerNode` , `VideoLayerNode`
- [x] `PropertiesPanel` — context-sensitive to selected layer type
- [x] `TextLayerProperties` — font, size, bold/italic, color, align, letter-spacing, line-height, animation style
- [x] `ImageLayerProperties` — opacity, flip H/V, replace, border-radius
- [x] `ShapeLayerProperties` — fill, stroke, stroke-width, border-radius
- [x] `CommonLayerControls` — X/Y/W/H, rotation, z-order, delete
- [x] `PropertyControls` + `useLayerUpdater`
- [x] `Timeline` — 180px Renderforest layout: `TimelineControlBar` , `SceneThumbnailStrip` / `SceneThumbnailBlock` , `TimelineActionRow` ; playhead on strip (`STRIP_PX_PER_SECOND` 24); zoom slider 30– 120
- [x] `TimeRuler` — time markers, click to seek
- [x] `SceneTrack` + `SceneBlock` — color-coded, drag-right-edge to resize duration
- [x] `AudioTrack` — file picker, file name display
- [x] `TimelinePlayhead` — red playhead overlay on thumbnail strip during playback
- [x] Legacy `SceneBlock` / `SceneTrack` / `TimeRuler` / `AudioTrack` — unused by Timeline (kept for reference)
- [x] `StudioToolbar` — add Text / Image / Video / Shape buttons
- [x] `RenderModal` — resolution, FPS, progress bar, download link
- [x] `useCanvasKeyboard` — Delete, Ctrl+C/V/Z/Y
- [x] `useCanvasPreviewPlayback` — scene-by-scene playback with timing
- [x] `useContainerSize` — responsive canvas scaling
- [x] `studio-store.ts` — full Zustand store (scenes, layers, playback, zoom, audio, undo/redo)
- [x] `studio-history.ts` — past/future snapshot undo stack (limit 50)
- [x] `studio-timeline.ts` — duration helpers, zoom levels, scene-at-time
- [x] `studio-types.ts` — Scene, Layer, LayerType, `SceneTransition` , AddLayerInput interfaces
- [x] `studio-snapshot.ts` — Konva stage → PNG download
- [x] `studio-canvas-stage.ts` — global stage ref registry
- [x] `studio-scene-thumbnail.ts` — `toDataURL({ pixelRatio: 0.2 })` + deferred capture after layer edits
- [x] `studio-scene-data.ts` / `image-scene-data.ts` — parse + serialize `scene_data` for persistence
- [x] `ProjectSaveIndicator` — Saving… / Saved / Local save / Save failed (image editor); video studio uses `StudioTopBarSaveBadge`
- [x] `canvas-transform.ts` — node transform → layer coords
- [x] `studio-layer-props.ts` — typed prop accessors per layer type
- [x] `dev-mock-project.ts` — dev-only mock for testing without Supabase
### Video Trimmer (`/studio/trimmer`)
- [x] `TrimmerUploadZone` — drag-drop + click, accepts video/*
- [x] `TrimmerVideoPreview` — `<video>` + `react-rnd` crop overlay, aspect ratio buttons
- [x] `TrimmerStrip` — frame thumbnail strip, draggable trim handles
- [x] `TrimmerExportSection` — MP4/WebM toggle, export button, progress, download
- [x] `ffmpeg-trim.worker.ts` — full ffmpeg.wasm Web Worker (init, progress, process, complete)
- [x] `ffmpeg-worker-client.ts` — typed client to communicate with worker
- [x] `trimmer-types.ts` + `trimmer-utils.ts` — types and crop scaling math
### Image Editor (`/studio/image` and `/studio/image/[projectId]`)
- [x] `ImageEditorLayout` — full-viewport, dark theme; mobile gate; `useImageProjectPersistence` auto-save
- [x] `ImageEditorTopBar` — project name, export button
- [x] `ImageEditorToolbar` — Select, Crop, Text, Shape, Draw, AI tools
- [x] `ImageEditorCanvas` — dynamic import (SSR off), Konva stage
- [x] `ImageBaseLayer` — base image rendering with Konva filters
- [x] `ImageEditorLayerNode` — text/shape/draw layer nodes
- [x] `ImageCropOverlay` — `react-rnd` crop box on canvas (aspect lock)
- [x] `VignetteOverlay` — radial gradient vignette
- [x] `ImageCropControls` — aspect presets (Free, 1:1, 16:9, 4:3, 9:16), Apply/Cancel above canvas
- [x] `image-editor-crop.ts` — aspect math, canvas→source crop, `cropImageDataUrl`
- [x] `ImageEditorRightPanel` — tabbed: Adjust | Filters | Layers
- [x] `AdjustPanel` — brightness, contrast, saturation, hue, blur, sharpen, vignette sliders
- [x] `FiltersPanel` — 12 preset filter thumbnails
- [x] `LayersPanel` — reorder, hide, lock, delete
- [x] `AiRemoveBgModal` — calls `/api/remove-bg` , shows result
- [x] `image-editor-store.ts` — Zustand store for image editor
- [x] `image-editor-filters.ts` — Konva filter pipeline helpers
- [x] `image-editor-konva.ts` — Konva helpers
- [x] `image-editor-types.ts` — ImageLayer, ImageEditorState types
- [x] `image-editor-export.ts` — stage → PNG/JPG/WebP download
- [x] `image-editor-stage-ref.ts` — global stage ref
- [x] `image-editor-transform.ts` — transform helpers
### API Routes
- [x] `POST /api/checkout` — creates Stripe Checkout session
- [x] `POST /api/webhooks/stripe` — updates user plan on checkout.session.completed
- [x] `GET/POST /api/projects` — fetch / create user projects
- [x] `GET/PATCH /api/projects/[projectId]` — load project + auto-save `scene_data`
- [x] `POST /api/remove-bg` — calls remove.bg or rembg service
- [x] `POST /api/render` — queues render job in Supabase
- [x] `GET /api/render/[jobId]/status` — poll render job status
### Server (render worker process)
- [x] `server/render-worker.ts` — HTTP server on port 3355, `/health` + `/process`
- [x] `server/render-job-processor.ts` — fetches job from Supabase, runs nexrender, uploads result
- [x] `server/nexrender-job-builder.ts` — builds nexrender job JSON from scene data
- [x] `server/nexrender.d.ts` — type declarations for @nexrender/core
### Infrastructure
- [x] `supabase/migrations/001_profiles.sql` — profiles table, RLS
- [x] `supabase/migrations/002_render_jobs.sql` — render_jobs table, RLS
- [x] `supabase/migrations/003_projects.sql` — projects table, RLS, updated_at trigger
2026-05-27 09:06:51 +03:30
- [x] `.env.example` — all required env vars documented (including `ADMIN_API_URL` )
2026-05-24 17:37:21 +03:30
- [x] `next.config.mjs` — webpack globalObject fix + COOP/COEP headers (required for ffmpeg.wasm)
- [x] `.cursorrules` — full project rules for Cursor AI
2026-05-27 09:06:51 +03:30
- [x] `tailwind.config.ts` — custom colors, font families (heading, body, vazirmatn)
2026-05-24 17:37:21 +03:30
- [x] `components.json` — shadcn/ui config
2026-05-27 09:06:51 +03:30
- [x] `CLAUDE.md` — Claude Code instructions (auto-read on session start)
- [x] `public/favicon.svg` — brand favicon (SVG, blue rounded square + play icon)
### i18n
- [x] `messages/fa.json` + `messages/en.json` — full translations for all public pages
- [x] Namespaces: hero, nav, products, templates, pricing, testimonials, faq, footer, metadata, videoMaker, imageMaker
- [x] `globals.css` — `[dir="rtl"]` block forces Vazirmatn on all elements in Persian locale
- [x] `src/i18n/routing.ts` — `fa` default (no prefix), `en` at `/en/`
### Brand / Logo
- [x] `src/components/ui/LogoMark.tsx` — inline SVG brand mark (play triangle + 3 layer bars in blue square)
- [x] Navbar, Footer, DashboardSidebar — all use `<LogoMark>` (removed old `<Sparkles>` icon)
- [x] `app/opengraph-image.tsx` — proper FlatRender OG image (1200× 630, headline + feature pills)
### Admin Panel integration
- [x] `src/lib/admin-api.ts` — `fetchCategories` , `fetchProjects` , `fetchProject` , `isAdminApiAvailable`
- [x] `app/[locale]/page.tsx` — async, fetches 8 projects → `<TemplateGallery adminItems={...}>`
- [x] `app/[locale]/templates/page.tsx` — async, fetches 100 video projects → `initialCatalog`
- [x] `TemplateGallery.tsx` — accepts `adminItems` prop, maps `AdminProject` → `TemplateItem`
- [x] `VideoTemplatesPageContent.tsx` — accepts `initialCatalog` prop
- [x] `video-templates-catalog.ts` — `adminProjectToCatalogTemplate()` mapper added
### Dashboard Settings
- [x] `/dashboard/settings` — full settings page (Profile, Security, Billing, Notifications, Danger zone)
- [x] `src/lib/supabase/client.ts` — browser Supabase client (for client-side auth updates)
- [x] `SettingsProfile.tsx` — editable display name via `supabase.auth.updateUser`
- [x] `SettingsSecurity.tsx` — change password (re-authenticates first)
- [x] `SettingsBilling.tsx` — plan info + features + Stripe billing portal link
- [x] `SettingsNotifications.tsx` — 4 email toggle switches
2026-05-24 17:37:21 +03:30
---
## 🔄 In Progress
_ Nothing currently in progress. _
2026-05-27 09:06:51 +03:30
### Status as of 2026-05-27
- `npx tsc --noEmit` — clean (zero TypeScript errors)
- All public pages fully built and i18n'd (fa + en)
- Admin panel fully built (backend + frontend) — needs real Postgres + MinIO credentials
- Admin API integrated into Next.js with ISR fallback
- Logo, favicon, OG image all done
- Dashboard settings page fully functional
- Next step: fill in `.env.local` credentials and test end-to-end
2026-05-24 17:37:21 +03:30
---
## 📋 Backlog (Next Tasks)
### 🔴 Must Do Before Launch
2026-05-27 09:06:51 +03:30
- [ ] Create `.env.local` from `.env.example` and fill in Supabase + Stripe keys
- [ ] Run Supabase migrations (`001` → `002` → `003` ) in SQL Editor
- [ ] Set up admin API: copy `appsettings.Development.json.example` → `appsettings.Development.json` , fill Postgres + MinIO
- [ ] Seed first admin: `POST /api/auth/seed` with email + password
- [ ] Upload real template categories + projects via admin panel (auto-appears on website)
- [ ] Add real logo image/video assets (currently using picsum + Mixkit placeholders)
2026-05-24 17:37:21 +03:30
- [ ] Test full auth flow (sign up → dashboard → create project → open studio)
- [ ] Test ffmpeg.wasm trimmer end-to-end in browser
2026-05-27 09:06:51 +03:30
- [ ] Build settings page "Delete account" confirmation flow
2026-05-24 17:37:21 +03:30
### 🟡 UI Polish (Cursor screenshot-driven)
- [x] Navbar: Video/Image Maker + Learn dropdowns (Renderforest-style, no mega menu)
- [x] Landing polish pass: `rf-blue` / `rf-blue-light` tokens, Hero AI gradient, pricing Save 20% badge, `#templates` scroll-mt-20
- [x] Hero: animated video thumbnail preview cards (autoplay muted)
- [x] TemplateCard: video preview on hover (autoplay muted loop, AnimatePresence fade)
- [x] Studio: scene thumbnail auto-generated from Konva canvas (toDataURL)
- [x] Studio: transition picker between scenes (fade, slide, zoom)
- [x] Dashboard: skeleton loading states for project cards
- [x] Mobile: studio pages desktop gate (under 768px shows `StudioMobileGate` , not full editor)
### 🟢 Nice to Have
- [ ] Template system: pre-built `.aep` templates for nexrender
- [ ] Image editor: text curved/arc effect
- [ ] Image editor: sticker/icon library (200+ SVGs)
- [ ] Video studio: background color/gradient picker per scene
- [ ] Onboarding flow for new users (first project wizard)
- [ ] Usage limits per plan (enforced server-side)
---
## 🐛 Known Issues
| # | Issue | File | Priority |
|---|---|---|---|
| 1 | Brand name "CreatorStudio" in UI | ✅ Fixed 2026-05-21 — all 4 files updated | — |
| 2 | `next.config.mjs` was missing COOP/COEP headers | ✅ Fixed 2026-05-21 | — |
| 3 | Scene thumbnails are placeholder gray boxes | ✅ Fixed 2026-05-21 — `thumbnailUrl` via `updateSceneThumbnail` | — |
| 4 | No loading/error state in trimmer if ffmpeg CDN is slow | `TrimmerExportSection` | 🟡 Medium |
| 5 | Image editor crop tool not fully implemented | ✅ Fixed 2026-05-21 — `ImageCropControls` , `ImageCropOverlay` , pixel crop in `applyCrop` | — |
---
## 🏗️ Architecture Decisions
| Decision | Rationale |
|---|---|
| React-Konva for all canvas work | Consistent layer model across Video Studio and Image Editor |
| ffmpeg.wasm in Web Worker only | Never block main thread; SharedArrayBuffer requires COOP/COEP headers in `next.config.mjs` |
| Zustand for studio state (not React context) | Avoids re-render cascade on every canvas update |
| nexrender + aerender for final render | AE templates give highest quality output; `RENDER_MOCK=true` skips it in dev |
| Supabase RLS on all tables | Row-level security — users can only access their own data |
| `studio-canvas-stage.ts` global stage ref | Allows snapshot/export from any component without prop-drilling |
| Dynamic import for ImageEditorCanvas | Konva cannot run on server — `ssr: false` prevents SSR crash |
| `dev-mock-project.ts` | Dev POST mock; `dev-project` id skips load/save in studio editors |
---
## 🚀 Production-Ready Checklist
| Item | Status |
|---|---|
| `next.config.mjs` — `output: 'standalone'` (Docker) | ✅ |
| `app/sitemap.ts` — `/` , `/video-maker` , `/image-maker` , `/templates` , `/pricing` | ✅ |
| `app/robots.ts` — allow public; disallow `/dashboard` , `/studio` , `/api` | ✅ |
| Page metadata via `createPageMetadata` (public routes + studio layouts) | ✅ |
| `app/pricing/page.tsx` — dedicated pricing route for SEO/sitemap | ✅ |
| `app/error.tsx` — error boundary with reload | ✅ |
| `app/not-found.tsx` — 404 with home CTA | ✅ |
| `npx tsc --noEmit` clean | ✅ (re-run before deploy) |
| `.env.local` + Supabase migrations | ⬜ Operator setup |
| `NEXT_PUBLIC_SITE_URL` set to production domain | ⬜ Required for sitemap/OG URLs |
---
## 🔑 Environment Variables Checklist
| Variable | Status | Where to get it |
|---|---|---|
| `NEXT_PUBLIC_SUPABASE_URL` | ⬜ Not set | Supabase → Settings → API |
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | ⬜ Not set | Supabase → Settings → API |
| `SUPABASE_SERVICE_ROLE_KEY` | ⬜ Not set | Supabase → Settings → API |
| `STRIPE_SECRET_KEY` | ⬜ Not set | Stripe Dashboard → API Keys |
| `STRIPE_WEBHOOK_SECRET` | ⬜ Not set | Stripe → Webhooks → signing secret |
| `STRIPE_PRICE_PRO_MONTHLY` | ⬜ Not set | Stripe → Products → price ID |
| `STRIPE_PRICE_PRO_ANNUAL` | ⬜ Not set | Stripe → Products → price ID |
| `STRIPE_PRICE_BUSINESS_MONTHLY` | ⬜ Not set | Stripe → Products → price ID |
| `STRIPE_PRICE_BUSINESS_ANNUAL` | ⬜ Not set | Stripe → Products → price ID |
| `REMOVE_BG_API_KEY` | ⬜ Not set | remove.bg → API |
| `RENDER_WORKER_URL` | ✅ Default: `http://localhost:3355` | — |
| `RENDER_MOCK` | ✅ Default: `true` | Set to `false` when AE is configured |
| `NEXRENDER_TEMPLATE_SRC` | ⬜ Not set | Path to your `.aep` template file |
| `NEXRENDER_BINARY` | ⬜ Not set | Path to `aerender` executable |
---
## 📁 Key File Map (Quick Reference)
```
src/
├── app/
│ ├── page.tsx ← Landing page
│ ├── video-maker/page.tsx ← Video Maker product page
│ ├── image-maker/page.tsx ← Image Maker product page
│ ├── templates/page.tsx ← Templates gallery
│ ├── pricing/page.tsx ← Pricing (public SEO route)
│ ├── sitemap.ts / robots.ts ← SEO + crawler rules
│ ├── error.tsx / not-found.tsx ← Global error UI
│ ├── auth/page.tsx ← Sign in / Sign up
│ ├── dashboard/page.tsx ← User dashboard
│ ├── studio/
│ │ ├── video/new/page.tsx ← New video project onboarding
│ │ ├── video/[projectId]/page.tsx ← Video Creation Studio
│ │ ├── image/[projectId]/page.tsx ← Image Editor
│ │ └── trimmer/page.tsx ← Video Trimmer/Cropper
│ └── api/ ← All API routes
├── components/
│ ├── layout/ ← Navbar, Footer, SiteChrome
│ ├── sections/ ← Landing page sections
│ ├── studio/ ← Video Studio components
│ ├── image-editor/ ← Image Editor components
│ ├── trimmer/ ← Video Trimmer components
│ ├── dashboard/ ← Dashboard components
│ └── ui/ ← shadcn/ui (do not edit)
├── lib/
│ ├── studio-store.ts ← Video Studio Zustand store
│ ├── studio-types.ts ← Scene / Layer types
│ ├── image-editor-store.ts ← Image Editor Zustand store
│ └── supabase/ ← Supabase client helpers
├── hooks/ ← useCanvasKeyboard, useContainerSize, useIsMobile, etc.
└── workers/
└── ffmpeg-trim.worker.ts ← ffmpeg.wasm Web Worker
server/
├── render-worker.ts ← HTTP server (port 3355)
├── render-job-processor.ts ← nexrender job runner
└── nexrender-job-builder.ts ← builds AE job from scene JSON
supabase/
└── migrations/ ← SQL files, run in order in Supabase SQL Editor
```
---
## 📅 Session Log
| Date | What was done |
|---|---|
| 2026-05-21 | Full project scaffolded: all pages, studio modules, API routes, Supabase migrations, server render worker |
| 2026-05-21 | Fixed `next.config.mjs` — added COOP/COEP headers required for ffmpeg.wasm SharedArrayBuffer |
| 2026-05-21 | Created `PROJECT_MEMORY.md` — project brain for Cursor + Claude |
| 2026-05-21 | Fixed brand name in 4 files: `metadata.ts` , `DashboardSidebar.tsx` , `ProductsMegaMenu.tsx` , `Navbar.tsx` |
| 2026-05-21 | Discovered `ProductsMegaMenu` already fully built — moved from backlog to done |
| 2026-05-21 | Added `PricingCompareTable` with 5 feature sections matching Renderforest /subscription layout |
| 2026-05-21 | Scene thumbnails: `thumbnailUrl` on Scene, `updateSceneThumbnail` , `DraggableSceneItem` img preview |
2026-05-27 09:06:51 +03:30
| 2026-05-27 | Built admin panel at `D:\Projects\flatrender-admin` : .NET 10 API + React SPA. Categories/Projects/Media CRUD, JWT auth, MinIO storage, public endpoints |
| 2026-05-27 | i18n: added `videoMaker` + `imageMaker` namespaces (fa + en), wired `useTranslations` in all 8 components |
| 2026-05-27 | Wired admin API into Next.js: `admin-api.ts` , homepage + templates page async with ISR, `TemplateGallery` accepts `adminItems` |
| 2026-05-27 | RTL fix: `globals.css` `[dir="rtl"]` block forces Vazirmatn on every text element |
| 2026-05-27 | `LogoMark` SVG component — replaces Sparkles in Navbar, Footer, DashboardSidebar; `public/favicon.svg` added |
| 2026-05-27 | OG image rebranded FlatRender with logo, feature pills |
| 2026-05-27 | Dashboard settings page: Profile, Security (pw change), Billing (plan + Stripe link), Notifications toggles |
| 2026-05-27 | Admin API: added `GET /api/auth/me` , `PATCH /api/auth/profile` , `POST /api/auth/change-password` |
| 2026-05-27 | Admin UI: Settings page (profile edit + password change), Settings link in sidebar |
| 2026-05-27 | `appsettings.Development.json.example` created for admin API local setup |
| 2026-05-27 | `CLAUDE.md` created — Claude Code auto-reads on session start |