36e264f3e3
- Wire admin API into homepage + templates page (ISR 60s, null fallback) - Add src/lib/admin-api.ts with safeFetch helper - Add adminProjectToTemplateItem + adminProjectToCatalogTemplate mappers - Add LogoMark SVG component, replace Sparkles icon in Navbar/Footer/Sidebar - Add public/favicon.svg (SVG brand mark) - Rewrite opengraph-image.tsx with FlatRender branding - Add RTL/Persian font cascade: unlayered [dir=rtl] block forces Vazirmatn - Dashboard Settings page: Profile, Security, Billing, Notifications sections - Add src/lib/supabase/client.ts browser client - Admin API: GET /me, PATCH /profile, POST /change-password endpoints - Admin API DTOs: AdminUserDto, UpdateProfileRequest, ChangePasswordRequest - Admin UI Settings page with TanStack Query + mutations - Add CLAUDE.md + README.md to both repos for new-machine onboarding - Update PROJECT_MEMORY.md with session log - Add appsettings.Development.json.example template
408 lines
25 KiB
Markdown
408 lines
25 KiB
Markdown
# 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
|
||
- [x] `.env.example` — all required env vars documented (including `ADMIN_API_URL`)
|
||
- [x] `next.config.mjs` — webpack globalObject fix + COOP/COEP headers (required for ffmpeg.wasm)
|
||
- [x] `.cursorrules` — full project rules for Cursor AI
|
||
- [x] `tailwind.config.ts` — custom colors, font families (heading, body, vazirmatn)
|
||
- [x] `components.json` — shadcn/ui config
|
||
- [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
|
||
|
||
---
|
||
|
||
## 🔄 In Progress
|
||
|
||
_Nothing currently in progress._
|
||
|
||
### 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
|
||
|
||
---
|
||
|
||
## 📋 Backlog (Next Tasks)
|
||
|
||
### 🔴 Must Do Before Launch
|
||
- [ ] 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)
|
||
- [ ] Test full auth flow (sign up → dashboard → create project → open studio)
|
||
- [ ] Test ffmpeg.wasm trimmer end-to-end in browser
|
||
- [ ] Build settings page "Delete account" confirmation flow
|
||
|
||
### 🟡 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 | 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 |
|