# 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` β€” `