twotalesanimation 53fc8dc65b
Deploy / deploy (push) Successful in 6m1s
fix(pipeline): re-exports keep a shot's approval, and carry no client-facing text
A shot is routinely re-exported for delivery after it has already been
client-approved — most often an unscaled/un-punched-in pass. Every
pipeline-created Version defaulted to approvalStatus PENDING_REVIEW,
which is exactly what the dashboard counts, the shot page badge and the
playlist read as "awaiting review" — so a re-export made an approved
shot look like new unreviewed work to the whole team, with nothing
actually different about its approval.

approvalStatus is now inherited from the task's previous latest version
rather than left at the create default. A task with no prior version
(its first export) still gets PENDING_REVIEW, which is correct.

Separately, every pipeline version was stamped with notes: "Pipeline
render vXXX (internal only)" — and notes is the artist's message to
reviewers, rendered verbatim in the client portal and the review player.
Nothing enforces that a pipeline version stays unshared once created (see
the gap noted in RenderPipeline2.md), so that internal-sounding string
could reach a client if the shot were re-shared after a re-export. notes
is left unset; what a version is and where it came from belongs on the
Export and its timeline, which is where a human would actually go
looking.

RenderPipeline2.md §9 documents both, plus the share-flow gap that let
notes reach a client in the first place: shareWithClient promotes
whichever Version is isLatest with no awareness that a pipeline version
is meant to stay internal permanently. Not fixed here — closing it needs
a way to identify a pipeline-origin version at the share call sites, and
Export.versionId is currently a one-way scalar with no inverse relation
on Version.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 15:52:49 +02:00
2026-07-08 14:17:03 +02:00
2026-06-11 12:39:01 +02:00
2026-07-08 16:28:18 +02:00
2026-05-19 22:20:29 +02:00
2026-05-19 22:20:29 +02:00
2026-08-07 07:34:10 +02:00
2026-05-19 22:20:29 +02:00
2026-05-19 22:20:29 +02:00
2026-05-20 13:06:04 +02:00
2026-06-11 12:59:39 +02:00
2026-06-11 13:07:59 +02:00
2026-05-29 10:40:28 +02:00
2026-07-08 19:54:24 +02:00
2026-05-19 22:20:29 +02:00
2026-06-11 12:30:28 +02:00
2026-06-11 12:30:28 +02:00
2026-05-19 22:20:29 +02:00
2026-06-11 15:19:12 +02:00
2026-05-19 22:20:29 +02:00
2026-05-19 22:20:29 +02:00
2026-05-19 22:20:29 +02:00
2026-07-22 10:37:13 +02:00
2026-07-11 15:06:12 +02:00
2026-06-11 12:30:28 +02:00

FeedBack — VFX Review & Approval Platform

Frame-accurate video review, annotation drawing, and approval tracking for boutique VFX and animation studios.


Features

  • Dead-simple video upload — drag & drop MP4/MOV, up to 2 GB, version-tracked
  • Frame-accurate scrubbing — canvas-based timeline ruler with click-and-drag seek
  • Timestamp comments — comments anchored to exact frame numbers, threaded replies, resolve/unresolve
  • Annotation drawing — freehand, arrow, rectangle, circle tools with color + stroke width picker
  • Approval workflow — Approve / Reject / Needs Changes with notes, full history
  • Client review links — shareable token-based review URLs for external clients (no login required)
  • Role-based access — Admin / Producer / Supervisor / Artist / Client roles
  • Slack notifications — webhook alerts for uploads and approvals
  • Self-hostable — Docker Compose with PostgreSQL + MinIO (S3-compatible) included

Tech Stack

Layer Technology
Framework Next.js 15 App Router (Turbopack)
Language TypeScript 5 strict
Styling TailwindCSS 3 + shadcn/ui (zinc, dark-only)
Auth NextAuth.js v5 (Credentials + JWT)
Database PostgreSQL 16 via Prisma 6
File Storage UploadThing / S3 / R2 / B2 / MinIO / local
State Zustand 5 (player) + TanStack Query 5 (server)
Annotations HTML5 Canvas API (normalized coordinates)
Video Playback HTML5 <video> with custom controls
Container Docker multi-stage build

Quick Start (Docker)

