@4ort/cli 0.8.3 → 0.8.4
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/README.md +25 -2
- package/dist/index.js +1 -1
- package/examples/fact-short.html +160 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -409,8 +409,31 @@ automatically (no `FORT_FACTORY_KEY` needed).
|
|
|
409
409
|
|
|
410
410
|
`render` sends a single HTML composition (or a directory, tarred) to the
|
|
411
411
|
video factory, polls to completion, downloads the mp4 — and with
|
|
412
|
-
`--publish` it lands on 4ort.mov directly.
|
|
413
|
-
|
|
412
|
+
`--publish` it lands on 4ort.mov directly.
|
|
413
|
+
|
|
414
|
+
**Start from the shipped template** — a known-good composition that passes
|
|
415
|
+
the factory's lint and renders a 12s vertical fact-card short:
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
cp "$(npm root -g)/@4ort/cli/examples/fact-short.html" my-short.html
|
|
419
|
+
# edit the text/colors, then:
|
|
420
|
+
4ort mov render my-short.html -q draft
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
The factory lints compositions strictly. The contract, in short:
|
|
424
|
+
|
|
425
|
+
- The root is a plain `<div>` with `data-composition-id`, `data-width`,
|
|
426
|
+
`data-height`, `data-start="0"`, and `data-duration` — directly in
|
|
427
|
+
`<body>`, **no `<template>` wrapper**.
|
|
428
|
+
- Exactly one GSAP timeline, created `{ paused: true }`, registered
|
|
429
|
+
**synchronously** on `window.__timelines` under the **same id** as the
|
|
430
|
+
root div. Never build it inside async/setTimeout.
|
|
431
|
+
- Deterministic only: no `Math.random()`, no `Date.now()`, no
|
|
432
|
+
`repeat: -1` (use finite repeat counts), never call `.play()` on media.
|
|
433
|
+
- Video length comes from `data-duration`, not the GSAP timeline length.
|
|
434
|
+
- Scope GSAP selectors to your composition root so they can't leak.
|
|
435
|
+
- Don't write attribute-like literals in HTML comments — the linter scans
|
|
436
|
+
raw source and will misparse them as code.
|
|
414
437
|
|
|
415
438
|
### `4ort vault` + `4ort run` — secrets without plaintext
|
|
416
439
|
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ const program = new Command();
|
|
|
34
34
|
program
|
|
35
35
|
.name("4ort")
|
|
36
36
|
.description("Unified CLI for the 4ort ecosystem — hosting, knowledge graph, and more")
|
|
37
|
-
.version("0.8.
|
|
37
|
+
.version("0.8.4");
|
|
38
38
|
// ─────────────────────────────────────────────────────────────────────
|
|
39
39
|
// 4ort.net subdomain hosting
|
|
40
40
|
// ─────────────────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>fact-short — 4ort mov render starter template</title>
|
|
6
|
+
<!--
|
|
7
|
+
Minimal KNOWN-GOOD HyperFrames composition for `4ort mov render`.
|
|
8
|
+
Vertical 1080x1920 (a "short"). For landscape swap the width/height attrs to 1920/1080.
|
|
9
|
+
|
|
10
|
+
The lint contract (violate any of these and the factory rejects the job):
|
|
11
|
+
1. The root element is a plain div with a composition id attribute, DIRECTLY
|
|
12
|
+
in the body - no template-tag wrapper on a standalone file.
|
|
13
|
+
2. The root div needs numeric width + height attrs, start "0", and a duration.
|
|
14
|
+
3. Exactly one GSAP timeline, created paused, registered synchronously on the
|
|
15
|
+
global timelines object under the SAME id as the root div (see the script
|
|
16
|
+
at the bottom of this file - copy that shape exactly).
|
|
17
|
+
4. No randomness or clock reads, no infinite repeats (use finite counts),
|
|
18
|
+
never call play() on media - the renderer owns the clock.
|
|
19
|
+
5. Total video length comes from the duration attr, not the GSAP timeline.
|
|
20
|
+
6. Keep GSAP selectors scoped (prefix them with the composition root) so they
|
|
21
|
+
never leak into other compositions when bundled.
|
|
22
|
+
|
|
23
|
+
NOTE: do not write attribute-like literals (the id/width/timeline patterns) in
|
|
24
|
+
comments - the linter scans raw source and will misparse them as code.
|
|
25
|
+
|
|
26
|
+
Edit the text, colors, and facts. Render with:
|
|
27
|
+
4ort mov render fact-short.html -q draft # test render
|
|
28
|
+
4ort mov render fact-short.html --publish -t "Title" # render + publish to 4ort.mov
|
|
29
|
+
-->
|
|
30
|
+
<style>
|
|
31
|
+
* { margin: 0; box-sizing: border-box; }
|
|
32
|
+
body { background: #000; }
|
|
33
|
+
|
|
34
|
+
[data-composition-id="fact-short"] {
|
|
35
|
+
position: relative;
|
|
36
|
+
overflow: hidden;
|
|
37
|
+
background: #0d0d14;
|
|
38
|
+
font-family: "Inter", "Helvetica Neue", Arial, sans-serif;
|
|
39
|
+
color: #e8e8f0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* soft radial glow — radial (not linear) avoids H.264 banding on dark bg */
|
|
43
|
+
.glow {
|
|
44
|
+
position: absolute;
|
|
45
|
+
top: -20%; left: 50%;
|
|
46
|
+
width: 1400px; height: 1400px;
|
|
47
|
+
transform: translateX(-50%);
|
|
48
|
+
background: radial-gradient(circle, rgba(167, 139, 250, 0.16) 0%, rgba(13, 13, 20, 0) 60%);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.scene-content {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
justify-content: center;
|
|
55
|
+
width: 100%;
|
|
56
|
+
height: 100%;
|
|
57
|
+
padding: 160px 96px;
|
|
58
|
+
gap: 44px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.kicker {
|
|
62
|
+
font-size: 34px;
|
|
63
|
+
font-weight: 700;
|
|
64
|
+
letter-spacing: 0.22em;
|
|
65
|
+
text-transform: uppercase;
|
|
66
|
+
color: #a78bfa;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.headline {
|
|
70
|
+
font-size: 110px;
|
|
71
|
+
font-weight: 800;
|
|
72
|
+
line-height: 1.05;
|
|
73
|
+
max-width: 880px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.accent-bar {
|
|
77
|
+
width: 140px;
|
|
78
|
+
height: 8px;
|
|
79
|
+
border-radius: 4px;
|
|
80
|
+
background: #a78bfa;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.fact {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: baseline;
|
|
86
|
+
gap: 24px;
|
|
87
|
+
}
|
|
88
|
+
.fact-number {
|
|
89
|
+
font-size: 64px;
|
|
90
|
+
font-weight: 800;
|
|
91
|
+
color: #a78bfa;
|
|
92
|
+
font-variant-numeric: tabular-nums;
|
|
93
|
+
min-width: 90px;
|
|
94
|
+
}
|
|
95
|
+
.fact-text {
|
|
96
|
+
font-size: 40px;
|
|
97
|
+
line-height: 1.3;
|
|
98
|
+
color: #c9c9da;
|
|
99
|
+
max-width: 740px;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.footer {
|
|
103
|
+
margin-top: 28px;
|
|
104
|
+
font-size: 30px;
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
color: #8d8da4;
|
|
107
|
+
letter-spacing: 0.04em;
|
|
108
|
+
}
|
|
109
|
+
</style>
|
|
110
|
+
</head>
|
|
111
|
+
<body>
|
|
112
|
+
|
|
113
|
+
<div data-composition-id="fact-short" data-width="1080" data-height="1920" data-start="0" data-duration="12">
|
|
114
|
+
<div class="glow"></div>
|
|
115
|
+
<div class="scene-content">
|
|
116
|
+
<div class="kicker">📡 Did you know</div>
|
|
117
|
+
<h1 class="headline">Sagittarius A* weighs 4.3 million suns</h1>
|
|
118
|
+
<div class="accent-bar"></div>
|
|
119
|
+
<div class="fact fact-1">
|
|
120
|
+
<span class="fact-number">01</span>
|
|
121
|
+
<span class="fact-text">It sits 26,000 light-years away at the center of our galaxy.</span>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="fact fact-2">
|
|
124
|
+
<span class="fact-number">02</span>
|
|
125
|
+
<span class="fact-text">First photographed in 2022 by the Event Horizon Telescope.</span>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="fact fact-3">
|
|
128
|
+
<span class="fact-number">03</span>
|
|
129
|
+
<span class="fact-text">The star S2 orbits it at 3% of the speed of light.</span>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="footer">yourname.4ort.net</div>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
|
136
|
+
<script>
|
|
137
|
+
// Built synchronously, paused, registered — the renderer drives it.
|
|
138
|
+
window.__timelines = window.__timelines || {};
|
|
139
|
+
const tl = gsap.timeline({ paused: true });
|
|
140
|
+
|
|
141
|
+
// Entrances — varied eases, first tween offset past t=0.
|
|
142
|
+
tl.from(".kicker", { y: -30, opacity: 0, duration: 0.5, ease: "power2.out" }, 0.2);
|
|
143
|
+
tl.from(".headline", { y: 60, opacity: 0, duration: 0.8, ease: "power3.out" }, 0.4);
|
|
144
|
+
tl.from(".accent-bar", { scaleX: 0, transformOrigin: "left center", duration: 0.6, ease: "expo.out" }, 0.9);
|
|
145
|
+
tl.from(".fact-1", { x: -50, opacity: 0, duration: 0.6, ease: "back.out(1.4)" }, 1.2);
|
|
146
|
+
tl.from(".fact-2", { x: -50, opacity: 0, duration: 0.6, ease: "back.out(1.4)" }, 1.5);
|
|
147
|
+
tl.from(".fact-3", { x: -50, opacity: 0, duration: 0.6, ease: "back.out(1.4)" }, 1.8);
|
|
148
|
+
tl.from(".footer", { opacity: 0, duration: 0.6, ease: "power1.out" }, 2.4);
|
|
149
|
+
|
|
150
|
+
// Ambient pulse on the accent bar — FINITE repeats sized to the 12s duration.
|
|
151
|
+
tl.to(".accent-bar", { opacity: 0.55, duration: 1.0, ease: "sine.inOut", repeat: 7, yoyo: true }, 3.0);
|
|
152
|
+
|
|
153
|
+
// Final-scene fade out (allowed only on the last scene — this is a one-scene short).
|
|
154
|
+
tl.to('[data-composition-id="fact-short"] .scene-content, [data-composition-id="fact-short"] .glow', { opacity: 0, duration: 0.8, ease: "power2.in" }, 11.0);
|
|
155
|
+
|
|
156
|
+
window.__timelines["fact-short"] = tl;
|
|
157
|
+
</script>
|
|
158
|
+
|
|
159
|
+
</body>
|
|
160
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@4ort/cli",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "Unified CLI for the 4ort ecosystem
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Unified CLI for the 4ort ecosystem \u2014 4ort.net hosting, knowledge graph, and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"4ort": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
-
"README.md"
|
|
11
|
+
"README.md",
|
|
12
|
+
"examples"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
15
|
"dev": "tsx src/index.ts",
|