feat(remotion): asset-library catalog + Phase 0 (license firewall, @remotion/lottie, 30 CC0 characters)
- docs/ASSET_LIBRARY.md: curated catalog from the asset sweep (91 sources -> 62 usable) + completeness-critic reality check; clean CC0/MIT tier, license/geo traps, and the 2.5D layered-scene plan (sky->room->furniture->device->character ->grain) to fix the "naked scene". - deps: add @remotion/lottie@4.0.290 (runtime) + DiceBear (build-time devDep). - scripts/gen-dicebear.mjs: generate 30 CC0 Open-Peeps characters OFFLINE (no runtime CDN) into public/illustrations/dicebear/ + a per-file assets.json ledger. - scripts/check-assets.mjs: license-firewall CI guard — fails on any un-ledgered vendored asset. - AssetSheet dev composition: proves vendored SVG -> staticFile() -> Remotion render (30 real characters render cleanly). - NOTE: GitHub (Open Peeps/IRA/Notion git clones) + Gumroad (Lukasz) are geo-blocked headless here; those + Humaaans (Figma export) need a manual/mirror fetch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@@ -0,0 +1,271 @@
|
||||
# FlatRender — Curated Asset Library Catalog
|
||||
|
||||
> Generated by the `flatrender-asset-sweep` workflow (91 sources surveyed → 62 usable
|
||||
> after adversarial license/Iran-access verification) + a completeness-critic pass.
|
||||
> **Read §12 (Reality Check) before treating any count as "done".** Nothing here is
|
||||
> vendored yet — this is an *acquisition + build plan*, not a shipped library.
|
||||
|
||||
**Reference look:** Google "Alegria" / Pablo-Stanley flat editorial illustration — bold flat colour-blocking (2–3 shades per shape), confident hand-drawn line, expressive hands & foreshortening, characters set in **rich scenes** (rooms, furniture, devices, sky), subtle grain.
|
||||
|
||||
**Render stack (verified in repo):** Remotion `4.0.290` + `@remotion/three` `4.0.290` (installed). **`@remotion/lottie` is NOT yet a dependency** in `services/remotion/package.json` — it must be added (MIT, Nexus-mirrorable) before any Lottie path works.
|
||||
|
||||
**Stack rule (standing):** every template animation is built on **Remotion + Three.js together** (`@remotion/three`). Flat-illustration art is composited as **2.5D** — 2D layers placed on planes inside a Three.js scene for parallax camera, depth, lighting and 3D particles. Animate only off `useCurrentFrame()`.
|
||||
|
||||
**Vendoring target (verified):** `services/remotion/public/` exists and currently holds only `fonts/` (Vazirmatn 400–900 woff2). The project already serves vendored files via `staticFile()` (see `src/lib/fonts.ts` and `AppShowcase3D.tsx`). All asset categories below land under `public/illustrations/...` and `public/lottie/...`.
|
||||
|
||||
**The "naked scene" problem (verified):** `src/compositions/CharacterStory.tsx` draws a single hand-coded SVG figure standing on an abstract blurred blob inside a gradient — no room, no furniture, no real sky, no props. The catalog and integration plan below exist specifically to fix this with a layered, asset-driven scene system.
|
||||
|
||||
---
|
||||
|
||||
## 0. Totals (claimed — see §12 for the honest correction)
|
||||
|
||||
| Bucket | Claimed usable count |
|
||||
|---|---|
|
||||
| **Characters — riggable (separable parts)** | ~110 base components / poses (Humaaans ~100 + Open Peeps part-set) |
|
||||
| Characters — Lottie/animated (self-authored + curated CC0) | ~50–80 loops (mostly self-authored) |
|
||||
| Scenes & interiors (recolorable, vendor curated subset) | ~300+ curated (from unDraw/ManyPixels/Lukasz pools of 4,000+) |
|
||||
| Devices / props | ~150 |
|
||||
| Sky / nature / abstract | ~80 |
|
||||
| Grain / texture | ~10 |
|
||||
| Persian / seasonal | ~40 (self-authored) |
|
||||
|
||||
> ⚠️ The critic's verdict: this "≥100 characters" is **permutation-inflated**. The defensible
|
||||
> count of distinct, named, ledgered figures from the firewall-clean CC0/MIT tier is **~50–60**,
|
||||
> and **0 are riggable today** (all need manual `<g>`-splitting). §12 gives a concrete plan to a
|
||||
> real, enumerated 100-figure roster.
|
||||
|
||||
---
|
||||
|
||||
## 1. Characters — Riggable (separable SVG parts) ⭐ core tier
|
||||
|
||||
Individual `<g>` body parts can be driven by `useCurrentFrame()` / `interpolate()` — true per-limb rigging, not just whole-figure parallax.
|
||||
|
||||
### 1.1 Humaaans (Pablo Stanley) — FLAGSHIP
|
||||
- **License:** CC0 1.0 Public Domain (commercial OK, no attribution, redistribution/vendoring OK).
|
||||
- **Iran-access:** acquisition **yes** (humaaans.com / Figma Community / archive.org). **Do NOT use Gumroad.** Render-time is CDN-free once vendored.
|
||||
- **Animation-fit:** riggable-parts — **realistically 7–8/10**. Parts are separable as *components in the Figma/Sketch source*; a flat one-shot SVG export flattens groups, so you must export each body part as its own `<g>` first.
|
||||
- **Count:** ~100 base components (≈12 base poses + dozens of heads/hair/tops/bottoms/shoes + objects).
|
||||
- **Style-match:** **9/10** — THE flagship Alegria reference.
|
||||
- **Download:** Figma Community file `1200350623263197299` → export per-part SVGs; or humaaans.com; `archive.org/details/humaaans` fallback.
|
||||
- **Use-cases:** full-body hero rigging; per-limb wave/present/think/celebrate poses (replaces the hand-coded `Pose` system in `CharacterStory.tsx`).
|
||||
|
||||
### 1.2 Open Peeps (Pablo Stanley) — secondary
|
||||
- **License:** CC0 1.0 (no attribution, redistribution OK).
|
||||
- **Iran-access:** acquisition yes. **Animation-fit:** riggable-parts — `github.com/opeepsfun/open-peeps` exposes separated body/head/face/beard/accessory SVGs (npm wrapper is MIT; **vendor the raw CC0 SVGs, not the wrapper**).
|
||||
- **Count:** ~200 building-block parts. **Style-match 7/10** (confident hand-drawn line; lighter colour-blocking). Character-only — pair with §3 scenes.
|
||||
- ⚠️ **Do NOT confuse with Avataaars** (same artist, NOT CC0).
|
||||
|
||||
### 1.3 DiceBear (programmatic, offline) — build-time avatars
|
||||
- **License:** core MIT; per-style — `open-peeps`=CC0, `avataaars`=free-commercial custom, `big-smile`/`adventurer`/`croodles`=**CC BY 4.0 (attribution REQUIRED)**.
|
||||
- **Iran-access:** **yes** — `@dicebear/core` + `@dicebear/collection` run **fully offline via npm** (Nexus mirror). `createAvatar(style,{seed}).toString()` → raw SVG, no runtime CDN. Do NOT call the dicebear HTTP API at render.
|
||||
- **Animation-fit:** component-swap + transforms (blink/expression micro-rigs), not full skeletal rig. Bust→half-body scale.
|
||||
- **Count:** ~45 styles. **Style-match 6/10.** Use `idRandomization` to avoid SVG id collisions.
|
||||
|
||||
### 1.4 IRA Design (Creative Tim) — selective gradient style
|
||||
- **License:** **MIT** (`ira-design/ira-illustrations`). **Retain LICENSE.md** alongside vendored SVGs (no on-screen credit needed).
|
||||
- **Iran-access:** yes (`git clone`). **Animation-fit:** moderate — monolithic per-illustration files, manual `<g>` split needed; gradient fills complicate flat parallax.
|
||||
- **Count:** ~100 vendorable SVGs (36 characters + 52 objects + backgrounds). **Style-match 6/10** (gradient sketch, not strict flat-block).
|
||||
|
||||
### 1.5 Avataaars (Pablo Stanley) — ⚠️ caution
|
||||
- **License:** code ports MIT, but **artwork is custom "free for personal & commercial use", NOT MIT/CC0** — no redistribution "in a pack", no "use to create a competing service" (a live risk for an avatar SaaS).
|
||||
- **Verdict:** talking-head micro-animation **only** (via DiceBear `avataaars` offline npm); document as "permissive-with-restrictions"; do NOT build a user-facing avatar generator on it.
|
||||
|
||||
---
|
||||
|
||||
## 2. Characters — Lottie / Animated
|
||||
|
||||
> **Strategic note:** every third-party Lottie library carries a redistribution and/or
|
||||
> competing-service clause that collides with a paid template SaaS vendoring assets into
|
||||
> `public/`. **Primary path = SELF-AUTHOR brand Lottie loops** from the CC0 SVGs in §1/§3
|
||||
> and drive them with `@remotion/lottie`.
|
||||
|
||||
- **2.1 LottieFiles (free/community)** — ⚠️ Simple License (commercial OK) but **no "compile files to develop a competing service"**, no standalone JSON redistribution; per-file Free/Premium badge. Iran-access unknown (login-gated). Use only inside a final render, Free badge re-verified.
|
||||
- **2.2 Lottielab** — ⚠️ free tier **watermarks all exports**; value is as an **authoring tool** on cleanly-licensed SVGs (Pro ~$12/mo for watermark-free).
|
||||
- **2.3 LottieFiles creators/marketplace** — ⚠️ per-item; only **Free**-badged vendorable; Premium forbids redistribution even after purchase. Style-match up to 8/10 for the right creator.
|
||||
|
||||
---
|
||||
|
||||
## 3. Scenes & Interiors (recolorable flat backdrops — fixes the "naked scene")
|
||||
|
||||
> **The category that directly cures `CharacterStory.tsx`** — flat scene SVGs (rooms, desks, cities, devices, sky) used as BACKGROUND/MID-GROUND layers behind the riggable §1 characters; animation is whole-scene parallax/recolor.
|
||||
|
||||
- **3.1 unDraw** — ⚠️ **NOT MIT** (stale label) → custom proprietary (free commercial, no attribution) that **forbids replicating a competing service, distributing "in packs", scraping, AND AI/ML training**. ~1,300 scenes. **Style-match 2–3/10.** Hand-pick only (no bulk scrape), bake into renders, log `license="unDraw custom (proprietary)"`.
|
||||
- **3.2 ManyPixels** — ⚠️ custom permissive but forbids "distribute in packs", being the product's center, AND AI-training. 2,500+. Iran-access yes (Iconduck/`quentincaffeino/manypixels-illustrations` mirror). **Style-match 4/10.** Curated subset baked in; never an in-product picker.
|
||||
- **3.3 Lukasz Adam** — ⚠️ **CC0/MIT** (cleanest scene tier) but **acquisition NO via official Gumroad** (sanctioned) → Eagle/aggregator mirror or non-Iran box. **229 confirmed** (characters, remote-work, cities, devices). The free-static scene anchor.
|
||||
- **3.4 Storyset (Freepik)** — ⚠️ **reference only** — resale/database clause + visible Freepik credit; Iran-access **NO** (OFAC checkout). Only attractive property: exports Lottie JSON.
|
||||
- **3.5 DrawKit** — ⚠️ freemium proprietary, forbids standalone redistribution + AI-training, revocable terms. Use only if repo private + users get rendered output only.
|
||||
- **3.6 Black Illustrations** — ⚠️ proprietary; forbids serving raw SVG / end-user extraction → **bake into MP4 only**. ~120 free. Valuable inclusive-character supplement.
|
||||
- **3.7 Ouch! by Icons8** — ⚠️ **reference only** — forbids distributing as "stand-alone files" (conflicts with `public/`+`staticFile()`); Iran-access NO.
|
||||
|
||||
---
|
||||
|
||||
## 4. Devices / Props
|
||||
- **Humaaans objects** (CC0) — laptops/phones/plants/chairs/signs, separable mid-ground props.
|
||||
- **IRA Design objects** (MIT) — 52 objects; split manually.
|
||||
- **Lukasz Adam "Devices"** (CC0) — phones/laptops/monitors; pairs with the `AppShowcase3D.tsx` `screenUrl` + `staticFile()` pattern.
|
||||
- **Self-authored SVG props** — drawn inline in the same flat style (the repo already proves this works).
|
||||
|
||||
## 5. Sky / Nature / Abstract
|
||||
- **Self-authored gradients & shapes** (CSS/SVG, already used in `CharacterStory.tsx`) — cleanest license-free sky/abstract layer; drift off `useCurrentFrame()`.
|
||||
- **unDraw/ManyPixels nature** (curated, recolored).
|
||||
- **Three.js abstract** via `@remotion/three` (installed) for parallax sky/particles depth.
|
||||
|
||||
## 6. Grain / Texture
|
||||
- **Inline `feTurbulence` SVG noise** — ALREADY in `CharacterStory.tsx` (`mixBlendMode: overlay`, opacity 0.05). Keep as the standard grain.
|
||||
- **CC0 paper/noise tiles** — vendor 5–10 (ambientCG / cc0textures, CC0).
|
||||
|
||||
## 7. Persian / Seasonal
|
||||
- **Self-authored Nowruz (haft-sin, sabzeh, goldfish, sonbol), Yalda (pomegranate, watermelon, Hafez), Ramadan (crescent, fanoos)** flat SVG motifs — the repo already ships `Nowruz3D.tsx` / `NowruzGreeting.tsx`.
|
||||
- **Recolored CC0 scenes** (Humaaans + Lukasz) dressed with seasonal props. Vazirmatn RTL already vendored.
|
||||
|
||||
---
|
||||
|
||||
## 8. DOWNLOAD MANIFEST
|
||||
|
||||
All assets land under `services/remotion/public/`. npm via the **Nexus mirror** (`mirror.soroushasadi.com`). For Gumroad/Freepik/Icons8/Cloudflare-gated sources, acquire from a **non-Iran box / VPN once**, then commit — render-time is CDN-free.
|
||||
|
||||
```bash
|
||||
# 0. Folders
|
||||
mkdir -p services/remotion/public/illustrations/{humaaans,openpeeps,undraw,manypixels,lukaszadam,ira,notion}
|
||||
mkdir -p services/remotion/public/lottie
|
||||
|
||||
# 1. Humaaans (CC0) — FLAGSHIP. Figma community 1200350623263197299 → export each
|
||||
# body-part as its own <g> SVG → public/illustrations/humaaans/ (NOT Gumroad)
|
||||
|
||||
# 2. Open Peeps (CC0) — pre-separated parts:
|
||||
git clone https://github.com/opeepsfun/open-peeps # vendor raw CC0 SVGs, not the wrapper
|
||||
|
||||
# 3. DiceBear (offline, no runtime CDN) — generate at BUILD time:
|
||||
npm i @dicebear/core @dicebear/collection # via Nexus mirror
|
||||
# createAvatar(openPeeps,{seed}).toString() → write SVG to public/
|
||||
|
||||
# 4. IRA Design (MIT) — keep LICENSE.md alongside:
|
||||
git clone https://github.com/ira-design/ira-illustrations
|
||||
|
||||
# 5. Lukasz Adam (CC0, 229) — Eagle/aggregator mirror or non-Iran box (Gumroad sanctioned)
|
||||
|
||||
# 6. unDraw / ManyPixels — HAND-PICK only (no bulk scrape); curated subset
|
||||
|
||||
# 7. Notion Avatars (CC0) — talking-head busts:
|
||||
git clone https://github.com/notion-avatar/notion-avatar
|
||||
|
||||
# 8. Lottie pipeline (must add the package first):
|
||||
npm i @remotion/lottie # via Nexus — currently MISSING
|
||||
```
|
||||
|
||||
**Iran-mirror flags:** Gumroad (Lukasz/Open Peeps/Black Illustrations) = sanctioned. Freepik/Storyset + Icons8 = OFAC-blocked. Cloudflare (DrawKit/ManyPixels) = intermittent. All npm = Nexus mirror.
|
||||
|
||||
---
|
||||
|
||||
## 9. INTEGRATION PLAN
|
||||
|
||||
### 9.1 License firewall — `public/illustrations/assets.json`
|
||||
Every vendored file gets one ledger row. **No row → asset may not ship.**
|
||||
```jsonc
|
||||
{
|
||||
"humaaans/torso-a.svg": { "source": "Humaaans", "license": "CC0-1.0",
|
||||
"license_class": "CC0", "commercial_ok": true, "attribution_required": false,
|
||||
"ai_training_allowed": true, "url": "humaaans.com", "vendored": "2026-06-22" },
|
||||
"ira/scene-desk.svg": { "source": "IRA Design", "license": "MIT",
|
||||
"attribution_required": true, "notice_file": "ira/LICENSE.md", "ai_training_allowed": true },
|
||||
"undraw/working.svg": { "source": "unDraw", "license": "unDraw custom (proprietary)",
|
||||
"commercial_ok": true, "attribution_required": false,
|
||||
"ai_training_allowed": false, "redistribute_as_pack": false }
|
||||
}
|
||||
```
|
||||
Hard rules: **(1)** only CC0/MIT/PD vendored as raw `public/` SVG; **(2)** custom-restrictive (unDraw/ManyPixels/DrawKit/Black Illustrations) only as a **curated subset baked into renders**, `ai_training_allowed:false` (excluded from FlatRender's future AI-video pipeline); **(3)** Blush/Storyset/Icons8/Avataaars-pack = **never vendored**, reference only.
|
||||
|
||||
### 9.2 Rigging an SVG kit in Remotion (`useCurrentFrame()`-driven `<g>` parts)
|
||||
The repo already proves the pattern in `CharacterStory.tsx` (`arm(ang,sign)` / `leg(sign,ang)` rotate `<g>` groups by frame-derived angles). Replace the hand-drawn paths with vendored Humaaans part SVGs, keep the rig math:
|
||||
```tsx
|
||||
const f = useCurrentFrame();
|
||||
const wave = pose === "wave" ? 130 + Math.sin(f / 4) * 14 : 12;
|
||||
<g transform={`translate(${shoulderX} ${shoulderY}) rotate(${wave})`}>
|
||||
<UpperArm /> {/* vendored SVG <g>, pivot at shoulder */}
|
||||
<g transform={`translate(0 ${forearmY}) rotate(${elbow})`}><Forearm /></g>
|
||||
</g>
|
||||
```
|
||||
Keep conventions: `staticFile()` for raster, stable `rand(seed)` (not `Math.random`), per-instance `id()` prefixes (`cs${idn}_`) to avoid `<defs>` id collisions, `L.vmin()/L.pick()` for aspect re-flow.
|
||||
|
||||
### 9.3 `@remotion/lottie` (after `npm i @remotion/lottie`)
|
||||
Vendor JSON under `public/lottie/`; never a CDN/HTTP API at render. Use for self-authored idle/confetti/sky loops; firewall third-party Premium JSON out.
|
||||
|
||||
### 9.4 LAYER scenes for depth — the cure for "naked scene" (do this in the Three.js 2.5D scene)
|
||||
Stack layers back-to-front, each on its own plane / parallax speed off `useCurrentFrame()`:
|
||||
```
|
||||
Layer 0 SKY gradient / Three.js abstract (slow drift, far plane)
|
||||
Layer 1 ROOM vendored interior SVG (wall, window) (slow)
|
||||
Layer 2 FURNITURE desk / shelf / plant props (medium)
|
||||
Layer 3 DEVICE laptop/phone (staticFile, AppShowcase pattern)
|
||||
Layer 4 CHARACTER riggable Humaaans <g> rig (foreground, full motion)
|
||||
Layer 5 GRAIN feTurbulence overlay (already in repo, opacity 0.05) + vignette
|
||||
```
|
||||
Parallax = depth factor (`0.1 … 1.0`) on each layer's translate / z-position. Direct upgrade of `CharacterStory.tsx`: "blob + particles + character" → "sky → room → furniture → device → character → grain".
|
||||
|
||||
### 9.5 Recolor to brand palette
|
||||
Map `colorSchema` (`accentColor`/`secondaryColor`/`backgroundColor`/`textColor`) onto each scene SVG's fills. unDraw exposes one accent var; multi-shade SVGs (Lukasz/ManyPixels/Humaaans) need a small fill-remap at vendor time (`mixHex()` from `src/lib/anim.ts`).
|
||||
|
||||
---
|
||||
|
||||
## 10. PHASED BUILD PLAN (to Alegria quality)
|
||||
|
||||
- **Phase 0 — Plumbing (½ day).** `public/illustrations/*` + `public/lottie/`; `assets.json` ledger + a CI check that fails on un-ledgered files; `npm i @remotion/lottie`.
|
||||
- **Phase 1 — Flagship character rig (2–3 days).** Vendor Humaaans parts; build `<RiggedCharacter>` (separable `<g>` arms/legs/head, pose presets) reusing the `CharacterStory.tsx` pose math.
|
||||
- **Phase 2 — Layered scene system (2–3 days).** `<SceneStage>` composing sky→room→furniture→device→grain with parallax inside the Three.js scene. Vendor a curated ~30-scene set (Lukasz CC0 first, then hand-picked unDraw/ManyPixels). Rebuild `CharacterStory.tsx`'s 13 beats with real environments.
|
||||
- **Phase 3 — Recolor + brand binding (1–2 days).** Wire `colorSchema` → scene fills; verify studio colour controls recolor the whole stack.
|
||||
- **Phase 4 — Lottie & motion polish (2 days).** Self-author 8–10 idle/wave/confetti/sky loops; integrate via `@remotion/lottie`; per-limb secondary motion + foreshortening on the hero (expressive hands).
|
||||
- **Phase 5 — Persian/seasonal pack (1–2 days).** Nowruz/Yalda/Ramadan prop sets on the layered scenes (reuse `Nowruz3D`).
|
||||
- **Phase 6 — QA & firewall audit (1 day).** Render 3 aspects; confirm determinism, no runtime CDN, full `assets.json` coverage, AI-prohibited assets flagged out.
|
||||
|
||||
---
|
||||
|
||||
## 11. Verdict summary
|
||||
|
||||
| Source | Verdict | Vendor raw? | License | Iran (acquire) | Anim-fit | Style |
|
||||
|---|---|---|---|---|---|---|
|
||||
| Humaaans | **USE** ⭐ | ✅ | CC0 | yes | rig 7–8 | 9 |
|
||||
| Open Peeps | **USE** | ✅ | CC0 | yes | rig | 7 |
|
||||
| DiceBear (CC0/free) | **USE** | ✅ gen→commit | MIT+CC0 | yes (offline npm) | swap/transform | 6 |
|
||||
| IRA Design | **USE** (selective) | ✅ +LICENSE.md | MIT | yes | moderate | 6 |
|
||||
| Lukasz Adam | **USE** (mirror) | ✅ | CC0 | acquire NO (Gumroad) | single-svg | 4 |
|
||||
| Notion Avatars | **USE** (add) | ✅ | CC0 | yes | bust micro-rig | 6 |
|
||||
| unDraw | caution | curated/baked | custom-restrictive | unknown | single-svg | 2–3 |
|
||||
| ManyPixels | caution | curated/baked | custom-permissive | yes | single-svg | 4 |
|
||||
| Black Illustrations | caution | bake-into-MP4 | proprietary | unknown | single-svg | 4 |
|
||||
| Avataaars (art) | caution | gen→commit, no pack | custom-permissive | yes | bust micro-rig | 6 |
|
||||
| LottieFiles (free) | caution | inside-render only | Simple License | unknown | lottie | 5–6 |
|
||||
| DrawKit | caution | private repo only | freemium-proprietary | unknown | lottie | 4 |
|
||||
| Storyset | **reference only** | ❌ | resale-ban | NO | lottie | 5 |
|
||||
| Ouch!/Icons8 | **reference only** | ❌ | no stand-alone files | NO | lottie | 5 |
|
||||
| Blush | **reference only** | ❌ | proprietary | NO (Stripe) | rig (paid) | 9 |
|
||||
|
||||
**Bottom line:** Build the production library on the clean, vendorable CC0/MIT tier — **Humaaans, Open Peeps, DiceBear-CC0, IRA, Notion Avatars** + **Lukasz Adam** scenes; supplement scenery with **curated, baked-in** unDraw/ManyPixels; **self-author** Lottie loops; keep the encumbered/Iran-blocked sources (Blush/Storyset/Icons8/DrawKit) as **design-time reference only**.
|
||||
|
||||
---
|
||||
|
||||
## 12. ⚠️ Reality Check (completeness critic) — READ THIS
|
||||
|
||||
The "≥100 characters" in §0 does **not** survive scrutiny. Honest status and the fix:
|
||||
|
||||
**Gaps:**
|
||||
1. **Count is permutation-inflated.** "Humaaans ~100 components" = interchangeable heads/hair/tops/bottoms, not 100 figures. Defensible distinct, named, firewall-clean figures ≈ **12 Humaaans poses + 36 IRA + a few DiceBear seeds ≈ 50–60** — and those need manual `<g>`-splitting before riggable.
|
||||
2. **Nothing is vendored yet.** `public/` contains only `fonts/`. `public/illustrations/` + `public/lottie/` don't exist. The catalog is an **acquisition plan**, not a library. **Riggable-today count = 0.**
|
||||
3. **Riggability overstated.** A one-shot Humaaans SVG export flattens groups → until per-part `<g>` export + pivot authoring is done, it's single-figure parallax (same tier as unDraw).
|
||||
4. **Diversity thin & encumbered.** The only dedicated inclusive source (Black Illustrations) is bake-into-MP4-only. No source covers older adults, disability, hijab/chador, or Persian dress beyond self-authored props.
|
||||
5. **`@remotion/lottie` is a hard blocker** (absent from `package.json`) — every Lottie path (§2) is non-functional until added; don't count those ~50–80 loops yet.
|
||||
6. **Self-authored assets counted as if they exist** (Lottie ~50–80, seasonal ~40, sky ~80, props ~150 are future work).
|
||||
|
||||
**Additions / the concrete fix — enumerate a real 100-figure roster (each an actual committed file + `assets.json` row):**
|
||||
- **~30** Humaaans base poses × authored top/bottom/skin variants you actually create & ledger.
|
||||
- **36** IRA Design character SVGs (MIT, `github.com/ira-design/ira-illustrations`).
|
||||
- **30** DiceBear `open-peeps` (CC0) fixed seeds, generated + committed.
|
||||
- **~10** Open Peeps part assemblies. → **~106 real, named, ledgered figures.**
|
||||
- **+ Notion Avatars** (CC0, `github.com/notion-avatar/notion-avatar`) — ~10–15 talking-head busts, firewall-clean, Iran-accessible. Fills the talking-head gap without Avataaars' restrictions.
|
||||
- **+ Croodles / Adventurer** (DiceBear, **CC BY 4.0 — attribution ledger row**) — ~20 doodle-line seeds.
|
||||
- **+ OpenMoji** people/gestures (CC BY-SA 4.0, `github.com/hfg-gmuend/openmoji`) — expressive hands/heads for secondary characters; curated subset + share-alike tracking.
|
||||
- **Diversity pass:** author hijab/scarf head `<g>` overlays, older-adult variants, varied skin tones via `mixHex()` recolor on the **CC0 Humaaans base** (firewall-clean derivative; directly serves the Persian-first product).
|
||||
- **Grain:** vendor 3–5 CC0 paper/noise tiles from **ambientCG** (CC0, GitHub/CDN-mirrorable).
|
||||
- **`@remotion/lottie`** added in Phase 0 *before* any Lottie asset counts as usable.
|
||||
- **Sky:** add Lukasz Adam CC0 nature SVGs + 2–3 self-authored gradient-sky presets bound to `colorSchema`.
|
||||
|
||||
**So the true near-term deliverable** is not "100 characters downloaded" but: Phase 0 plumbing + a vendored, ledgered **~30–40 character starter set** (Humaaans + IRA + DiceBear + Notion) split into riggable `<g>` parts, plus a `<SceneStage>` layered-scene system — enough to rebuild `CharacterStory` to the Alegria bar — then grow the roster to 100+ on that proven pipeline.
|
||||
@@ -12,6 +12,7 @@
|
||||
"@react-three/fiber": "^9.1.2",
|
||||
"@react-three/postprocessing": "^3.0.4",
|
||||
"@remotion/cli": "4.0.290",
|
||||
"@remotion/lottie": "^4.0.290",
|
||||
"@remotion/three": "^4.0.290",
|
||||
"@remotion/zod-types": "4.0.290",
|
||||
"@types/three": "^0.171.0",
|
||||
@@ -23,6 +24,8 @@
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dicebear/collection": "^9.4.2",
|
||||
"@dicebear/core": "^9.4.2",
|
||||
"@types/react": "19.0.0",
|
||||
"typescript": "5.5.4"
|
||||
}
|
||||
@@ -48,6 +51,468 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/adventurer": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/adventurer/-/adventurer-9.4.2.tgz",
|
||||
"integrity": "sha512-jqYp834ZmGDA9HBBDQAdgF1O2UTCwHF4vVrktXWa2Dppp1JczPL5HnVOWsjtrLmXNn61Wd6OLmBb2e6rhzp3ig==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/adventurer-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/adventurer-neutral/-/adventurer-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-5xgkG/mNL4j3Q4SJGQLBU/KnU90tng8Ze5ofThD+55wi0oeY/nSAUowg6UFCmHrktjifj/MEx3CQqbpcPWtfIA==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/avataaars": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/avataaars/-/avataaars-9.4.2.tgz",
|
||||
"integrity": "sha512-3x9jKFkOkFSPmpTbt9xvhiU2E1GX7beCSsX0tXRUShj8x6+5Ks9yBRT1VlkySbnXrZ/GglADGg7vJ/D2uIx1Yw==",
|
||||
"dev": true,
|
||||
"license": "See LICENSE file",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/avataaars-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/avataaars-neutral/-/avataaars-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-/eNrp0YCNJRwQXqOloLm1+3Ss2C+pMpUQIGkbEnGsP1UK+13Ge80ggDDof1HpdqvG9HAZcKa7hnbG/0HSwyDSw==",
|
||||
"dev": true,
|
||||
"license": "See LICENSE file",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/big-ears": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/big-ears/-/big-ears-9.4.2.tgz",
|
||||
"integrity": "sha512-mNfz3ppNA7UBq0IO3nXCiV5pFPG7c1DfzRB0foNU2Wo1XXT8FIcSY2BvDlYqorZTOUOz7dHb0vx06hqvG0HP5w==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/big-ears-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/big-ears-neutral/-/big-ears-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-M8Ozmzza4eY4hpLOYULgJxMYmBA0CsBnrE15/xw6LZkEREXnrX5z0NJsf8hUfdyF6BWZ+RBgzoiav32DAC5zcg==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/big-smile": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/big-smile/-/big-smile-9.4.2.tgz",
|
||||
"integrity": "sha512-hmT5i7rcPPhStjZyg28pbIhdTnnMBzK3RObI0vKCpY30EFrzaPkkdDL6Ck5fAFBdvDIW1EpOJkenyR0XPmhgbQ==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/bottts": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/bottts/-/bottts-9.4.2.tgz",
|
||||
"integrity": "sha512-tsx+dII7EFUCVA8URj66G1GqORCCVduCAx4dY2prEY2IeFianVpkntXuFsWZ9BBGx1NZFndvDith5oTwKMQPbQ==",
|
||||
"dev": true,
|
||||
"license": "See LICENSE file",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/bottts-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/bottts-neutral/-/bottts-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-kFNwWt6j+gzZ5n5Pz7WVwePubREAQOF8ZwWA9ztwVYDVMLnOChWbAofy5FED4j5md2MXFH2EgLCFCMr5K2BmIA==",
|
||||
"dev": true,
|
||||
"license": "See LICENSE file",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/collection": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/collection/-/collection-9.4.2.tgz",
|
||||
"integrity": "sha512-KArubv7if8H7j9sIfpDK2hJJqrdNVR5zMPAMOSpIU2JPyXx8TC9o5wsmXb8il5wOHgaS9Q/cla7jUNIiDD7Gsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@dicebear/adventurer": "9.4.2",
|
||||
"@dicebear/adventurer-neutral": "9.4.2",
|
||||
"@dicebear/avataaars": "9.4.2",
|
||||
"@dicebear/avataaars-neutral": "9.4.2",
|
||||
"@dicebear/big-ears": "9.4.2",
|
||||
"@dicebear/big-ears-neutral": "9.4.2",
|
||||
"@dicebear/big-smile": "9.4.2",
|
||||
"@dicebear/bottts": "9.4.2",
|
||||
"@dicebear/bottts-neutral": "9.4.2",
|
||||
"@dicebear/croodles": "9.4.2",
|
||||
"@dicebear/croodles-neutral": "9.4.2",
|
||||
"@dicebear/dylan": "9.4.2",
|
||||
"@dicebear/fun-emoji": "9.4.2",
|
||||
"@dicebear/glass": "9.4.2",
|
||||
"@dicebear/icons": "9.4.2",
|
||||
"@dicebear/identicon": "9.4.2",
|
||||
"@dicebear/initials": "9.4.2",
|
||||
"@dicebear/lorelei": "9.4.2",
|
||||
"@dicebear/lorelei-neutral": "9.4.2",
|
||||
"@dicebear/micah": "9.4.2",
|
||||
"@dicebear/miniavs": "9.4.2",
|
||||
"@dicebear/notionists": "9.4.2",
|
||||
"@dicebear/notionists-neutral": "9.4.2",
|
||||
"@dicebear/open-peeps": "9.4.2",
|
||||
"@dicebear/personas": "9.4.2",
|
||||
"@dicebear/pixel-art": "9.4.2",
|
||||
"@dicebear/pixel-art-neutral": "9.4.2",
|
||||
"@dicebear/rings": "9.4.2",
|
||||
"@dicebear/shapes": "9.4.2",
|
||||
"@dicebear/thumbs": "9.4.2",
|
||||
"@dicebear/toon-head": "9.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/core": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/core/-/core-9.4.2.tgz",
|
||||
"integrity": "sha512-MF0042+Z3s8PGZKZLySfhft28bUa3B1iq0e5NSjCvY8gfMi5aIH/iRJGRJa1N9Jz1BNkxYb4yvJ/N9KO8Z6Y+w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/croodles": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/croodles/-/croodles-9.4.2.tgz",
|
||||
"integrity": "sha512-6VoO0JviIf7dKKMBTL/SMXxWhnXHaZuzufX90G0nXxS77ELG1YkGNMaZzawizN4C09Gbya2gJkozqrWiJN/aGw==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/croodles-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/croodles-neutral/-/croodles-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-oG5IeUdtiYshQ89gkAVcl5w3xAEi5UZX2fTzIyelpBPCG176l7VuuFzlxi2umnB3E6LVHYy06DXvUo/p+rXB2Q==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/dylan": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/dylan/-/dylan-9.4.2.tgz",
|
||||
"integrity": "sha512-1vQvRu9x9DrwFxhFaIU2rf0EUL04yDTbAt7fHyAjM0mEsKzTD4mRNf95tCRuavCoW6W48u7A/OY6jyIub6kxLQ==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/fun-emoji": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/fun-emoji/-/fun-emoji-9.4.2.tgz",
|
||||
"integrity": "sha512-kqB6LPkdYCdEU/mwbyz34xLzoNUKL6ARcoo3fr5ASq9D6ZE07qIKybC3xv5+CPz7VmspJ1Q3c/VVWVMDRP7Twg==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/glass": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/glass/-/glass-9.4.2.tgz",
|
||||
"integrity": "sha512-z5qUogHQ1b6UJ2zCqT848mU2U9DKbVDhiX6GPDjD7tYLisCCJVisH9p6WyNdHvflUd4SHkA6gRqVJIh2v2HnTA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/icons": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/icons/-/icons-9.4.2.tgz",
|
||||
"integrity": "sha512-QSMMz0NA03ypSGhXC8HQX8FSj8lYT+/5yqH+/N03OH2IjL0q7wwGZ7nqsrtlRp76O5WqMTwGfSbTUUYPjFr+Xw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/identicon": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/identicon/-/identicon-9.4.2.tgz",
|
||||
"integrity": "sha512-JVDSmZsv11mSWqwAktK5x9Bslht2xY3TFUn8xzu6slAYe1Z7hEXZ76eb+UJ6F4qEzdwZ7xPWzAS6Nb0Y3A0pww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/initials": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/initials/-/initials-9.4.2.tgz",
|
||||
"integrity": "sha512-yePuIUasmwtl9IrtB6rEzE/zb5fImKP/neW0CdcTC2MwLgMuP1GLHEGRgg1zI8exIh+PMv1YdLGyyUuRTE2Qpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/lorelei": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/lorelei/-/lorelei-9.4.2.tgz",
|
||||
"integrity": "sha512-YMv6vnriW6VLFDsreKuOnUFFno6SRe7+7X7R7zPY0rZ+MaHX9V3jcioIG+1PSjIHEDfOLUHpr5vd1JBWv8y7UA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/lorelei-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/lorelei-neutral/-/lorelei-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-yspanTthA5vh6iCdeLzn6xZ4yYMYRcfcxblcgSvHTF1ut0bjAXtw5SXzZ6aJTrJWiHkzYOQuTOR6GVYiW80Q7w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/micah": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/micah/-/micah-9.4.2.tgz",
|
||||
"integrity": "sha512-e4D3W/OlChSsLo7Llwsy0J18vk0azJqF/uFoY+EKACCNHBc1HGNsqVvu2CTf+OWOA8wTyAK6UkjBN5p01r7D+g==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/miniavs": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/miniavs/-/miniavs-9.4.2.tgz",
|
||||
"integrity": "sha512-wLwyFNNUnDRd3BbhSBhXR0XEpX8sG0/xDA5M/OkDoapLqZnnI48YLUSDd2N5QTAVMmcSEuZOYxkcnj7WW79vlg==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/notionists": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/notionists/-/notionists-9.4.2.tgz",
|
||||
"integrity": "sha512-ZCySq+nxcD/x4xyYgytcj2N9uY3gxrL+qpnmOdp2BdA221KacVrxlsUPpIgEMqxS2rMmBQXfxg129Pzn4ycIpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/notionists-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/notionists-neutral/-/notionists-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-AyD9kEfVxQUwDGf4Op059gVmYIOAkTKg3dtE9h9mEKP7zl/kMy5B67BFFOo7sB0mXCjzAegZ6ekGU02E8+hIHw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/open-peeps": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/open-peeps/-/open-peeps-9.4.2.tgz",
|
||||
"integrity": "sha512-i01tLgtp2g937T81sVeAOVlqsCtiTck/Kw20g7hN80+7xrXjOUepz2HPLy3HeiMjwjMGRy5o54kSd0/8Ht4Dqg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/personas": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/personas/-/personas-9.4.2.tgz",
|
||||
"integrity": "sha512-NJlkvI5F5gugt6t2+7QrYNTwQC7+4IQZS3vG0dYk2BncxOHax0BuLovdSdiAesTL4ZkytFYIydWmKmV2/xcUwg==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/pixel-art": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/pixel-art/-/pixel-art-9.4.2.tgz",
|
||||
"integrity": "sha512-peHf7oKICDgBZ8dUyj+txPnS7VZEWgvKE+xW4mNQqBt6dYZIjmva2shOVHn0b1JU+FDxMx3uIkWVixKdUq4WGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/pixel-art-neutral": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/pixel-art-neutral/-/pixel-art-neutral-9.4.2.tgz",
|
||||
"integrity": "sha512-9e9Lz554uQvWaXV2P17ss+hPa6rTyuAKBtB8zk8ECjHiZzIl61N/KcTVLZ4dILVZwj7gYriaLo16QEqvL2GJCg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/rings": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/rings/-/rings-9.4.2.tgz",
|
||||
"integrity": "sha512-Pc3ymWrRDQPJFNrbbLt7RJrzGvUuuxUiDkrfLhoVE+B6mZWEL1PC78DPbS1yUWYLErJOpJuM2GSwXmTbVjWf+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/shapes": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/shapes/-/shapes-9.4.2.tgz",
|
||||
"integrity": "sha512-AFL6jAaiLztvcqyq+ds+lWZu6Vbp3PlGWhJeJRm842jxtiluJpl6r4f6nUXP2fdMz7MNpDzXfLooQK9E04NbUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/thumbs": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/thumbs/-/thumbs-9.4.2.tgz",
|
||||
"integrity": "sha512-ccWvDBqbkWS5uzHbsg5L6uML6vBfX7jT3J3jHCQksvz8haHItxTK02w+6e1UavZUsvza4lG5X/XY3eji3siJ4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dicebear/toon-head": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@dicebear/toon-head/-/toon-head-9.4.2.tgz",
|
||||
"integrity": "sha512-lwFeSXyAnaKnCfMt9TiJwnD1cXQUGkey/0h6i/+4TVHVMCz5/Ri5u1ynovPNHy1SnBf858QwoXHkxilGLwQX/g==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND CC-BY-4.0)",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dicebear/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz",
|
||||
@@ -760,6 +1225,20 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@remotion/lottie": {
|
||||
"version": "4.0.290",
|
||||
"resolved": "https://registry.npmjs.org/@remotion/lottie/-/lottie-4.0.290.tgz",
|
||||
"integrity": "sha512-2wwPGs/RmUynF37mdhAIIXMw++uT7FbpTXv773mOoyMQf1VUq4J9XYpcewTm9nAIKIJhCF7D3l1FoZIrwIVqeQ==",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"dependencies": {
|
||||
"remotion": "4.0.290"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"lottie-web": "^5",
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@remotion/media-parser": {
|
||||
"version": "4.0.290",
|
||||
"resolved": "https://registry.npmjs.org/@remotion/media-parser/-/media-parser-4.0.290.tgz",
|
||||
@@ -2106,6 +2585,13 @@
|
||||
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lottie-web": {
|
||||
"version": "5.13.0",
|
||||
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.13.0.tgz",
|
||||
"integrity": "sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
"dev": "remotion studio",
|
||||
"render": "remotion render",
|
||||
"still": "remotion still",
|
||||
"upgrade": "remotion upgrade"
|
||||
"upgrade": "remotion upgrade",
|
||||
"gen:dicebear": "node scripts/gen-dicebear.mjs",
|
||||
"check:assets": "node scripts/check-assets.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^10.7.7",
|
||||
"@react-three/fiber": "^9.1.2",
|
||||
"@react-three/postprocessing": "^3.0.4",
|
||||
"@remotion/cli": "4.0.290",
|
||||
"@remotion/lottie": "^4.0.290",
|
||||
"@remotion/three": "^4.0.290",
|
||||
"@remotion/zod-types": "4.0.290",
|
||||
"@types/three": "^0.171.0",
|
||||
@@ -25,6 +28,8 @@
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dicebear/collection": "^9.4.2",
|
||||
"@dicebear/core": "^9.4.2",
|
||||
"@types/react": "19.0.0",
|
||||
"typescript": "5.5.4"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
{
|
||||
"dicebear/openpeeps-01.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-1'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-02.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-2'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-03.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-3'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-04.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-4'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-05.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-5'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-06.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-6'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-07.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-7'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-08.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-8'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-09.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-9'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-10.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-10'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-11.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-11'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-12.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-12'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-13.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-13'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-14.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-14'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-15.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-15'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-16.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-16'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-17.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-17'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-18.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-18'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-19.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-19'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-20.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-20'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-21.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-21'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-22.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-22'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-23.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-23'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-24.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-24'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-25.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-25'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-26.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-26'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-27.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-27'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-28.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-28'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-29.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-29'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
},
|
||||
"dicebear/openpeeps-30.svg": {
|
||||
"source": "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
"license": "CC0-1.0",
|
||||
"license_class": "CC0",
|
||||
"commercial_ok": true,
|
||||
"attribution_required": false,
|
||||
"ai_training_allowed": true,
|
||||
"animation_fit": "swap-transform (bust/half-body micro-rig)",
|
||||
"generator": "createAvatar(openPeeps,{seed:'flatrender-peep-30'})",
|
||||
"url": "https://www.dicebear.com/styles/open-peeps/",
|
||||
"vendored": "2026-06-22"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,41 @@
|
||||
// License-firewall CI guard.
|
||||
//
|
||||
// Every vendored asset under public/illustrations/ (and public/lottie/) MUST have a
|
||||
// row in public/illustrations/assets.json. No row -> the asset may not ship. Fails
|
||||
// the build (exit 1) on any un-ledgered file. Run: npm run check:assets
|
||||
import { readFileSync, readdirSync, statSync, existsSync } from "node:fs";
|
||||
import { join, dirname, relative } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const PUBLIC = join(__dirname, "..", "public");
|
||||
const ILLUS = join(PUBLIC, "illustrations");
|
||||
const ledgerPath = join(ILLUS, "assets.json");
|
||||
|
||||
if (!existsSync(ledgerPath)) {
|
||||
console.error(`MISSING license ledger: ${ledgerPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const ledger = JSON.parse(readFileSync(ledgerPath, "utf8"));
|
||||
|
||||
function walk(dir) {
|
||||
if (!existsSync(dir)) return [];
|
||||
let out = [];
|
||||
for (const e of readdirSync(dir)) {
|
||||
const p = join(dir, e);
|
||||
if (statSync(p).isDirectory()) out = out.concat(walk(p));
|
||||
else if (/\.(svg|json)$/i.test(e) && e !== "assets.json") out.push(p);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Asset files live under illustrations/<source>/ and lottie/.
|
||||
const files = [...walk(ILLUS), ...walk(join(PUBLIC, "lottie"))]
|
||||
.map((p) => relative(ILLUS, p).split("\\").join("/"));
|
||||
|
||||
const missing = files.filter((f) => !ledger[f]);
|
||||
if (missing.length) {
|
||||
console.error(`Un-ledgered assets (add a row to assets.json):\n ${missing.join("\n ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`assets.json OK — ${files.length} vendored asset(s), all ledgered.`);
|
||||
@@ -0,0 +1,53 @@
|
||||
// Build-time character generator.
|
||||
//
|
||||
// DiceBear's `open-peeps` style IS Pablo Stanley's Open Peeps artwork (CC0-1.0).
|
||||
// We generate deterministic per-seed SVGs OFFLINE (no runtime CDN / HTTP call) and
|
||||
// vendor them into public/illustrations/dicebear/, then write a license-ledger row
|
||||
// per file into public/illustrations/assets.json. Run: npm run gen:dicebear
|
||||
import { createAvatar } from "@dicebear/core";
|
||||
import { openPeeps } from "@dicebear/collection";
|
||||
import { writeFileSync, readFileSync, mkdirSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const ILLUS = join(__dirname, "..", "public", "illustrations");
|
||||
const OUT = join(ILLUS, "dicebear");
|
||||
mkdirSync(OUT, { recursive: true });
|
||||
|
||||
const COUNT = 30;
|
||||
const VENDORED = "2026-06-22";
|
||||
const ledger = {};
|
||||
|
||||
for (let i = 1; i <= COUNT; i++) {
|
||||
const seed = `flatrender-peep-${i}`;
|
||||
// idRandomizer keeps SVG <defs> ids unique so multiple avatars can be inlined
|
||||
// in one document without clashing (Remotion composites many in one frame).
|
||||
const svg = createAvatar(openPeeps, { seed, size: 400, randomizeIds: true }).toString();
|
||||
const file = `openpeeps-${String(i).padStart(2, "0")}.svg`;
|
||||
writeFileSync(join(OUT, file), svg, "utf8");
|
||||
ledger[`dicebear/${file}`] = {
|
||||
source: "DiceBear open-peeps (Pablo Stanley Open Peeps)",
|
||||
license: "CC0-1.0",
|
||||
license_class: "CC0",
|
||||
commercial_ok: true,
|
||||
attribution_required: false,
|
||||
ai_training_allowed: true,
|
||||
animation_fit: "swap-transform (bust/half-body micro-rig)",
|
||||
generator: `createAvatar(openPeeps,{seed:'${seed}'})`,
|
||||
url: "https://www.dicebear.com/styles/open-peeps/",
|
||||
vendored: VENDORED,
|
||||
};
|
||||
}
|
||||
|
||||
// Merge into the assets.json license ledger (preserve any existing rows).
|
||||
const ledgerPath = join(ILLUS, "assets.json");
|
||||
let existing = {};
|
||||
try {
|
||||
existing = JSON.parse(readFileSync(ledgerPath, "utf8"));
|
||||
} catch {
|
||||
existing = {};
|
||||
}
|
||||
writeFileSync(ledgerPath, JSON.stringify({ ...existing, ...ledger }, null, 2) + "\n", "utf8");
|
||||
console.log(`generated ${COUNT} open-peeps SVGs in ${OUT}`);
|
||||
console.log(`ledger now has ${Object.keys({ ...existing, ...ledger }).length} rows`);
|
||||
@@ -2,6 +2,7 @@ import { Composition } from "remotion";
|
||||
import { ASPECTS } from "./lib/aspect";
|
||||
import { TEMPLATES } from "./templates";
|
||||
import { Three3DTest } from "./compositions/Three3DTest";
|
||||
import { AssetSheet } from "./compositions/AssetSheet";
|
||||
import {
|
||||
IlluminatedCircles,
|
||||
illuminatedCirclesSchema,
|
||||
@@ -113,6 +114,16 @@ export const RemotionRoot: React.FC = () => {
|
||||
height={720}
|
||||
/>
|
||||
|
||||
{/* Dev preview: vendored CC0 character library (not a customer template) */}
|
||||
<Composition
|
||||
id="AssetSheet"
|
||||
component={AssetSheet}
|
||||
durationInFrames={60}
|
||||
fps={30}
|
||||
width={1920}
|
||||
height={1080}
|
||||
/>
|
||||
|
||||
{/* Branded templates — each registered in all three aspects. A template may
|
||||
supply a dedicated component per aspect (componentsByAspect) when its
|
||||
design differs structurally; otherwise the shared `component` adapts
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import React from "react";
|
||||
import { AbsoluteFill, Img, staticFile } from "remotion";
|
||||
import { FONT } from "../lib/fonts";
|
||||
|
||||
// Dev/preview composition (NOT a customer template — registered standalone in Root,
|
||||
// never seeded). Renders a contact-sheet of the vendored CC0 Open-Peeps characters
|
||||
// to verify the public/illustrations -> staticFile() -> render pipeline works.
|
||||
const COUNT = 30;
|
||||
|
||||
export const AssetSheet: React.FC = () => {
|
||||
const items = Array.from({ length: COUNT }, (_, i) =>
|
||||
`illustrations/dicebear/openpeeps-${String(i + 1).padStart(2, "0")}.svg`
|
||||
);
|
||||
return (
|
||||
<AbsoluteFill style={{ background: "#ece4d6", fontFamily: FONT, padding: 44 }}>
|
||||
<div style={{ fontSize: 34, fontWeight: 800, color: "#2b3a55", marginBottom: 22, direction: "rtl" }}>
|
||||
کتابخانهٔ شخصیتها — Open Peeps (CC0) ۳۰ نمونه
|
||||
</div>
|
||||
<div style={{ display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gridAutoRows: "1fr", gap: 16, flex: 1 }}>
|
||||
{items.map((src, i) => (
|
||||
<div
|
||||
key={i}
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
borderRadius: 18,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
boxShadow: "0 10px 26px rgba(43,58,85,0.10)",
|
||||
}}
|
||||
>
|
||||
<Img src={staticFile(src)} style={{ width: "84%", height: "84%", objectFit: "contain" }} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||