# 1. Clone and configure
cp .env.example .env
# Edit .env — set AUTH_SECRET, DATABASE_URL, storage provider

# 2. Start services (PostgreSQL + MinIO + App)
docker compose up -d

# 3. Run migrations and seed
docker compose exec app npx prisma migrate deploy
docker compose exec app npx tsx prisma/seed.ts

# 4. Open http://localhost:3000

Demo accounts (after seed):

Email Password Role
admin@vfxreview.local admin123 Admin
producer@vfxreview.local producer123 Producer
supervisor@vfxreview.local supervisor123 Supervisor
artist@vfxreview.local artist123 Artist
client@studio.com client123 Client

Local Development

# Install dependencies
npm install

# Set up database (Postgres must be running)
npx prisma migrate dev
npx tsx prisma/seed.ts

# Start dev server
npm run dev

Open http://localhost:3000.


Environment Variables

See .env.example for full reference. Key variables:

# Required
DATABASE_URL="postgresql://..."
AUTH_SECRET="your-32-char-secret"
NEXTAUTH_URL="http://localhost:3000"

# Storage (choose one)
STORAGE_PROVIDER="local"          # local | uploadthing | s3 | r2 | b2 | minio

# UploadThing (if STORAGE_PROVIDER=uploadthing)
UPLOADTHING_SECRET="sk_live_..."
UPLOADTHING_APP_ID="..."

# AWS S3 / R2 / B2 compatible
S3_ACCESS_KEY_ID=""
S3_SECRET_ACCESS_KEY=""
S3_BUCKET_NAME=""
S3_REGION=""
S3_ENDPOINT=""            # for R2/B2/MinIO

# Slack (optional)
SLACK_BOT_TOKEN=""

# Email (optional, nodemailer)
SMTP_HOST=""
SMTP_PORT="587"
SMTP_USER=""
SMTP_PASS=""

Project Structure

app/
  (auth)/login/          — Sign-in page
  (dashboard)/           — Protected dashboard layout
    dashboard/           — Home stats + shot queue
    projects/            — Project list + detail pages
    settings/            — User profile
  review/[versionId]/    — Full-screen review player
  client/[token]/        — Unauthenticated client review link
  api/
    auth/[...nextauth]/  — NextAuth route handler
    uploadthing/         — UploadThing route handler
    notifications/       — Notification CRUD
    projects/            — Projects REST endpoint

components/
  player/                — ReviewPlayer, FrameTimeline, PlaybackControls
  annotations/           — AnnotationCanvas, AnnotationTools
  comments/              — CommentPanel (threads + replies)
  versions/              — VersionUpload, VersionList
  shots/                 — ShotCard, NewShotDialog
  projects/              — ProjectCard, NewProjectDialog
  dashboard/             — StatsCards, ShotQueue, RecentActivity
  layout/                — Sidebar, Header, NotificationBell, Providers
  ui/                    — shadcn/ui base components

actions/                 — Server Actions (projects, shots, versions, comments, annotations, approvals)
lib/                     — db, auth, utils, frame-utils, storage, slack, notifications, uploadthing
hooks/                   — use-review-player (Zustand), use-annotations, use-frame-comments
prisma/                  — schema.prisma, seed.ts

Review Player Keyboard Shortcuts

Key Action
Space / K Play / Pause
J Reverse playback
L Forward playback
← / → Step one frame
F Toggle fullscreen

Documentation

Doc Covers
RenderPipeline2.md Render pipeline specification — normative design, state machine, API contracts
DELIVERY_WORKFLOW.md Building and shipping delivery packages (how-to)
VFXReviewConnector.md After Effects panel — setup, Shot Builder, QC, diagnostics
RenderWorker/README.md Render worker service — packaging, install, validation, delivery builds
BlenderPanel/README.md Blender add-on — queueing a .blend on the farm
EXT_API_REFERENCE.md External API (/api/ext/*) used by the panel and workers
Shot task workflow.md Shot and task lifecycle in the web app

License

MIT

S
Description
No description provided
Readme 490 MiB
Languages
TypeScript 78.7%
C# 10.5%
JavaScript 7.5%
Python 2.2%
PowerShell 0.5%
Other 0.5%