Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8e0081c
feat: add autoscroll video showcase, replace "Run it three ways"
AdrianLlopart Jun 18, 2026
b8f5509
fix(showcase): inline status in top bar, de-dupe carousel, randomize …
AdrianLlopart Jun 18, 2026
11a3ef7
perf(showcase): lazy-load clips, play only while visible
AdrianLlopart Jun 18, 2026
df36a3f
feat(showcase): host clips on HF dataset, two-tier preview/full
AdrianLlopart Jun 18, 2026
0979b6c
docs: document showcase video workflow in README
AdrianLlopart Jun 18, 2026
a579d6b
fix(showcase): move SUCCESS/FAIL pill to bottom-right
AdrianLlopart Jun 18, 2026
5eea199
refactor: reorder sections — problem before architecture, showcase be…
AdrianLlopart Jun 18, 2026
3fde1b0
fix(solve): left-align robotics-landscape.diff with the install console
AdrianLlopart Jun 18, 2026
8851770
Merge pull request #11 from OpenRAL/feat/video-showcase
AdrianLlopart Jun 18, 2026
c98bc3a
feat: extend hero terminal to full Coca-Cola fetch scenario
claude Jun 19, 2026
c7c2df3
feat: add continuous detection, spatial memory recall, clarify RSkill…
claude Jun 19, 2026
6623a3b
feat: give open_door/close_door their own RSkill chip, update fridge …
claude Jun 19, 2026
6348020
feat: add close_door as its own RSkill chip
claude Jun 19, 2026
a4c1f70
Merge pull request #12 from OpenRAL/claude/hero-terminal-steps-0jo1br
AdrianLlopart Jun 19, 2026
ce8ed90
feat(dashboard): add annotated "Mission control" section
AdrianLlopart Jun 19, 2026
2924e9e
feat(dashboard): play the walkthrough video in the console
AdrianLlopart Jun 19, 2026
0f2e940
feat(dashboard): trim intro, green LIVE dot, drop expand/lightbox
AdrianLlopart Jun 19, 2026
3ab5065
fix(live): white "LIVE" label with green blinking dot; update DESIGN.md
AdrianLlopart Jun 19, 2026
29e70d5
feat(contact): expand "This is about" options, theme the dropdown
AdrianLlopart Jun 19, 2026
8f9521d
feat(contact): replace native select with a custom ARIA listbox
AdrianLlopart Jun 19, 2026
793c0b2
chore(footer): drop "Apache-2.0" from License link and copyright line
AdrianLlopart Jun 19, 2026
490491e
Merge pull request #13 from OpenRAL/feat/show_dashboard
AdrianLlopart Jun 19, 2026
729778c
Install Vercel Speed Insights
vercel[bot] Jun 19, 2026
00ed81f
Merge pull request #14 from OpenRAL/vercel/install-vercel-speed-insig…
AdrianLlopart Jun 20, 2026
d0a0c24
feat(media): point manifest at 19 benchmark + 4 simulation clips
AdrianLlopart Jun 20, 2026
536ebc0
feat(media): add 2 deployment clips (sim+dashboard side-by-side)
AdrianLlopart Jun 20, 2026
df1ee1b
chore(media): rename deployment clips
AdrianLlopart Jun 20, 2026
fe9148d
fix(showcase): uniform right-to-left scroll + aspect-fit hi-res modal
claude Jun 20, 2026
cc5ce8b
Merge pull request #15 from OpenRAL/claude/see-it-run-video-rtl-hires…
AdrianLlopart Jun 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@ node_modules/
*.log
dist/

# Local video sources & encoded outputs — hosted on HF, never committed.
# (Drop raw clips in media/, run `npm run media`; only manifest.json is tracked.)
media/
media-dist/

# Claude Code worktrees and local state
.claude/
20 changes: 13 additions & 7 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,16 @@ white** used sparingly.
- **White Line** `rgba(255,255,255,0.22)` (`--accent-line`) — emphasized 1px
borders (active nodes, tabs, pills).

