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
267 lines
10 KiB
Markdown
267 lines
10 KiB
Markdown
# FlatRender — Claude Instructions
|
|
|
|
> **Read this entire file before touching any code.**
|
|
> This is the single source of truth for the AI assistant working on this project.
|
|
|
|
---
|
|
|
|
## 🗂 Project Layout (two repos, work together)
|
|
|
|
```
|
|
D:\Projects\flatrender\ ← Next.js marketing + studio app (THIS REPO)
|
|
D:\Projects\flatrender-admin\ ← Admin panel (separate repo)
|
|
admin-api\ ← .NET 10 ASP.NET Core Web API
|
|
admin-ui\ ← Vite + React + TypeScript SPA
|
|
```
|
|
|
|
Both repos must be open together — the Next.js app consumes admin-api's public endpoints.
|
|
|
|
---
|
|
|
|
## 🚀 How to Run
|
|
|
|
### Next.js app
|
|
```bash
|
|
cd D:\Projects\flatrender
|
|
npm run dev # → http://localhost:3000
|
|
npm run render-worker # optional — video render worker on :3355
|
|
```
|
|
|
|
### Admin API (.NET 10)
|
|
```bash
|
|
cd D:\Projects\flatrender-admin\admin-api
|
|
# First time: copy appsettings.Development.json.example → appsettings.Development.json
|
|
# Fill in Postgres + MinIO credentials, then:
|
|
dotnet run # → http://localhost:5000
|
|
# Scalar API docs: http://localhost:5000 (root)
|
|
```
|
|
|
|
### Admin UI (React SPA)
|
|
```bash
|
|
cd D:\Projects\flatrender-admin\admin-ui
|
|
npm run dev # → http://localhost:5173
|
|
```
|
|
|
|
### First-time admin seed
|
|
```
|
|
POST http://localhost:5000/api/auth/seed
|
|
Body: { "email": "admin@example.com", "password": "YourPassword123" }
|
|
Only works when zero admin users exist.
|
|
```
|
|
|
|
---
|
|
|
|
## 🛠 Tech Stack
|
|
|
|
| Layer | Technology |
|
|
|---|---|
|
|
| Framework | Next.js 15 App Router, TypeScript |
|
|
| Styling | Tailwind CSS v3, shadcn/ui, Framer Motion |
|
|
| Canvas | React-Konva (Video Studio + Image Editor) |
|
|
| State | Zustand (`studio-store.ts`, `image-editor-store.ts`) |
|
|
| Auth + DB | Supabase (`@supabase/ssr`) |
|
|
| Payments | Stripe |
|
|
| i18n | next-intl (`fa` = default/RTL, `en` = `/en/` prefix) |
|
|
| Fonts | Vazirmatn (Persian RTL), Plus Jakarta Sans + Inter (English) |
|
|
| Video (browser) | ffmpeg.wasm in Web Worker |
|
|
| Video (server) | nexrender + After Effects |
|
|
| Admin backend | .NET 10 ASP.NET Core, EF Core 9 + Npgsql (Supabase Postgres) |
|
|
| Admin storage | MinIO (S3-compatible) |
|
|
| Admin auth | JWT Bearer, BCrypt |
|
|
| Admin UI | Vite + React + TypeScript + Tailwind + TanStack Query |
|
|
|
|
---
|
|
|
|
## 🌐 i18n / Locale Routing
|
|
|
|
- **Persian (`fa`)** — default, no URL prefix, RTL, Vazirmatn font
|
|
- **English (`en`)** — at `/en/` prefix, LTR, Plus Jakarta Sans + Inter
|
|
|
|
Config: `src/i18n/routing.ts`
|
|
Messages: `messages/fa.json` and `messages/en.json`
|
|
Both files must have identical keys — add to both when adding new strings.
|
|
Components use `useTranslations("namespace")` hook.
|
|
|
|
**RTL font rule**: `globals.css` has a `[dir="rtl"]` block that forces Vazirmatn on all elements — do not fight it with utility classes.
|
|
|
|
---
|
|
|
|
## 🔑 Environment Variables
|
|
|
|
Copy `.env.example` → `.env.local` and fill in:
|
|
|
|
```env
|
|
# Admin API (optional — hardcoded fallback when not set)
|
|
ADMIN_API_URL=http://localhost:5000
|
|
|
|
# Supabase — REQUIRED for auth/dashboard/studio
|
|
NEXT_PUBLIC_SUPABASE_URL=
|
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
SUPABASE_SERVICE_ROLE_KEY=
|
|
|
|
# Stripe — required for payments
|
|
STRIPE_SECRET_KEY=
|
|
STRIPE_WEBHOOK_SECRET=
|
|
STRIPE_PRICE_PRO_MONTHLY=
|
|
STRIPE_PRICE_PRO_ANNUAL=
|
|
STRIPE_PRICE_BUSINESS_MONTHLY=
|
|
STRIPE_PRICE_BUSINESS_ANNUAL=
|
|
|
|
# Image background removal
|
|
REMOVE_BG_API_KEY=
|
|
|
|
# Video rendering (RENDER_MOCK=true → skip real rendering in dev)
|
|
RENDER_MOCK=true
|
|
RENDER_WORKER_URL=http://localhost:3355
|
|
NEXRENDER_BINARY=
|
|
NEXRENDER_TEMPLATE_SRC=
|
|
```
|
|
|
|
---
|
|
|
|
## 📁 Key File Map
|
|
|
|
```
|
|
src/
|
|
├── app/[locale]/
|
|
│ ├── page.tsx ← Homepage (async, fetches admin projects)
|
|
│ ├── video-maker/page.tsx ← Video Maker landing
|
|
│ ├── image-maker/page.tsx ← Image Maker landing
|
|
│ ├── templates/page.tsx ← Templates browser (async, fetches admin projects)
|
|
│ ├── pricing/page.tsx ← Pricing page
|
|
│ ├── auth/page.tsx ← Sign in / Sign up (Supabase)
|
|
│ ├── dashboard/
|
|
│ │ ├── layout.tsx ← Auth guard, DashboardShell
|
|
│ │ ├── page.tsx ← Projects grid
|
|
│ │ └── settings/page.tsx ← Settings (Profile, Security, Billing, Notifications)
|
|
│ └── studio/
|
|
│ ├── video/new/page.tsx ← New project onboarding
|
|
│ ├── video/[projectId]/page.tsx ← Video Creation Studio
|
|
│ ├── image/[projectId]/page.tsx ← Image Editor
|
|
│ └── trimmer/page.tsx ← Video Trimmer
|
|
│
|
|
├── components/
|
|
│ ├── layout/
|
|
│ │ ├── Navbar.tsx ← Sticky nav, dropdowns, mobile sheet
|
|
│ │ ├── Footer.tsx ← 4-column dark footer
|
|
│ │ └── SiteChrome.tsx ← Wraps pages in Navbar+Footer (skips dashboard/studio)
|
|
│ ├── ui/
|
|
│ │ └── LogoMark.tsx ← Inline SVG brand icon (used everywhere)
|
|
│ ├── sections/ ← Landing page sections
|
|
│ │ ├── TemplateGallery.tsx ← Accepts adminItems prop from server
|
|
│ │ └── template-gallery-data.ts ← Hardcoded fallback + TemplateItem type
|
|
│ ├── dashboard/
|
|
│ │ └── settings/ ← Settings sub-components
|
|
│ │ ├── SettingsProfile.tsx
|
|
│ │ ├── SettingsSecurity.tsx
|
|
│ │ ├── SettingsBilling.tsx
|
|
│ │ └── SettingsNotifications.tsx
|
|
│ ├── studio/ ← Video Studio (Konva canvas)
|
|
│ ├── image-editor/ ← Image Editor (Konva canvas)
|
|
│ └── templates/ ← Templates page components
|
|
│
|
|
├── lib/
|
|
│ ├── admin-api.ts ← fetchCategories, fetchProjects, fetchProject
|
|
│ ├── supabase/
|
|
│ │ ├── server.ts ← Server-side Supabase client
|
|
│ │ ├── client.ts ← Browser-side Supabase client
|
|
│ │ └── middleware.ts ← Session refresh
|
|
│ ├── studio-store.ts ← Video Studio Zustand store
|
|
│ ├── image-editor-store.ts ← Image Editor Zustand store
|
|
│ ├── video-templates-catalog.ts ← Hardcoded + admin-to-catalog mapper
|
|
│ ├── plans.ts ← PlanId type, Stripe price helpers
|
|
│ └── profiles.ts ← getUserProfile (reads Supabase profiles table)
|
|
│
|
|
├── i18n/
|
|
│ ├── routing.ts ← locales: ["fa","en"], defaultLocale: "fa"
|
|
│ └── request.ts ← getRequestConfig (loads messages JSON)
|
|
│
|
|
└── middleware.ts ← next-intl + Supabase session
|
|
|
|
messages/
|
|
├── fa.json ← Persian translations (default locale)
|
|
└── en.json ← English translations
|
|
|
|
public/
|
|
└── favicon.svg ← SVG favicon (blue rounded square + play icon)
|
|
|
|
supabase/migrations/
|
|
├── 001_profiles.sql
|
|
├── 002_render_jobs.sql
|
|
└── 003_projects.sql
|
|
|
|
server/
|
|
├── render-worker.ts ← HTTP server port 3355
|
|
├── render-job-processor.ts
|
|
└── nexrender-job-builder.ts
|
|
```
|
|
|
|
---
|
|
|
|
## 🔗 Admin API Integration
|
|
|
|
The Next.js app fetches from the admin API server-side with ISR (60-second revalidation).
|
|
|
|
**`src/lib/admin-api.ts`** exports:
|
|
- `fetchCategories(type?)` → `AdminCategory[]`
|
|
- `fetchProjects(opts?)` → `AdminProjectsResponse`
|
|
- `fetchProject(slug)` → `AdminProject | null`
|
|
- `isAdminApiAvailable()` → `boolean`
|
|
|
|
**Fallback behaviour**: If `ADMIN_API_URL` is not set or the service is unreachable, all functions return empty arrays / null — the app works standalone with hardcoded data.
|
|
|
|
**Wired pages**:
|
|
- `app/[locale]/page.tsx` → fetches 8 projects → passes `adminItems` to `<TemplateGallery>`
|
|
- `app/[locale]/templates/page.tsx` → fetches 100 video projects → converts to `VideoCatalogTemplate[]` → passes `initialCatalog` to `<VideoTemplatesPageContent>`
|
|
|
|
---
|
|
|
|
## 🗄 Database (Supabase)
|
|
|
|
Run migrations in order in Supabase SQL Editor:
|
|
1. `supabase/migrations/001_profiles.sql` — profiles (plan, billing_period, stripe IDs)
|
|
2. `supabase/migrations/002_render_jobs.sql` — render_jobs
|
|
3. `supabase/migrations/003_projects.sql` — projects + scene_data
|
|
|
|
---
|
|
|
|
## ✅ What Is Complete
|
|
|
|
- All marketing pages (Home, Video Maker, Image Maker, Pricing, Templates)
|
|
- Full Video Creation Studio (Konva canvas, timeline, layers, transitions, undo/redo)
|
|
- Full Image Editor (Konva canvas, filters, crop, adjustments, layers)
|
|
- Video Trimmer (ffmpeg.wasm, frame strip, export)
|
|
- Auth (Supabase, email/password, Google OAuth)
|
|
- Dashboard (project grid, plan badge, settings page)
|
|
- Stripe checkout + webhook for plan upgrades
|
|
- Admin API backend (full CRUD for categories, projects, media + public endpoints)
|
|
- Admin UI (dashboard, projects, categories, media library, settings)
|
|
- i18n for all public pages (fa + en)
|
|
- Logo brand mark (inline SVG `LogoMark` component)
|
|
- RTL font (Vazirmatn forced via `[dir="rtl"]` CSS)
|
|
|
|
---
|
|
|
|
## ⏳ What Still Needs Setup (credentials required)
|
|
|
|
| Item | Action needed |
|
|
|---|---|
|
|
| Supabase | Create project → get URL + anon key + service key → add to `.env.local` → run 3 SQL migrations |
|
|
| Stripe | Create products with 4 prices → add price IDs to `.env.local` |
|
|
| Admin API DB | Fill `appsettings.Development.json` with real Postgres connection string |
|
|
| MinIO | Run MinIO locally or use S3 → update admin `appsettings.Development.json` |
|
|
| Real template assets | Upload via admin panel → auto-appears on website |
|
|
| Video rendering | Set `RENDER_MOCK=false` + `NEXRENDER_BINARY` path |
|
|
|
|
---
|
|
|
|
## 📝 Coding Conventions
|
|
|
|
- **Server components** for data fetching; **`"use client"`** for interactivity
|
|
- All new translation strings go in **both** `messages/fa.json` AND `messages/en.json`
|
|
- Never hardcode English strings in components — use `useTranslations()`
|
|
- Logo: always use `<LogoMark size={36} />` — never the old `<Sparkles>` icon
|
|
- Admin API calls in page.tsx only (server-side), never in client components
|
|
- TypeScript strict — run `npx tsc --noEmit` before committing
|
|
- Tailwind only — no inline styles except Framer Motion animations
|