- 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>
22 KiB
FlatRender — Curated Asset Library Catalog
Generated by the
flatrender-asset-sweepworkflow (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/humaaansfallback. - Use-cases: full-body hero rigging; per-limb wave/present/think/celebrate poses (replaces the hand-coded
Posesystem inCharacterStory.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-peepsexposes 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/collectionrun 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
idRandomizationto 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
avataaarsoffline 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-illustrationsmirror). 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.tsxscreenUrl+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 offuseCurrentFrame(). - unDraw/ManyPixels nature (curated, recolored).
- Three.js abstract via
@remotion/three(installed) for parallax sky/particles depth.
6. Grain / Texture
- Inline
feTurbulenceSVG noise — ALREADY inCharacterStory.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.
# 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.
{
"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:
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.jsonledger + 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 theCharacterStory.tsxpose 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). RebuildCharacterStory.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.jsoncoverage, 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:
- 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. - Nothing is vendored yet.
public/contains onlyfonts/.public/illustrations/+public/lottie/don't exist. The catalog is an acquisition plan, not a library. Riggable-today count = 0. - 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). - 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.
@remotion/lottieis a hard blocker (absent frompackage.json) — every Lottie path (§2) is non-functional until added; don't count those ~50–80 loops yet.- 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 viamixHex()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/lottieadded 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.