diff --git a/astro.config.mjs b/astro.config.mjs
index 8c0cf0b4..65681089 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -280,7 +280,11 @@ Developer & Agent Interfaces:
pageSeparator: llmsPageSeparator,
// Strip heading anchor links from llms-full.txt and llms-small.txt
// (see src/utils/heading-anchor.ts).
- customSelectors: { all: [HEADING_ANCHOR_LINK_SELECTOR] },
+ customSelectors: {
+ all: [HEADING_ANCHOR_LINK_SELECTOR],
+ // Video links are no use in the minified bundle.
+ small: ['.demo-video'],
+ },
// `exclude` only affects `llms-small.txt`, and `demote` lines
// unlisted pages up for `stripUnlistedFromLlmsFull`.
exclude: [...unlistedPages],
diff --git a/public/_headers b/public/_headers
index f36bc400..5d351f1b 100644
--- a/public/_headers
+++ b/public/_headers
@@ -66,3 +66,7 @@
/humans.txt
Content-Type: text/plain; charset=utf-8
Access-Control-Allow-Origin: *
+
+# Demo videos and their posters. Cached for a week, so a re-export shows up within that.
+/videos/*
+ Cache-Control: public, max-age=604800
diff --git a/public/_routes.json b/public/_routes.json
new file mode 100644
index 00000000..635ad384
--- /dev/null
+++ b/public/_routes.json
@@ -0,0 +1,5 @@
+{
+ "version": 1,
+ "include": ["/*"],
+ "exclude": ["/videos/*"]
+}
diff --git a/public/videos/create-api-key.jpg b/public/videos/create-api-key.jpg
new file mode 100644
index 00000000..b9523557
Binary files /dev/null and b/public/videos/create-api-key.jpg differ
diff --git a/public/videos/create-api-key.mp4 b/public/videos/create-api-key.mp4
new file mode 100644
index 00000000..3d04edc8
Binary files /dev/null and b/public/videos/create-api-key.mp4 differ
diff --git a/public/videos/create-flutter-project.jpg b/public/videos/create-flutter-project.jpg
new file mode 100644
index 00000000..b81c8f65
Binary files /dev/null and b/public/videos/create-flutter-project.jpg differ
diff --git a/public/videos/create-flutter-project.mp4 b/public/videos/create-flutter-project.mp4
new file mode 100644
index 00000000..7ede5523
Binary files /dev/null and b/public/videos/create-flutter-project.mp4 differ
diff --git a/public/videos/create-release.jpg b/public/videos/create-release.jpg
new file mode 100644
index 00000000..ca494808
Binary files /dev/null and b/public/videos/create-release.jpg differ
diff --git a/public/videos/create-release.mp4 b/public/videos/create-release.mp4
new file mode 100644
index 00000000..1bec74db
Binary files /dev/null and b/public/videos/create-release.mp4 differ
diff --git a/public/videos/delete-release.jpg b/public/videos/delete-release.jpg
new file mode 100644
index 00000000..ce9edcec
Binary files /dev/null and b/public/videos/delete-release.jpg differ
diff --git a/public/videos/delete-release.mp4 b/public/videos/delete-release.mp4
new file mode 100644
index 00000000..a078f8de
Binary files /dev/null and b/public/videos/delete-release.mp4 differ
diff --git a/public/videos/getting-started.jpg b/public/videos/getting-started.jpg
new file mode 100644
index 00000000..12c9562a
Binary files /dev/null and b/public/videos/getting-started.jpg differ
diff --git a/public/videos/getting-started.mp4 b/public/videos/getting-started.mp4
new file mode 100644
index 00000000..4126ff90
Binary files /dev/null and b/public/videos/getting-started.mp4 differ
diff --git a/public/videos/initialize-shorebird.jpg b/public/videos/initialize-shorebird.jpg
new file mode 100644
index 00000000..39554eba
Binary files /dev/null and b/public/videos/initialize-shorebird.jpg differ
diff --git a/public/videos/initialize-shorebird.mp4 b/public/videos/initialize-shorebird.mp4
new file mode 100644
index 00000000..874cbe13
Binary files /dev/null and b/public/videos/initialize-shorebird.mp4 differ
diff --git a/public/videos/manage-org-collaborators.jpg b/public/videos/manage-org-collaborators.jpg
new file mode 100644
index 00000000..d2b1f28a
Binary files /dev/null and b/public/videos/manage-org-collaborators.jpg differ
diff --git a/public/videos/manage-org-collaborators.mp4 b/public/videos/manage-org-collaborators.mp4
new file mode 100644
index 00000000..2d404c92
Binary files /dev/null and b/public/videos/manage-org-collaborators.mp4 differ
diff --git a/public/videos/rollback-patch.jpg b/public/videos/rollback-patch.jpg
new file mode 100644
index 00000000..35b51b34
Binary files /dev/null and b/public/videos/rollback-patch.jpg differ
diff --git a/public/videos/rollback-patch.mp4 b/public/videos/rollback-patch.mp4
new file mode 100644
index 00000000..18717fc7
Binary files /dev/null and b/public/videos/rollback-patch.mp4 differ
diff --git a/public/videos/send-ota-update.jpg b/public/videos/send-ota-update.jpg
new file mode 100644
index 00000000..239b45f4
Binary files /dev/null and b/public/videos/send-ota-update.jpg differ
diff --git a/public/videos/send-ota-update.mp4 b/public/videos/send-ota-update.mp4
new file mode 100644
index 00000000..a4184060
Binary files /dev/null and b/public/videos/send-ota-update.mp4 differ
diff --git a/public/videos/staging-patch.jpg b/public/videos/staging-patch.jpg
new file mode 100644
index 00000000..f2f23370
Binary files /dev/null and b/public/videos/staging-patch.jpg differ
diff --git a/public/videos/staging-patch.mp4 b/public/videos/staging-patch.mp4
new file mode 100644
index 00000000..a0643e52
Binary files /dev/null and b/public/videos/staging-patch.mp4 differ
diff --git a/public/videos/update-billing-contact.jpg b/public/videos/update-billing-contact.jpg
new file mode 100644
index 00000000..f02ba7b1
Binary files /dev/null and b/public/videos/update-billing-contact.jpg differ
diff --git a/public/videos/update-billing-contact.mp4 b/public/videos/update-billing-contact.mp4
new file mode 100644
index 00000000..a53f4863
Binary files /dev/null and b/public/videos/update-billing-contact.mp4 differ
diff --git a/public/videos/view-releases.jpg b/public/videos/view-releases.jpg
new file mode 100644
index 00000000..7b7815e0
Binary files /dev/null and b/public/videos/view-releases.jpg differ
diff --git a/public/videos/view-releases.mp4 b/public/videos/view-releases.mp4
new file mode 100644
index 00000000..b8bdd79d
Binary files /dev/null and b/public/videos/view-releases.mp4 differ
diff --git a/src/components/ArcadeEmbed.astro b/src/components/ArcadeEmbed.astro
deleted file mode 100644
index 5e3dc4b4..00000000
--- a/src/components/ArcadeEmbed.astro
+++ /dev/null
@@ -1,37 +0,0 @@
----
-interface Props {
- src: string;
- title: string;
-}
-
-const { src, title } = Astro.props;
----
-
-
-
-
-
-
diff --git a/src/components/DemoVideo.astro b/src/components/DemoVideo.astro
new file mode 100644
index 00000000..218bc3a2
--- /dev/null
+++ b/src/components/DemoVideo.astro
@@ -0,0 +1,74 @@
+---
+import { existsSync } from 'node:fs';
+import { fileURLToPath } from 'node:url';
+import { publicDir } from 'astro:config/server';
+import sharp from 'sharp';
+
+interface Props {
+ /** File name (without extension) of the video in `public/videos/`. */
+ name: string;
+ title: string;
+}
+
+const { name, title } = Astro.props;
+
+// Keep `name` URL-safe so the file checked below is the one that's served.
+if (!/^[a-z0-9-]+$/.test(name)) {
+ throw new Error(`DemoVideo: name "${name}" must be lowercase kebab-case`);
+}
+
+const src = `/videos/${name}.mp4`;
+const poster = `/videos/${name}.jpg`;
+
+const fileIn = (file: string) => new URL(`.${file}`, publicDir);
+
+// Fail the build on a missing video or poster instead of shipping a player
+// that 404s.
+for (const file of [src, poster]) {
+ if (!existsSync(fileIn(file))) {
+ throw new Error(`DemoVideo: public${file} does not exist`);
+ }
+}
+
+// The poster is a frame of the video, so its size reserves the right box
+// before anything loads and the page doesn't jump.
+const { width, height } = await sharp(
+ fileURLToPath(fileIn(poster)),
+).metadata();
+---
+
+
+
+ Watch the video: {title}
+
+
+
diff --git a/src/content/docs/account/api-keys.mdx b/src/content/docs/account/api-keys.mdx
index be9352a5..cf54a7e1 100644
--- a/src/content/docs/account/api-keys.mdx
+++ b/src/content/docs/account/api-keys.mdx
@@ -5,7 +5,7 @@ sidebar:
order: 4
---
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
API keys let you authenticate with Shorebird from CI systems and other automated
environments. You can create, view, and revoke API keys from the
@@ -19,10 +19,7 @@ allows.
## Creating an API key
-
+
1. Open **Account → API Keys** in the console.
2. Click **Create API Key**.
diff --git a/src/content/docs/account/billing.mdx b/src/content/docs/account/billing.mdx
index c06b622d..6fb25460 100644
--- a/src/content/docs/account/billing.mdx
+++ b/src/content/docs/account/billing.mdx
@@ -6,7 +6,7 @@ sidebar:
---
import { Image } from 'astro:assets';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
import viewBillingPortal from '~/assets/view_billing_portal.png';
import accountMonthlySpendingLimit from '~/assets/account_monthly_spending_limit.png';
import setSpendingLimitDialog from '~/assets/set_spending_limit_dialog.png';
@@ -32,10 +32,7 @@ same, but you can change them to be different.
If you'd like invoices sent to a different email address than the one you use to
log in, you can change this in Stripe:
-
+
1. Navigate to your "Account" panel within Shorebird.
2. Click on the drop-down menu on the right side.
diff --git a/src/content/docs/account/orgs.mdx b/src/content/docs/account/orgs.mdx
index fdf3c18d..f350618c 100644
--- a/src/content/docs/account/orgs.mdx
+++ b/src/content/docs/account/orgs.mdx
@@ -6,7 +6,7 @@ sidebar:
---
import { Image } from 'astro:assets';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
import addMemberToOrg from '~/assets/add_member_to_org.png';
import completedAddMemberToOrg from '~/assets/completed_add_member_to_org.png';
import transferAppToDifferentOrg from '~/assets/transfer_app_to_different_org.png';
@@ -83,9 +83,9 @@ You can also transfer an app from the command line with
### Add a member
-
To add one or more members to your organization, visit the organization's
diff --git a/src/content/docs/code-push/ci/_authentication.mdx b/src/content/docs/code-push/ci/_authentication.mdx
index 29e2f8f2..a32d5205 100644
--- a/src/content/docs/code-push/ci/_authentication.mdx
+++ b/src/content/docs/code-push/ci/_authentication.mdx
@@ -1,13 +1,10 @@
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
Most Shorebird functionality, like creating releases and patches, requires
authentication. To authenticate in your CI, create an API key from the
[Shorebird Console](https://console.shorebird.dev):
-
+
1. Go to **Account → API Keys**.
2. Click **Create API Key**.
diff --git a/src/content/docs/code-push/create.mdx b/src/content/docs/code-push/create.mdx
index b386e389..c83b3768 100644
--- a/src/content/docs/code-push/create.mdx
+++ b/src/content/docs/code-push/create.mdx
@@ -6,7 +6,7 @@ sidebar:
order: 2
---
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
:::note
@@ -21,9 +21,9 @@ To create a new Flutter project with Shorebird, use `shorebird create`:
shorebird create my_app
```
-
This does several things:
diff --git a/src/content/docs/code-push/guides/staging-patches.mdx b/src/content/docs/code-push/guides/staging-patches.mdx
index 502281b4..70cab96a 100644
--- a/src/content/docs/code-push/guides/staging-patches.mdx
+++ b/src/content/docs/code-push/guides/staging-patches.mdx
@@ -9,12 +9,9 @@ import { CodeTabs, LinkCard } from 'starlight-theme-nova/components';
import { Image } from 'astro:assets';
import goLive from '~/assets/staging_patches_change_track_dropdown.png';
import switchTrack from '~/assets/staging_patches_patch_context_menu.png';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
-
+
This guide will walk you through how to validate a patch in Shorebird's staging
environment before promoting the patch to production.
diff --git a/src/content/docs/code-push/index.mdx b/src/content/docs/code-push/index.mdx
index ec8ca35d..efb71401 100644
--- a/src/content/docs/code-push/index.mdx
+++ b/src/content/docs/code-push/index.mdx
@@ -6,13 +6,13 @@ sidebar:
order: 1
---
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
For a quick overview, check out the demo below.
-
## What is Code Push?
diff --git a/src/content/docs/code-push/initialize.mdx b/src/content/docs/code-push/initialize.mdx
index 22f57b8e..960594a0 100644
--- a/src/content/docs/code-push/initialize.mdx
+++ b/src/content/docs/code-push/initialize.mdx
@@ -7,7 +7,7 @@ sidebar:
---
import { LinkCard } from 'starlight-theme-nova/components';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
:::note
@@ -17,9 +17,9 @@ Shorebird.
:::
-
To configure an existing Flutter project to use Shorebird, use `shorebird init`
diff --git a/src/content/docs/code-push/release.mdx b/src/content/docs/code-push/release.mdx
index 7e07bedc..76054343 100644
--- a/src/content/docs/code-push/release.mdx
+++ b/src/content/docs/code-push/release.mdx
@@ -9,7 +9,7 @@ sidebar:
{/* cspell:words armeabi abiFilters v7a */}
import { Tabs, TabItem } from '@astrojs/starlight/components';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
import { LinkCard } from 'starlight-theme-nova/components';
import { Image } from 'astro:assets';
import releaseDeleteDialog from '~/assets/release_delete_dialog.png';
@@ -17,10 +17,7 @@ import listReleases from '~/assets/list_releases.png';
In order to start pushing updates, you will need to create a release.
-
+
`shorebird release` is a drop-in replacement for `flutter build`. It builds your
app and uploads the compiled Dart artifacts to Shorebird's servers as a baseline
@@ -488,9 +485,9 @@ you can manage your app's releases directly from the command line using the
### List releases
-
#### Via the Shorebird CLI
@@ -546,10 +543,7 @@ afterwards, use `--target-platform` as described in
### Delete releases
-
+
:::caution[Deleting a release is permanent]
diff --git a/src/content/docs/code-push/rollback.mdx b/src/content/docs/code-push/rollback.mdx
index 89abf039..8f70dc7e 100644
--- a/src/content/docs/code-push/rollback.mdx
+++ b/src/content/docs/code-push/rollback.mdx
@@ -8,7 +8,7 @@ sidebar:
import { LinkCard } from 'starlight-theme-nova/components';
import { Image } from 'astro:assets';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
import rollbackButton from '~/assets/rollback_button.png';
import rollbackPatch2Active from '~/assets/rollback_patch2_active.png';
import rollbackPatch2RolledBack from '~/assets/rollback_patch2_rolled_back.png';
@@ -46,10 +46,7 @@ Roll back requires a minimum Flutter version of 3.27.4.
:::
-
+
## Active and superseded patches
diff --git a/src/content/docs/code-push/tracks.mdx b/src/content/docs/code-push/tracks.mdx
index 5ff2b11d..df6994fb 100644
--- a/src/content/docs/code-push/tracks.mdx
+++ b/src/content/docs/code-push/tracks.mdx
@@ -8,7 +8,7 @@ sidebar:
---
import { CodeTabs, LinkCard } from 'starlight-theme-nova/components';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
**Tracks** are named deployment channels that control which devices receive a
patch. Every Shorebird app has a built-in `stable` track, which is the default
@@ -62,10 +62,7 @@ built-in names, so those tracks can't be deleted.
## Publishing a patch to a track
-
+
Pass the `--track` flag to any `shorebird patch` command. If you omit the flag,
the patch is published to `stable` by default. With Shorebird 1.6.130 or newer,
diff --git a/src/content/docs/getting-started/index.mdx b/src/content/docs/getting-started/index.mdx
index 4e8f5613..9ee7e85f 100644
--- a/src/content/docs/getting-started/index.mdx
+++ b/src/content/docs/getting-started/index.mdx
@@ -11,12 +11,9 @@ import {
LinkCard,
} from 'starlight-theme-nova/components';
import { Steps, Tabs, TabItem } from '@astrojs/starlight/components';
-import ArcadeEmbed from '~/components/ArcadeEmbed.astro';
+import DemoVideo from '~/components/DemoVideo.astro';
-
+
This guide walks you through installing Shorebird and integrating it into your
Flutter app.