Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 8 additions & 12 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
- 'pages/**'
- '.github/workflows/pages.yml'
- 'docs/**'
- 'scripts/verify-website.py'

concurrency:
group: pages
Expand Down Expand Up @@ -39,20 +40,12 @@ jobs:
cp -R pages/. site/
fi

if [ -f docs/loom-demo-thumbnail.png ]; then
cp docs/loom-demo-thumbnail.png site/docs/
fi

for f in docs/menu-navigation-*.png; do
if [ -f "$f" ]; then
cp "$f" site/docs/
fi
# Current, audited product captures and accessible trailer captions.
for asset in docs/menu-navigation-*.png docs/widget-showcase.png docs/loom-2.0-poster.png docs/loom-2.0-notifications.png docs/loom-2.0-captions.vtt; do
test -s "$asset"
cp "$asset" site/docs/
done

if [ -f docs/widget-showcase.png ]; then
cp docs/widget-showcase.png site/docs/
fi

if [ -f Resources/LoomIconMaster.png ]; then
cp Resources/LoomIconMaster.png site/Resources/
fi
Expand Down Expand Up @@ -150,6 +143,9 @@ jobs:
echo "Verified asset: ${asset} ($(wc -c < "${asset}" | tr -d ' ') bytes)"
done

- name: Verify website references
run: python3 scripts/verify-website.py site

- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
Expand Down
242 changes: 52 additions & 190 deletions README.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/DEMO_MEDIA.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ Each demo alert is delayed by three seconds and requires macOS notification auth
MacBook Pro photo mockup: [Plinth, Front / Silver](https://plinthmockups.com/?scene=macbook-11-silver). Commercial exports are permitted without credit; see [Plinth mockup terms](https://plinthmockups.com/macbook-mockup). The blank scene is not redistributed. The computer frame is for presentation only.

Notification banners are genuine user-provided macOS captures from 24 October 2026, cropped without changing their content. The trailer's session and quota data are illustrative demo content.

## Website and README captures

The current Sessions, Usage, Storage and widget images are the same audited native 2.0 captures used in the trailer. The [notification examples](loom-2.0-notifications.png) are genuine macOS banners captured from the explicit demo scenarios; their values are illustrative. The website includes an optional [English caption track](loom-2.0-captions.vtt). The film already contains visible subtitles, so this extra track is off by default to avoid duplicate text.
52 changes: 52 additions & 0 deletions docs/loom-2.0-captions.vtt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
WEBVTT

00:00:00.000 --> 00:00:01.899
Codex is running tests.

00:00:02.199 --> 00:00:03.884
Claude is writing code.

00:00:04.184 --> 00:00:07.299
Antigravity is working on another project.

00:00:08.099 --> 00:00:11.832
But one's been waiting for you. And you don't even know which one.

00:00:12.132 --> 00:00:13.305
Meet Loom.

00:00:13.605 --> 00:00:18.384
One place to see what your AI coding agents are doing on your Mac.

00:00:18.796 --> 00:00:21.228
Every project. Every session.

00:00:21.528 --> 00:00:25.560
Working. Waiting. Idle. Finished.

00:00:25.972 --> 00:00:27.444
See what's happening.

00:00:27.744 --> 00:00:29.643
Know what needs your attention.

00:00:29.943 --> 00:00:32.055
And get right back to what matters.

00:00:32.355 --> 00:00:35.150
Get alerted before your quota runs out.

00:00:36.407 --> 00:00:38.284
See where your storage goes.

00:00:38.584 --> 00:00:41.848
Keep everything in view with native Mac widgets.

00:00:42.760 --> 00:00:45.341
No cloud account. Just your Mac.

00:00:45.641 --> 00:00:50.441
Codex. Claude Code. Antigravity. Three agents. One clear view.

00:00:50.803 --> 00:00:53.000
Loom. Your agents, at a glance.
Binary file added docs/loom-2.0-notifications.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
674 changes: 82 additions & 592 deletions pages/index.html

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions pages/site.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict';
const copyButton = document.querySelector('#copy-brew');
const command = document.querySelector('#brew-command');
const copyStatus = document.querySelector('#copy-status');
copyButton.addEventListener('click', async () => {
const text = command.textContent;
// Copy within the user gesture first. Some embedded browsers leave the
// asynchronous Clipboard API permission request unresolved indefinitely.
const field = document.createElement('textarea');
field.value = text;
field.setAttribute('readonly', '');
field.style.position = 'fixed';
field.style.top = '-9999px';
document.body.append(field);
field.select();
let copied = false;
try { copied = document.execCommand('copy'); } catch (_) { copied = false; }
field.remove();
copyButton.focus();
if (!copied && navigator.clipboard && window.isSecureContext) {
try {
copied = await Promise.race([
navigator.clipboard.writeText(text).then(() => true),
new Promise(resolve => setTimeout(() => resolve(false), 1200))
]);
} catch (_) { copied = false; }
}
copyStatus.textContent = copied ? 'Homebrew command copied.' : 'Select the command above and copy it manually.';
if (!copied) {
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(command);
selection.removeAllRanges();
selection.addRange(range);
command.focus();
}
});
const dialog = document.querySelector('#image-dialog');
let imageTrigger;
if (typeof dialog.showModal === 'function') {
document.querySelectorAll('[data-lightbox]').forEach(link => {
link.addEventListener('click', event => {
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
imageTrigger = link;
const image = link.querySelector('img');
document.querySelector('#dialog-image').src = link.href;
document.querySelector('#dialog-image').alt = image.alt;
document.querySelector('#dialog-caption').textContent = image.alt;
document.querySelector('#dialog-original').href = link.href;
dialog.showModal();
});
});
dialog.querySelector('.dialog-close').addEventListener('click', () => dialog.close());
dialog.addEventListener('click', event => { if (event.target === dialog) {
const rect = dialog.getBoundingClientRect();
if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) dialog.close();
} });
dialog.addEventListener('close', () => { if (imageTrigger) imageTrigger.focus(); });
}
Loading
Loading