@devinilabs/reelstack 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +128 -0
- package/README.md +125 -0
- package/cli/beats.js +124 -0
- package/cli/bootstrap.js +124 -0
- package/cli/capture.js +34 -0
- package/cli/direction.js +114 -0
- package/cli/icons.js +49 -0
- package/cli/index.js +101 -0
- package/cli/init.js +253 -0
- package/cli/license.js +168 -0
- package/cli/lint.js +865 -0
- package/cli/preview.js +59 -0
- package/cli/render.js +404 -0
- package/cli/scaffold.js +239 -0
- package/cli/smoke.js +76 -0
- package/cli/update.js +26 -0
- package/cli/utils.js +184 -0
- package/docs/buyers-guide.md +220 -0
- package/docs/design-discipline.md +130 -0
- package/docs/family-galleries/dark.md +95 -0
- package/docs/family-galleries/forbidden.md +78 -0
- package/docs/family-galleries/glass.md +98 -0
- package/docs/family-galleries/paper.md +82 -0
- package/docs/family-galleries/warm.md +86 -0
- package/docs/superpowers/plans/2026-05-09-reelstack-init-readiness-gate.md +1166 -0
- package/docs/superpowers/specs/2026-05-09-reelstack-init-readiness-gate-design.md +233 -0
- package/families/dark/components/DriftingSpotlights.tsx +59 -0
- package/families/dark/components/FilmGrain.tsx +44 -0
- package/families/dark/components/ForestCard.tsx +43 -0
- package/families/dark/components/GridBackground.tsx +29 -0
- package/families/dark/components/RadialVignette.tsx +21 -0
- package/families/dark/components/Scanlines.tsx +35 -0
- package/families/dark/components/SegmentOpacity.ts +37 -0
- package/families/dark/components/index.ts +13 -0
- package/families/dark/index.ts +31 -0
- package/families/dark/palette.ts +98 -0
- package/families/dark/presets/claudedispatch.ts +46 -0
- package/families/dark/presets/codedrop.ts +37 -0
- package/families/dark/presets/gpt55.ts +54 -0
- package/families/dark/presets/notebooklm.ts +50 -0
- package/families/dark/presets/resourcescta.ts +35 -0
- package/families/dark/presets/skills.ts +40 -0
- package/families/dark/presets/stitch.ts +46 -0
- package/families/dark/presets/stitch2.ts +43 -0
- package/families/dark/typography.ts +16 -0
- package/families/forbidden/components/ForbiddenCausticBlobs.tsx +52 -0
- package/families/forbidden/components/NewsprintTexture.tsx +28 -0
- package/families/forbidden/components/TintedShadow.tsx +36 -0
- package/families/forbidden/components/index.ts +38 -0
- package/families/forbidden/index.ts +17 -0
- package/families/forbidden/palette.ts +88 -0
- package/families/forbidden/presets/heretic.ts +44 -0
- package/families/forbidden/typography.ts +18 -0
- package/families/glass/components/BreakdownCard.tsx +158 -0
- package/families/glass/components/CausticBlobs.tsx +49 -0
- package/families/glass/components/Counter.tsx +72 -0
- package/families/glass/components/EyebrowPill.tsx +59 -0
- package/families/glass/components/FilmStrip.tsx +202 -0
- package/families/glass/components/FloatingGlyphs.tsx +78 -0
- package/families/glass/components/GlassCard.tsx +58 -0
- package/families/glass/components/GlassCardBezel.tsx +45 -0
- package/families/glass/components/HairlineGrid.tsx +30 -0
- package/families/glass/components/IridescentRing.tsx +114 -0
- package/families/glass/components/IridescentText.tsx +98 -0
- package/families/glass/components/LightBeam.tsx +46 -0
- package/families/glass/components/ParticleBurst.tsx +62 -0
- package/families/glass/components/SonarRings.tsx +81 -0
- package/families/glass/components/StaggeredWords.tsx +74 -0
- package/families/glass/components/index.ts +20 -0
- package/families/glass/index.ts +31 -0
- package/families/glass/palette.ts +93 -0
- package/families/glass/presets/claudewatch.ts +64 -0
- package/families/glass/presets/claudewatchcta.ts +43 -0
- package/families/glass/presets/graphify.ts +45 -0
- package/families/glass/presets/gstack.ts +48 -0
- package/families/glass/presets/jcode.ts +50 -0
- package/families/glass/presets/lilagents.ts +52 -0
- package/families/glass/presets/paperclip.ts +43 -0
- package/families/glass/typography.ts +15 -0
- package/families/index.ts +49 -0
- package/families/paper/components/CardSpring.tsx +42 -0
- package/families/paper/components/CreamGrid.tsx +26 -0
- package/families/paper/components/EditorialSerifText.tsx +51 -0
- package/families/paper/components/GreenAccentCard.tsx +10 -0
- package/families/paper/components/PaperShadow.tsx +30 -0
- package/families/paper/components/ScaleBlurText.tsx +40 -0
- package/families/paper/components/index.ts +11 -0
- package/families/paper/index.ts +23 -0
- package/families/paper/palette.ts +102 -0
- package/families/paper/presets/designreel.ts +32 -0
- package/families/paper/presets/devini3d.ts +45 -0
- package/families/paper/presets/justdrop.ts +39 -0
- package/families/paper/presets/opus.ts +48 -0
- package/families/paper/typography.ts +17 -0
- package/families/warm/components/AccentGlow.tsx +60 -0
- package/families/warm/components/BentoCell.tsx +56 -0
- package/families/warm/components/BentoGrid.tsx +30 -0
- package/families/warm/components/FilmGrain.tsx +36 -0
- package/families/warm/components/ScaleBlurCounter.tsx +71 -0
- package/families/warm/components/WarmSurface.tsx +35 -0
- package/families/warm/components/index.ts +11 -0
- package/families/warm/index.ts +19 -0
- package/families/warm/palette.ts +81 -0
- package/families/warm/presets/huashu.ts +49 -0
- package/families/warm/presets/mempalace.ts +51 -0
- package/families/warm/typography.ts +17 -0
- package/package.json +85 -0
- package/reference/dark/claudedispatch.tsx +2441 -0
- package/reference/dark/notebooklm.tsx +2316 -0
- package/reference/dark/stitch.tsx +3040 -0
- package/reference/forbidden/heretic.tsx +2636 -0
- package/reference/glass/claudewatch.tsx +3827 -0
- package/reference/glass/graphify.tsx +2418 -0
- package/reference/glass/paperclip.tsx +2218 -0
- package/reference/paper/designreel.tsx +883 -0
- package/reference/paper/justdrop.tsx +1898 -0
- package/reference/paper/opus.tsx +1770 -0
- package/reference/warm/huashu.tsx +3413 -0
- package/reference/warm/mempalace.tsx +2909 -0
- package/skill/SKILL.md +229 -0
- package/skill/commands/reelstack-beats.md +20 -0
- package/skill/commands/reelstack-capture.md +24 -0
- package/skill/commands/reelstack-critique.md +15 -0
- package/skill/commands/reelstack-dark.md +40 -0
- package/skill/commands/reelstack-direction.md +17 -0
- package/skill/commands/reelstack-forbidden.md +25 -0
- package/skill/commands/reelstack-glass.md +39 -0
- package/skill/commands/reelstack-icons.md +22 -0
- package/skill/commands/reelstack-init.md +17 -0
- package/skill/commands/reelstack-lint.md +22 -0
- package/skill/commands/reelstack-paper.md +36 -0
- package/skill/commands/reelstack-render.md +20 -0
- package/skill/commands/reelstack-warm.md +36 -0
- package/templates/dark/template.tsx +115 -0
- package/templates/forbidden/template.tsx +111 -0
- package/templates/glass/template.tsx +201 -0
- package/templates/paper/template.tsx +133 -0
- package/templates/warm/template.tsx +210 -0
- package/utils/ai-purple-blocklist.ts +13 -0
- package/utils/banned-fonts.ts +11 -0
- package/utils/cubic-bezier.ts +36 -0
- package/utils/easing.ts +84 -0
- package/utils/grid.ts +13 -0
- package/utils/render-presets.json +56 -0
- package/utils/safe-zones.tsx +57 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReelStack — Glass Iridescent palette
|
|
3
|
+
*
|
|
4
|
+
* Verified against /Users/abhishekraj/my-video/src/GraphifyReel.tsx (the foundational
|
|
5
|
+
* preset). Other Glass presets (paperclip, gstack, lilagents, jcode) inherit this
|
|
6
|
+
* base and add accent variations in their own preset files.
|
|
7
|
+
*
|
|
8
|
+
* Mood: premium product reveal. Underwater-light caustics, glass surfaces,
|
|
9
|
+
* iridescent text shimmer.
|
|
10
|
+
*/
|
|
11
|
+
export const palette = {
|
|
12
|
+
// Backgrounds
|
|
13
|
+
bg: "#EFEAF2",
|
|
14
|
+
bgWarm: "#E9E2EE",
|
|
15
|
+
bgCool: "#E4E9F2",
|
|
16
|
+
|
|
17
|
+
// Ink (light-mode text)
|
|
18
|
+
ink: "#0E0E12", // contrast 16.8:1 on bg #EFEAF2 — WCAG AAA
|
|
19
|
+
inkSoft: "#26242C", // contrast 12.4:1 on bg #EFEAF2 — WCAG AAA
|
|
20
|
+
inkMuted: "#5A5867", // contrast 6.4:1 on bg #EFEAF2 — WCAG AA
|
|
21
|
+
inkDim: "#86848F", // contrast 3.4:1 on bg #EFEAF2 — WCAG AA-Large
|
|
22
|
+
|
|
23
|
+
// Iridescent stops (used by CausticBlobs, FloatingGlyphs, ParticleBurst)
|
|
24
|
+
iriCyan: "#7FE8D4",
|
|
25
|
+
iriViolet: "#8B7FE8",
|
|
26
|
+
iriRose: "#E89BC4",
|
|
27
|
+
iriGold: "#F2D88F",
|
|
28
|
+
|
|
29
|
+
// Pills (eyebrow / contextual labels)
|
|
30
|
+
violetPill: "#9D8BF2",
|
|
31
|
+
tealPill: "#85DDC9",
|
|
32
|
+
|
|
33
|
+
// Glass-card surface tokens
|
|
34
|
+
glassFill: "rgba(255, 255, 255, 0.42)",
|
|
35
|
+
glassFillStrong: "rgba(255, 255, 255, 0.62)",
|
|
36
|
+
glassBorder: "rgba(255, 255, 255, 0.86)",
|
|
37
|
+
|
|
38
|
+
// Macro-window dots (for embedded UI screenshots)
|
|
39
|
+
macClose: "#FF5F57",
|
|
40
|
+
macMin: "#FEBC2E",
|
|
41
|
+
macMax: "#28C840",
|
|
42
|
+
} as const;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Safe-zone constants — every Glass scaffold reserves these.
|
|
46
|
+
* Top 280–290 px and bottom 1500–1640 px are off-limits for hero copy / CTAs.
|
|
47
|
+
*/
|
|
48
|
+
export const safeZones = {
|
|
49
|
+
top: 290,
|
|
50
|
+
bottom: 1500, // y where the bottom 22% reserved band begins
|
|
51
|
+
canvas: { width: 1080, height: 1920 },
|
|
52
|
+
} as const;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Iridescent gradient strings derived from the palette — pre-computed so
|
|
56
|
+
* presets can drop them straight into CSS without re-mixing.
|
|
57
|
+
*/
|
|
58
|
+
export const gradients = {
|
|
59
|
+
iridescent: `linear-gradient(135deg, ${palette.iriCyan} 0%, ${palette.iriViolet} 33%, ${palette.iriRose} 66%, ${palette.iriGold} 100%)`,
|
|
60
|
+
causticCyan: `radial-gradient(ellipse, ${palette.iriCyan}55 0%, transparent 60%)`,
|
|
61
|
+
causticViolet: `radial-gradient(ellipse, ${palette.iriViolet}55 0%, transparent 60%)`,
|
|
62
|
+
causticRose: `radial-gradient(ellipse, ${palette.iriRose}55 0%, transparent 60%)`,
|
|
63
|
+
causticGold: `radial-gradient(ellipse, ${palette.iriGold}55 0%, transparent 60%)`,
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Hard-coded "allowed accents" list. The lint command checks every fill /
|
|
68
|
+
* stroke / background color in a Glass Iridescent reel against this set
|
|
69
|
+
* (plus neutral ink shades). Anything off-list is flagged as a hue bleed.
|
|
70
|
+
*/
|
|
71
|
+
export const ALLOWED_ACCENTS = [
|
|
72
|
+
palette.iriCyan,
|
|
73
|
+
palette.iriViolet,
|
|
74
|
+
palette.iriRose,
|
|
75
|
+
palette.iriGold,
|
|
76
|
+
palette.violetPill,
|
|
77
|
+
palette.tealPill,
|
|
78
|
+
palette.ink,
|
|
79
|
+
] as const;
|
|
80
|
+
|
|
81
|
+
export type GlassPalette = typeof palette;
|
|
82
|
+
|
|
83
|
+
/** Re-export grid units so consumers can pull them from the family entrypoint. */
|
|
84
|
+
export {
|
|
85
|
+
GRID,
|
|
86
|
+
GRID_2,
|
|
87
|
+
GRID_4,
|
|
88
|
+
GRID_6,
|
|
89
|
+
GRID_8,
|
|
90
|
+
GRID_12,
|
|
91
|
+
GRID_16,
|
|
92
|
+
GRID_24,
|
|
93
|
+
} from "../../utils/grid";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: claudewatch (Glass Iridescent)
|
|
3
|
+
* Source: ClaudeWatchReel.tsx
|
|
4
|
+
*
|
|
5
|
+
* The longest reel in the catalog (105.2s). Dual-narration structure (demo
|
|
6
|
+
* clip + technical explanation). Heavy use of frame-strip illustrations
|
|
7
|
+
* (film.mp4 sequences) for "video being watched" visuals.
|
|
8
|
+
*/
|
|
9
|
+
export const preset = {
|
|
10
|
+
name: "claudewatch",
|
|
11
|
+
family: "glass",
|
|
12
|
+
source: "ClaudeWatchReel",
|
|
13
|
+
durationFrames: 3156,
|
|
14
|
+
fps: 30,
|
|
15
|
+
copy: {
|
|
16
|
+
hook: "This custom Claude skill literally watches video.",
|
|
17
|
+
sub: "YouTube, any length. Whisper, auto-chapters, searchable, second brain.",
|
|
18
|
+
cta: "Free skill — link below.",
|
|
19
|
+
},
|
|
20
|
+
accents: {
|
|
21
|
+
claude: "#FF7A4D", // coral
|
|
22
|
+
film: "#E89414", // marigold
|
|
23
|
+
vector: "#6E6EFF", // indigo
|
|
24
|
+
success: "#1FD891", // mint
|
|
25
|
+
crimson: "#FF5C7E",
|
|
26
|
+
plasma: "#B58CFF",
|
|
27
|
+
},
|
|
28
|
+
beats: {
|
|
29
|
+
hook: 0,
|
|
30
|
+
viral: 240,
|
|
31
|
+
demo: 540,
|
|
32
|
+
result: 1110,
|
|
33
|
+
decode: 1410,
|
|
34
|
+
brain: 1740,
|
|
35
|
+
ytCta: 1980,
|
|
36
|
+
hood: 2160,
|
|
37
|
+
ytdlp: 2310,
|
|
38
|
+
ffmpeg: 2460,
|
|
39
|
+
flipbook: 2640,
|
|
40
|
+
local: 2820,
|
|
41
|
+
comment: 2970,
|
|
42
|
+
end: 3120,
|
|
43
|
+
},
|
|
44
|
+
primitives: [
|
|
45
|
+
"CausticBlobs",
|
|
46
|
+
"HairlineGrid",
|
|
47
|
+
"GlassCard", // strong variant: glassFill 0.42 / glassFillStrong 0.62
|
|
48
|
+
"EyebrowPill",
|
|
49
|
+
"StaggeredWords",
|
|
50
|
+
"Counter",
|
|
51
|
+
"SonarRings",
|
|
52
|
+
"ParticleBurst",
|
|
53
|
+
"LightBeam",
|
|
54
|
+
"FloatingGlyphs",
|
|
55
|
+
"FilmStrip", // perforated 35mm strip — "Type. Paste. Watch." centerpiece
|
|
56
|
+
"IridescentRing", // multi-stop chromatic halo — alternative to SonarRings
|
|
57
|
+
"IridescentText", // hero-word gradient treatment ("Watch.")
|
|
58
|
+
"BreakdownCard", // BREAKDOWN.MD callout under the filmstrip
|
|
59
|
+
"FrameStrip", // preset-specific — film.mp4 sequences as flipbook
|
|
60
|
+
],
|
|
61
|
+
glassVariant: "strong",
|
|
62
|
+
notes:
|
|
63
|
+
"ClaudeWatch's six accent colors are named scene-specific (claude, film, vector, success, crimson, plasma). Pick the accent per scene from the named set rather than mixing across scenes.",
|
|
64
|
+
} as const;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: claudewatchcta (Glass Iridescent)
|
|
3
|
+
* Source: ClaudeWatchCTAReel.tsx
|
|
4
|
+
*
|
|
5
|
+
* 8-second standalone CTA cut. Uses ClaudeWatchReel's primitives but
|
|
6
|
+
* collapsed into a tight quick-hook + eyebrow + hero word + sub-line +
|
|
7
|
+
* description-pill structure. Use as an outro/sticker on other reels.
|
|
8
|
+
*/
|
|
9
|
+
export const preset = {
|
|
10
|
+
name: "claudewatchcta",
|
|
11
|
+
family: "glass",
|
|
12
|
+
source: "ClaudeWatchCTAReel",
|
|
13
|
+
durationFrames: 240,
|
|
14
|
+
fps: 30,
|
|
15
|
+
copy: {
|
|
16
|
+
hook: "Claude Watches Video.",
|
|
17
|
+
sub: "Free skill, link below.",
|
|
18
|
+
},
|
|
19
|
+
accents: {
|
|
20
|
+
claude: "#FF7A4D",
|
|
21
|
+
},
|
|
22
|
+
beats: {
|
|
23
|
+
hook: 0,
|
|
24
|
+
eyebrow: 30,
|
|
25
|
+
heroWord: 60,
|
|
26
|
+
subLine: 120,
|
|
27
|
+
descriptionPill: 180,
|
|
28
|
+
end: 240,
|
|
29
|
+
},
|
|
30
|
+
primitives: [
|
|
31
|
+
"CausticBlobs",
|
|
32
|
+
"GlassCard",
|
|
33
|
+
"EyebrowPill",
|
|
34
|
+
"StaggeredWords",
|
|
35
|
+
"SonarRings",
|
|
36
|
+
"ParticleBurst",
|
|
37
|
+
"IridescentText", // hero-word gradient — fits inside the 8s budget
|
|
38
|
+
"BreakdownCard", // optional sub-line if the CTA needs structured rows
|
|
39
|
+
"IridescentRing", // chromatic halo behind the hero word
|
|
40
|
+
],
|
|
41
|
+
notes:
|
|
42
|
+
"Designed to be appended to longer reels as a final 8s CTA. Frame budget is tight — keep motion floors satisfied with concurrent layers, not sequenced ones.",
|
|
43
|
+
} as const;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: graphify (Glass Iridescent)
|
|
3
|
+
* Source: GraphifyReel.tsx — the foundational Glass reel.
|
|
4
|
+
*
|
|
5
|
+
* The reference build for the entire family. Multimodal product reveal,
|
|
6
|
+
* 65 seconds, full primitive vocabulary on display.
|
|
7
|
+
*/
|
|
8
|
+
export const preset = {
|
|
9
|
+
name: "graphify",
|
|
10
|
+
family: "glass",
|
|
11
|
+
source: "GraphifyReel",
|
|
12
|
+
durationFrames: 1956,
|
|
13
|
+
fps: 30,
|
|
14
|
+
copy: {
|
|
15
|
+
hook: "Multimodal Claude understands the whole web. Graph everything.",
|
|
16
|
+
cta: "Hit my YouTube for the full walkthrough.",
|
|
17
|
+
},
|
|
18
|
+
accents: {},
|
|
19
|
+
beats: {
|
|
20
|
+
intro: 0,
|
|
21
|
+
hookEnd: 180,
|
|
22
|
+
problem: 540,
|
|
23
|
+
revealName: 720,
|
|
24
|
+
mechanism: 1020,
|
|
25
|
+
clip: 1320,
|
|
26
|
+
numbers: 1500,
|
|
27
|
+
multimodal: 1680,
|
|
28
|
+
compat: 1830,
|
|
29
|
+
cta: 1860,
|
|
30
|
+
},
|
|
31
|
+
primitives: [
|
|
32
|
+
"CausticBlobs",
|
|
33
|
+
"HairlineGrid",
|
|
34
|
+
"GlassCard",
|
|
35
|
+
"EyebrowPill",
|
|
36
|
+
"StaggeredWords",
|
|
37
|
+
"Counter",
|
|
38
|
+
"SonarRings",
|
|
39
|
+
"ParticleBurst",
|
|
40
|
+
"LightBeam",
|
|
41
|
+
"FloatingGlyphs",
|
|
42
|
+
],
|
|
43
|
+
notes:
|
|
44
|
+
"Use this preset when in doubt — it carries the strongest motion-floor budget and the most polished primitive composition.",
|
|
45
|
+
} as const;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: gstack (Glass Iridescent)
|
|
3
|
+
* Source: GstackReel.tsx
|
|
4
|
+
*
|
|
5
|
+
* Long-form (94s) feature-callout heavy reel. Heaviest GlassCard usage in
|
|
6
|
+
* the family — backdropFilter blur(32px) saturate(180%) for that frosted
|
|
7
|
+
* heavy feel.
|
|
8
|
+
*/
|
|
9
|
+
export const preset = {
|
|
10
|
+
name: "gstack",
|
|
11
|
+
family: "glass",
|
|
12
|
+
source: "GstackReel",
|
|
13
|
+
durationFrames: 2820,
|
|
14
|
+
fps: 30,
|
|
15
|
+
copy: {
|
|
16
|
+
hook: "The president of YC just open-sourced his entire Claude Code setup. It's called gstack.",
|
|
17
|
+
cta: "Free, MIT, just clone.",
|
|
18
|
+
},
|
|
19
|
+
accents: {
|
|
20
|
+
ycOrange: "#F26625",
|
|
21
|
+
emerald: "#34D399",
|
|
22
|
+
rose: "#FB7185",
|
|
23
|
+
},
|
|
24
|
+
beats: {
|
|
25
|
+
hook: 0,
|
|
26
|
+
name: 240,
|
|
27
|
+
officeHours: 720,
|
|
28
|
+
qa: 1140,
|
|
29
|
+
cso: 1500,
|
|
30
|
+
parallel: 1860,
|
|
31
|
+
install: 2280,
|
|
32
|
+
cta: 2580,
|
|
33
|
+
end: 2820,
|
|
34
|
+
},
|
|
35
|
+
primitives: [
|
|
36
|
+
"CausticBlobs",
|
|
37
|
+
"HairlineGrid",
|
|
38
|
+
"GlassCard", // heavy variant — backdropFilter blur(32px) saturate(180%)
|
|
39
|
+
"EyebrowPill",
|
|
40
|
+
"StaggeredWords",
|
|
41
|
+
"SonarRings",
|
|
42
|
+
"ParticleBurst",
|
|
43
|
+
"FloatingGlyphs",
|
|
44
|
+
],
|
|
45
|
+
glassVariant: "heavy",
|
|
46
|
+
notes:
|
|
47
|
+
"Use the heavy GlassCard variant — gstack's feature callouts need stronger glass to read against the iridescent caustics behind them.",
|
|
48
|
+
} as const;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: jcode (Glass Iridescent)
|
|
3
|
+
* Source: JcodeReel.tsx
|
|
4
|
+
*
|
|
5
|
+
* Performance-claim reel with a single rust-orange accent on the iridescent
|
|
6
|
+
* base. ScrambleText (incremental char reveal) is the signature element.
|
|
7
|
+
* Film-grain overlay constant throughout.
|
|
8
|
+
*/
|
|
9
|
+
export const preset = {
|
|
10
|
+
name: "jcode",
|
|
11
|
+
family: "glass",
|
|
12
|
+
source: "JcodeReel",
|
|
13
|
+
durationFrames: 2164,
|
|
14
|
+
fps: 30,
|
|
15
|
+
copy: {
|
|
16
|
+
hook: "63 times faster than Codex. Jcode rebuilt in Rust. Parallel swarms.",
|
|
17
|
+
cta: "GitHub link below.",
|
|
18
|
+
},
|
|
19
|
+
accents: {
|
|
20
|
+
rust: "#E55A1A",
|
|
21
|
+
rustSoft: "#F9C5A5",
|
|
22
|
+
rustDeep: "#9B3A0E",
|
|
23
|
+
},
|
|
24
|
+
beats: {
|
|
25
|
+
hook: 0,
|
|
26
|
+
nameDrop: 348,
|
|
27
|
+
benchmark: 554,
|
|
28
|
+
rustReveal: 907,
|
|
29
|
+
parallel: 1153,
|
|
30
|
+
swarms: 1463,
|
|
31
|
+
install: 1660,
|
|
32
|
+
cta: 1995,
|
|
33
|
+
end: 2164,
|
|
34
|
+
},
|
|
35
|
+
primitives: [
|
|
36
|
+
"CausticBlobs",
|
|
37
|
+
"HairlineGrid",
|
|
38
|
+
"GlassCard",
|
|
39
|
+
"EyebrowPill",
|
|
40
|
+
"StaggeredWords",
|
|
41
|
+
"Counter",
|
|
42
|
+
"SonarRings",
|
|
43
|
+
"ParticleBurst",
|
|
44
|
+
"FloatingGlyphs", // code symbols only — no emojis
|
|
45
|
+
"ScrambleText", // preset-specific
|
|
46
|
+
"FilmGrain", // constant overlay (SVG turbulence, opacity 0.06)
|
|
47
|
+
],
|
|
48
|
+
notes:
|
|
49
|
+
"FloatingGlyphs use code-symbol set only (∑, ∫, ⟨⟩, ≠) — no emojis ever. Film grain stays on for the whole reel; do not toggle per scene.",
|
|
50
|
+
} as const;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: lilagents (Glass Iridescent)
|
|
3
|
+
* Source: LilAgentsReel.tsx
|
|
4
|
+
*
|
|
5
|
+
* Character-driven (Bruce + Jazz). Dock dark background variant + ThoughtBubble
|
|
6
|
+
* components. Sits in Glass family because the iridescent glass primitives
|
|
7
|
+
* still drive scene composition, but uses a darker bg.
|
|
8
|
+
*/
|
|
9
|
+
export const preset = {
|
|
10
|
+
name: "lilagents",
|
|
11
|
+
family: "glass",
|
|
12
|
+
source: "LilAgentsReel",
|
|
13
|
+
durationFrames: 2160,
|
|
14
|
+
fps: 30,
|
|
15
|
+
copy: {
|
|
16
|
+
hook: "Tiny Claude agents walk on your dock. Bruce and Jazz. Local, no signup.",
|
|
17
|
+
cta: "Free download below.",
|
|
18
|
+
},
|
|
19
|
+
accents: {
|
|
20
|
+
dockBg: "#1c162e", // overrides bg for the dock-style dark variant
|
|
21
|
+
peach: "#FFB088",
|
|
22
|
+
bruce: "#E89BC4",
|
|
23
|
+
jazz: "#7FE8D4",
|
|
24
|
+
terminalText: "#A8FFD9",
|
|
25
|
+
},
|
|
26
|
+
beats: {
|
|
27
|
+
hook: 0,
|
|
28
|
+
bruceIntro: 165,
|
|
29
|
+
jazzIntro: 268,
|
|
30
|
+
interaction: 448,
|
|
31
|
+
capability1: 542,
|
|
32
|
+
capability2: 711,
|
|
33
|
+
capability3: 837,
|
|
34
|
+
install: 1093,
|
|
35
|
+
privacy: 1391,
|
|
36
|
+
local: 1681,
|
|
37
|
+
cta: 2016,
|
|
38
|
+
},
|
|
39
|
+
primitives: [
|
|
40
|
+
"CausticBlobs",
|
|
41
|
+
"GlassCard",
|
|
42
|
+
"EyebrowPill",
|
|
43
|
+
"StaggeredWords",
|
|
44
|
+
"SonarRings",
|
|
45
|
+
"ParticleBurst",
|
|
46
|
+
"ThoughtBubble", // preset-specific
|
|
47
|
+
"DockSurface", // preset-specific (dark dock-style bg)
|
|
48
|
+
],
|
|
49
|
+
bgOverride: "dockBg",
|
|
50
|
+
notes:
|
|
51
|
+
"Override the family bg with dockBg (#1c162e) for character scenes. ThoughtBubbles float on sine paths. Terminal-text accent (#A8FFD9) for code/install scenes.",
|
|
52
|
+
} as const;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: paperclip (Glass Iridescent)
|
|
3
|
+
* Source: PaperclipReel.tsx
|
|
4
|
+
*
|
|
5
|
+
* Open-source reveal. 55 seconds. PaperclipGlyph (custom SVG paperclip with
|
|
6
|
+
* iridescent stroke draw-in via dash offset) is the signature element.
|
|
7
|
+
*/
|
|
8
|
+
export const preset = {
|
|
9
|
+
name: "paperclip",
|
|
10
|
+
family: "glass",
|
|
11
|
+
source: "PaperclipReel",
|
|
12
|
+
durationFrames: 1650,
|
|
13
|
+
fps: 30,
|
|
14
|
+
copy: {
|
|
15
|
+
hook: "It's called Paperclip. It's not OpenAI, it's not Google. MIT licensed, open source.",
|
|
16
|
+
cta: "Link in description.",
|
|
17
|
+
},
|
|
18
|
+
accents: {},
|
|
19
|
+
beats: {
|
|
20
|
+
hook: 0,
|
|
21
|
+
reveal: 270,
|
|
22
|
+
demoIn: 594,
|
|
23
|
+
demoOut: 1410,
|
|
24
|
+
cta: 1560,
|
|
25
|
+
},
|
|
26
|
+
primitives: [
|
|
27
|
+
"CausticBlobs",
|
|
28
|
+
"HairlineGrid",
|
|
29
|
+
"GlassCard",
|
|
30
|
+
"EyebrowPill",
|
|
31
|
+
"StaggeredWords",
|
|
32
|
+
"SonarRings",
|
|
33
|
+
"ParticleBurst",
|
|
34
|
+
"PaperclipGlyph", // preset-specific: see family components/PaperclipGlyph.tsx
|
|
35
|
+
],
|
|
36
|
+
embeddedClip: {
|
|
37
|
+
path: "captures/paperclip/demo.mp4",
|
|
38
|
+
sequenceStart: 594,
|
|
39
|
+
durationFrames: 816, // 27.17s
|
|
40
|
+
},
|
|
41
|
+
notes:
|
|
42
|
+
"PaperclipGlyph uses dash-offset animation on the inline SVG. Audio-locked beats are critical: demo cut points snap to whisper SRT segments.",
|
|
43
|
+
} as const;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Glass Iridescent typography scale. Geist Sans + Geist Mono only.
|
|
2
|
+
* Pulled from existing template usage; locks the implicit scale into named tokens.
|
|
3
|
+
* Letter-spacing follows leonxlnx/taste-skill: tighter at large sizes, looser for caption/mono.
|
|
4
|
+
*/
|
|
5
|
+
export const typography = {
|
|
6
|
+
hero: { fontSize: 96, fontWeight: 700, letterSpacing: -2, lineHeight: 1.05, fontFamily: "Geist, system-ui" },
|
|
7
|
+
h1: { fontSize: 84, fontWeight: 700, letterSpacing: -1.5, lineHeight: 1.1, fontFamily: "Geist, system-ui" },
|
|
8
|
+
h2: { fontSize: 56, fontWeight: 700, letterSpacing: -1.5, lineHeight: 1.15, fontFamily: "Geist, system-ui" },
|
|
9
|
+
h3: { fontSize: 36, fontWeight: 600, letterSpacing: -1, lineHeight: 1.2, fontFamily: "Geist, system-ui" },
|
|
10
|
+
body: { fontSize: 24, fontWeight: 500, letterSpacing: -0.2, lineHeight: 1.5, fontFamily: "Geist, system-ui" },
|
|
11
|
+
caption: { fontSize: 18, fontWeight: 500, letterSpacing: 0.5, lineHeight: 1.4, fontFamily: "Geist, system-ui", textTransform: "uppercase" as const },
|
|
12
|
+
mono: { fontSize: 22, fontWeight: 500, letterSpacing: 0.3, lineHeight: 1.4, fontFamily: "Geist Mono, monospace" },
|
|
13
|
+
counter: { fontSize: 144, fontWeight: 700, letterSpacing: -2, lineHeight: 1, fontFamily: "Geist Mono, monospace" },
|
|
14
|
+
} as const;
|
|
15
|
+
export type Typography = typeof typography;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReelStack — family registry.
|
|
3
|
+
*
|
|
4
|
+
* The CLI scaffolder reads this when handed `--family=<name> --preset=<name>`
|
|
5
|
+
* to validate inputs and to pull palette + preset metadata.
|
|
6
|
+
*/
|
|
7
|
+
import * as glass from "./glass";
|
|
8
|
+
import * as paper from "./paper";
|
|
9
|
+
import * as dark from "./dark";
|
|
10
|
+
import * as warm from "./warm";
|
|
11
|
+
import * as forbidden from "./forbidden";
|
|
12
|
+
|
|
13
|
+
export const families = {
|
|
14
|
+
glass,
|
|
15
|
+
paper,
|
|
16
|
+
dark,
|
|
17
|
+
warm,
|
|
18
|
+
forbidden,
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
export type FamilyName = keyof typeof families;
|
|
22
|
+
|
|
23
|
+
export const FAMILY_NAMES: FamilyName[] = ["glass", "paper", "dark", "warm", "forbidden"];
|
|
24
|
+
|
|
25
|
+
export function resolveFamily(name: string) {
|
|
26
|
+
if (!(name in families)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Unknown family "${name}". Valid families: ${FAMILY_NAMES.join(", ")}.`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return families[name as FamilyName];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function resolvePreset(familyName: string, presetName: string) {
|
|
35
|
+
const fam = resolveFamily(familyName);
|
|
36
|
+
if (!(presetName in fam.presets)) {
|
|
37
|
+
const valid = Object.keys(fam.presets).join(", ");
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Unknown preset "${presetName}" in family "${familyName}". Valid presets: ${valid}.`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
// @ts-expect-error - dynamic key access; runtime narrowing happens above
|
|
43
|
+
return fam.presets[presetName];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const TOTAL_PRESETS = Object.values(families).reduce(
|
|
47
|
+
(n, fam) => n + Object.keys(fam.presets).length,
|
|
48
|
+
0,
|
|
49
|
+
); // === 22
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import { spring, useCurrentFrame, useVideoConfig } from "remotion";
|
|
3
|
+
import { palette, springConfig, paperShadow } from "../palette";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CardSpring — generic dark-green card revealed with the family's signature
|
|
7
|
+
* spring (damping 20 / stiffness 200).
|
|
8
|
+
*
|
|
9
|
+
* Animates from translateY(32px) + scale(0.96) + opacity(0) to identity over
|
|
10
|
+
* the spring curve. Background is `palette.cardForest` with the multi-layer
|
|
11
|
+
* `paperShadow.card` stack. Cream text on forest green is the Cream Paper
|
|
12
|
+
* family contract — never override `color` to a dark value.
|
|
13
|
+
*/
|
|
14
|
+
export const CardSpring: React.FC<{
|
|
15
|
+
startFrame: number;
|
|
16
|
+
reduceMotion?: boolean;
|
|
17
|
+
style?: CSSProperties;
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
}> = ({ startFrame, reduceMotion = false, style, children }) => {
|
|
20
|
+
const frame = useCurrentFrame();
|
|
21
|
+
const { fps } = useVideoConfig();
|
|
22
|
+
const local = Math.max(0, frame - startFrame);
|
|
23
|
+
const t = reduceMotion ? 1 : spring({ frame: local, fps, config: springConfig });
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
style={{
|
|
27
|
+
background: palette.cardForest,
|
|
28
|
+
color: "#e9eee8",
|
|
29
|
+
borderRadius: 24,
|
|
30
|
+
padding: 36,
|
|
31
|
+
boxShadow: paperShadow.card,
|
|
32
|
+
opacity: t,
|
|
33
|
+
transform: reduceMotion
|
|
34
|
+
? "none"
|
|
35
|
+
: `translateY(${(1 - t) * 32}px) scale(${0.96 + t * 0.04})`,
|
|
36
|
+
...style,
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AbsoluteFill } from "remotion";
|
|
3
|
+
import { palette } from "../palette";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CreamGrid — full-bleed 72×72 grid in `palette.paperGrid` (a quiet warm
|
|
7
|
+
* tone) with a radial mask fade from center.
|
|
8
|
+
*
|
|
9
|
+
* Provides "paper texture" — the document feel the buyer reads as editorial
|
|
10
|
+
* rather than digital. Pure CSS background, zero per-frame cost. Sits at the
|
|
11
|
+
* very bottom of the layer stack, just above `palette.bg`.
|
|
12
|
+
*/
|
|
13
|
+
export const CreamGrid: React.FC = () => (
|
|
14
|
+
<AbsoluteFill
|
|
15
|
+
style={{
|
|
16
|
+
backgroundImage: `
|
|
17
|
+
linear-gradient(to right, ${palette.paperGrid} 1px, transparent 1px),
|
|
18
|
+
linear-gradient(to bottom, ${palette.paperGrid} 1px, transparent 1px)
|
|
19
|
+
`,
|
|
20
|
+
backgroundSize: "72px 72px",
|
|
21
|
+
WebkitMaskImage: "radial-gradient(ellipse at center, rgba(0,0,0,1) 35%, rgba(0,0,0,0) 80%)",
|
|
22
|
+
maskImage: "radial-gradient(ellipse at center, rgba(0,0,0,1) 35%, rgba(0,0,0,0) 80%)",
|
|
23
|
+
pointerEvents: "none",
|
|
24
|
+
}}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React, { CSSProperties } from "react";
|
|
2
|
+
import { useCurrentFrame } from "remotion";
|
|
3
|
+
import { palette } from "../palette";
|
|
4
|
+
import { ease } from "../../../utils/easing";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Editorial-serif hero text for Cream Paper reels.
|
|
8
|
+
* Falls back through Lyon Text → Newsreader → Playfair Display → serif.
|
|
9
|
+
* Inspired by leonxlnx/taste-skill-minimalist's "serif fonts ONLY for hero".
|
|
10
|
+
*/
|
|
11
|
+
export const EditorialSerifText: React.FC<{
|
|
12
|
+
startFrame: number;
|
|
13
|
+
text: string;
|
|
14
|
+
fontSize?: number;
|
|
15
|
+
color?: string;
|
|
16
|
+
italic?: boolean;
|
|
17
|
+
reduceMotion?: boolean;
|
|
18
|
+
style?: CSSProperties;
|
|
19
|
+
}> = ({
|
|
20
|
+
startFrame,
|
|
21
|
+
text,
|
|
22
|
+
fontSize = 96,
|
|
23
|
+
color = palette.heading,
|
|
24
|
+
italic = false,
|
|
25
|
+
reduceMotion = false,
|
|
26
|
+
style,
|
|
27
|
+
}) => {
|
|
28
|
+
const frame = useCurrentFrame();
|
|
29
|
+
const local = Math.max(0, frame - startFrame);
|
|
30
|
+
const tRaw = Math.min(1, local / 24);
|
|
31
|
+
const t = reduceMotion ? 1 : ease.power3Out(tRaw);
|
|
32
|
+
return (
|
|
33
|
+
<span
|
|
34
|
+
style={{
|
|
35
|
+
display: "inline-block",
|
|
36
|
+
fontFamily: "'Lyon Text', 'Newsreader', 'Playfair Display', Georgia, serif",
|
|
37
|
+
fontSize,
|
|
38
|
+
fontWeight: 500,
|
|
39
|
+
fontStyle: italic ? "italic" : "normal",
|
|
40
|
+
letterSpacing: -1,
|
|
41
|
+
lineHeight: 1.05,
|
|
42
|
+
color,
|
|
43
|
+
opacity: t,
|
|
44
|
+
transform: reduceMotion ? "none" : `translateY(${(1 - t) * 12}px) scale(${0.97 + t * 0.03})`,
|
|
45
|
+
...style,
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
{text}
|
|
49
|
+
</span>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CardSpring } from "./CardSpring";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GreenAccentCard — semantic alias of `CardSpring`.
|
|
5
|
+
*
|
|
6
|
+
* Some Cream Paper presets reference the spring-revealed forest-green card by
|
|
7
|
+
* the more descriptive `GreenAccentCard` name. Both names resolve to the same
|
|
8
|
+
* component so preset metadata can use whichever reads better in context.
|
|
9
|
+
*/
|
|
10
|
+
export const GreenAccentCard = CardSpring;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import { paperShadow } from "../palette";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PaperShadow — wrapper that applies one of the family's three printed-shadow
|
|
6
|
+
* stacks to its children.
|
|
7
|
+
*
|
|
8
|
+
* Depths:
|
|
9
|
+
* - "soft" — page-level lift, used under inline thumbnails
|
|
10
|
+
* - "card" — default, matches `CardSpring`
|
|
11
|
+
* - "elevated" — anchor-scene cards that need a second layer of depth
|
|
12
|
+
*
|
|
13
|
+
* The shadow is applied via inline `boxShadow`, so the wrapped element should
|
|
14
|
+
* be the visual surface (a div with a background and borderRadius). Wrapping
|
|
15
|
+
* a transparent fragment will cast no shadow.
|
|
16
|
+
*/
|
|
17
|
+
export const PaperShadow: React.FC<{
|
|
18
|
+
depth?: "soft" | "card" | "elevated";
|
|
19
|
+
style?: CSSProperties;
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
}> = ({ depth = "card", style, children }) => (
|
|
22
|
+
<div
|
|
23
|
+
style={{
|
|
24
|
+
boxShadow: paperShadow[depth],
|
|
25
|
+
...style,
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
{children}
|
|
29
|
+
</div>
|
|
30
|
+
);
|