### Status — the only permitted non-neutral
- **Success / Live** → **white** (`--green` is `#FFFFFF`). The "LIVE" dot, the
`✓` ticks, a sent-message confirmation are all white. No green.
### Status — the only permitted non-neutrals
- **Live** → a **green blinking dot** (`--live` `#4FB58B`, the live / open-source
signal) paired with the word **"LIVE" set in white**. The pulsing green dot is
a sanctioned status light — it reads as "the system is running." Everything
around it stays monochrome: the **"LIVE" label itself is white** (never green),
as are the `✓` ticks and a sent-message confirmation.
- **Error** `#D98A8E` (`--red`) — **form-validation errors only**, paired with
text and an invalid border. This desaturated rose is the *single* sanctioned
chroma in the system, and it must never appear decoratively.
text and an invalid border. This desaturated rose and the green live-dot are
the *only two* sanctioned chromas in the system; neither may ever appear
decoratively.

**Banned:** any colored accent (the old clay/orange and cyan are gone for good),
purple/blue "AI neon," outer-glow shadows, gradient text, pure `#000000`.
Expand Down Expand Up @@ -199,8 +203,10 @@ Universal AI tells **and** OpenRAL-specific bans:

- **No colored accent of any kind.** No clay/orange, no cyan, no purple/blue AI
neon, no gradient text. Emphasis is white + weight + opacity, period.
- **No green/red as decoration.** Success and "live" are white; the lone
desaturated `--red` is reserved for form errors paired with text.
- **No green/red as decoration.** The only sanctioned chromas are the **green
blinking live-dot** (`--live`, always paired with a *white* "LIVE" label) and
the desaturated `--red` for form errors paired with text. Success ticks and
confirmations stay white; never use green for text, fills or borders.
- No outer-glow / neon shadows (CTA shadows are dark, not white halos).
- No pure black `#000000` — the canvas is Ink `#0E0F13`.
- No emojis as UI — SVG icons only (GitHub / Hugging Face / Discord marks,
Expand Down
37 changes: 34 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,40 @@ perception and reasoning into safe, runnable robot behavior.

## Sections

Hero (floating L0–L7 layer stack) → **architecture diagram** (Helix-style dual-system
S1 ⇄ S2 flow) → what it solves → capabilities → **terminal install** (`curl` installer) →
rSkills → team → contact → footer (GitHub · Hugging Face · Discord).
Hero (floating L0–L7 layer stack) → **terminal install** (`curl` installer) →
what it solves → **architecture diagram** (Helix-style dual-system S1 ⇄ S2 flow) →
capabilities → rSkills → **showcase** (autoscrolling benchmark / simulation /
deployment clips) → contact → footer (GitHub · Hugging Face · Discord).

## Showcase videos

The **"See it run"** section is an autoscrolling strip of benchmark, simulation
and deployment clips. Videos are **not** committed to this repo — they're hosted
on the public [`OpenRAL/website-media`](https://huggingface.co/datasets/OpenRAL/website-media)
Hugging Face dataset (CDN-backed) and listed in `src/videos/manifest.json`.

**To make a video show up on the site:**

```bash
# 1. Drop the raw clip (any size/format) into the gitignored media/ folder.
# The sub-folder picks the tab; the filename fills the on-clip labels:
# <benchmark>_<rskill>_<success|fail>.<ext>
media/benchmarks/libero-spatial_pi05_success.mp4
media/simulation/warehouse-pick_rtdetr-v2_fail.mp4
media/deployment/franka-stack_qwen35_success.mp4

# 2. Encode (poster + square preview + full clip), upload to HF, refresh manifest:
npm run media

# 3. Commit the updated src/videos/manifest.json — that's the only tracked change.
git add src/videos/manifest.json && git commit -m "Add showcase clip"
```

Use hyphens *inside* a name (`libero-spatial`); underscores only separate the
three parts, and the last must be `success` or `fail`. Adding clips needs
`ffmpeg` and the `hf` CLI signed in with write access to the `OpenRAL` org
(`hf auth whoami`); `npm run media -- --no-upload` encodes + updates the
manifest locally without publishing. Full reference: [`src/videos/README.md`](./src/videos/README.md).

## Local preview

Expand Down
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"media": "node scripts/build-media.mjs"
},
"dependencies": {
"@vercel/analytics": "^2.0.1",
"@vercel/speed-insights": "^2.0.0",
"framer-motion": "^11.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
Expand Down
Binary file added public/assets/dashboard-navigation.webm
Binary file not shown.
Binary file added public/assets/dashboard-view.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
133 changes: 133 additions & 0 deletions scripts/build-media.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env node
/* ------------------------------------------------------------------
build-media.mjs — encode + upload showcase clips, refresh manifest.

Workflow:
1. Drop raw clips into media/<category>/<benchmark>_<rskill>_<success|fail>.<ext>
categories: benchmarks | simulation | deployment
2. Run: npm run media
→ ffmpeg encodes each clip into three web assets:
poster.jpg small first-frame thumbnail
preview.mp4 square 640px, muted, compressed — the autoscroll strip
full.mp4 capped 1080p, with audio — the click-to-expand modal
→ uploads them to the OpenRAL/website-media HF dataset (public)
→ writes src/videos/manifest.json (the only tracked artifact)

Raw clips and encoded outputs are gitignored; the website loads every
clip from the HF CDN, so nothing heavy ever touches the repo or bundle.

Flags:
--no-upload encode + write manifest only (skip the HF push)
------------------------------------------------------------------ */
import { execFileSync } from "node:child_process";
import { readdirSync, mkdirSync, writeFileSync, existsSync, statSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";

const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
const SRC = join(ROOT, "media");
const OUT = join(ROOT, "media-dist");
const MANIFEST = join(ROOT, "src", "videos", "manifest.json");

const REPO = "OpenRAL/website-media";
const BASE = `https://huggingface.co/datasets/${REPO}/resolve/main`;
const CATEGORIES = ["benchmarks", "simulation", "deployment"];
const VIDEO_RE = /\.(mp4|mov|webm|m4v|mkv)$/i;
const noUpload = process.argv.includes("--no-upload");

function sh(cmd, args) {
return execFileSync(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
}

// <benchmark>_<rskill>_<success|fail> — hyphens inside names, underscores separate.
function parseName(file) {
const base = file.replace(/\.[^.]+$/, "");
const parts = base.split("_");
const tail = parts[parts.length - 1] || "";
const status = /^succ/i.test(tail) ? "success" : /^fail/i.test(tail) ? "fail" : null;
const benchmark = parts[0] || base;
const rskill = parts.slice(1, status ? -1 : undefined).join("_") || "—";
return { base, benchmark, rskill, status };
}

function encode(input, dir, category) {
mkdirSync(dir, { recursive: true });
const preview = join(dir, "preview.mp4");
const full = join(dir, "full.mp4");
const poster = join(dir, "poster.jpg");

// strip preview: 640px square, muted, web-optimised.
// benchmarks/simulation are center-cropped to a square; deployment clips are
// wide side-by-side (sim | dashboard) composites, so a center crop would only
// show the seam — letterbox the whole frame into the square instead.
const previewVf = category === "deployment"
? "scale=640:-2:flags=lanczos,pad=640:640:(ow-iw)/2:(oh-ih)/2:color=black,fps=30"
: "crop='min(iw,ih)':'min(iw,ih)',scale=640:640:flags=lanczos,fps=30";
sh("ffmpeg", ["-y", "-i", input,
"-vf", previewVf,
"-an", "-c:v", "libx264", "-profile:v", "main", "-pix_fmt", "yuv420p",
"-crf", "28", "-preset", "veryfast", "-movflags", "+faststart", preview]);

// full clip: native aspect, capped at 1080p, keep audio
sh("ffmpeg", ["-y", "-i", input,
"-vf", "scale='min(1920,iw)':'-2':force_original_aspect_ratio=decrease,scale='-2':'min(1080,ih)'",
"-c:v", "libx264", "-profile:v", "high", "-pix_fmt", "yuv420p",
"-crf", "23", "-preset", "medium", "-c:a", "aac", "-b:a", "128k",
"-movflags", "+faststart", full]);

// poster: one frame from the square preview
sh("ffmpeg", ["-y", "-ss", "0.3", "-i", preview, "-frames:v", "1", "-q:v", "3", poster]);

const kb = (p) => Math.round(statSync(p).size / 1024);
return { preview, full, poster, sizes: { preview: kb(preview), full: kb(full), poster: kb(poster) } };
}

if (!existsSync(SRC)) {
console.error(`No media/ folder. Create media/<category>/ and drop clips in.`);
process.exit(1);
}

const clips = [];
let count = 0;
for (const category of CATEGORIES) {
const dir = join(SRC, category);
if (!existsSync(dir)) continue;
for (const file of readdirSync(dir).sort()) {
if (!VIDEO_RE.test(file)) continue;
const { base, benchmark, rskill, status } = parseName(file);
if (!status) {
console.warn(`⚠ skip ${category}/${file} — name must end in _success or _fail`);
continue;
}
const id = `${category}/${base}`;
process.stdout.write(`• ${id} … `);
const { sizes } = encode(join(dir, file), join(OUT, id), category);
console.log(`poster ${sizes.poster}kB · preview ${sizes.preview}kB · full ${sizes.full}kB`);
clips.push({
id, category, benchmark, rskill, status,
poster: `${id}/poster.jpg`,
preview: `${id}/preview.mp4`,
full: `${id}/full.mp4`,
});
count++;
}
}

if (!count) {
console.error("No valid clips found in media/. Nothing to do.");
process.exit(1);
}

writeFileSync(MANIFEST, JSON.stringify({ base: BASE, clips }, null, 2) + "\n");
console.log(`\n✓ wrote ${MANIFEST} (${count} clip${count > 1 ? "s" : ""})`);

if (noUpload) {
console.log("↷ --no-upload: skipped HF push.");
process.exit(0);
}

console.log(`↑ uploading media-dist → ${REPO} …`);
execFileSync("hf", ["upload", REPO, "media-dist", ".", "--type", "dataset",
"--commit-message", `Add ${count} showcase clip asset(s)`],
{ stdio: "inherit", cwd: ROOT });
console.log(`✓ done — ${count} clip(s) live on the HF CDN.`);
9 changes: 8 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/react";
import Nav from "./components/Nav.jsx";
import Hero from "./components/Hero.jsx";
import Terminal from "./components/Terminal.jsx";
import ArchitectureDiagram from "./components/ArchitectureDiagram.jsx";
import Solve from "./components/Solve.jsx";
import Capabilities from "./components/Capabilities.jsx";
import RSkills from "./components/RSkills.jsx";
import VideoShowcase from "./components/VideoShowcase.jsx";
import Dashboard from "./components/Dashboard.jsx";
import Contact from "./components/Contact.jsx";
import Footer from "./components/Footer.jsx";
import Privacy from "./components/Privacy.jsx";
Expand All @@ -18,6 +21,7 @@ export default function App() {
<>
<Privacy />
<Analytics />
<SpeedInsights />
</>
);

Expand All @@ -28,15 +32,18 @@ export default function App() {
<main id="top">
<Hero />
<Terminal />
<ArchitectureDiagram />
<Solve />
<ArchitectureDiagram />
<Capabilities />
<RSkills />
<VideoShowcase />
<Dashboard />
<Contact />
</main>
<Footer />
<CookieNotice />
<Analytics />
<SpeedInsights />
</>
);
}
2 changes: 1 addition & 1 deletion src/components/AgentConsole.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.1em;
color: var(--live);
color: #fff;
display: flex;
align-items: center;
gap: 7px;
Expand Down
Loading
Loading