Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
177a684
content(blog): what "the ontology is the software" means — the pillar…
claude Oct 5, 2026
ae4eabb
content(blog): re-slot the pillar definition post to Thursday 2026-10-15
claude Oct 15, 2026
5643fde
Merge remote-tracking branch 'origin/main' into ff/issue-216
claude Oct 15, 2026
9cce2db
site: correct seven claims that contradict the docs
claude Oct 6, 2026
34ea66c
Merge remote-tracking branch 'origin/main' into ff/issue-213
claude Oct 15, 2026
51e704d
fix(layout): phone-width tables, code blocks and body diagrams
claude Oct 6, 2026
435313e
fix(layout): state the overflowing-table bound with its border
claude Oct 6, 2026
0e5d9c8
fix(layout): focusable artifact code block, phone-width security table
claude Oct 6, 2026
e0ee9ba
Merge remote-tracking branch 'origin/main' into ff/issue-217
claude Oct 15, 2026
83d1088
site: fix the layout breaks, add 404 pages, gate internal links on th…
claude Oct 6, 2026
6b4409c
site: localize the rest of the header chrome
claude Oct 6, 2026
4909604
Merge remote-tracking branch 'origin/main' into ff/issue-221
claude Oct 15, 2026
5066537
content(blog/svg): fit 11 overflowing lines to their cards, lift .non…
claude Oct 6, 2026
be727dc
content(blog): describe the five decorative concept illustrations in …
claude Oct 6, 2026
b58839f
build: gate blog SVG text against the shape under it and shapes paint…
claude Oct 6, 2026
ab03e67
content(blog/svg): leave room for wider faces in two refitted lines
claude Oct 6, 2026
1023019
Merge remote-tracking branch 'origin/main' into ff/issue-209-sweep
claude Oct 15, 2026
310e45e
content(blog): README agent path CTA, canonical ObjectOS descriptor, …
claude Oct 6, 2026
2d9f5e4
content(blog): extend-existing-systems-with-ai — the data-residency b…
claude Oct 6, 2026
add901e
Merge remote-tracking branch 'origin/main' into ff/issue-218
claude Oct 15, 2026
92a9640
site(a11y): AA contrast tokens in both themes, drawer focus, disclosu…
claude Oct 6, 2026
cdff04e
Merge remote-tracking branch 'origin/main' into ff/issue-219
claude Oct 15, 2026
cbea2ee
content(blog): link the locale home, not the bare www root, from two …
claude Oct 6, 2026
25c933b
fix(seo): indexing hygiene — fallback rule, sitemap, lang, clusters, …
claude Oct 6, 2026
bab25b3
test(seo): seo-smoke guards the sitemap, body language and redirects;…
claude Oct 6, 2026
a688c3a
fix(seo): no SoftwareApplication offers until the headline price is r…
claude Oct 6, 2026
7c7595b
Merge remote-tracking branch 'origin/main' into ff/issue-220
claude Oct 15, 2026
b86611c
perf(images): serve raster blog covers through astro:assets as WebP w…
claude Oct 6, 2026
356a19c
feat(seo): render a 1200x630 JPEG share image per post from its cover
claude Oct 6, 2026
8dab22e
perf(images): move the hero into src/assets, serve it through <Image>…
claude Oct 6, 2026
cf121b0
perf(images): size card thumbnails for the width object-fit draws the…
claude Oct 6, 2026
85474eb
perf(images): serve cluster reading-path thumbnails through astro:assets
claude Oct 6, 2026
4a00b35
Merge remote-tracking branch 'origin/main' into ff/issue-224
claude Oct 15, 2026
96a0250
build: fail a drop shadow cut off by its filter region; grow 27 regio…
claude Oct 6, 2026
d6b1a46
content(blog): translate the four concept-illustration alt texts into…
claude Oct 6, 2026
f498430
content(blog/svg): keep the natural-language Runtime ring inside its …
claude Oct 6, 2026
31a2e84
Merge remote-tracking branch 'origin/main' into ff/issue-225
claude Oct 15, 2026
0b5376c
fix(blog): remove the space a hard-wrapped line leaves between two CJ…
claude Oct 6, 2026
fdafae5
Merge remote-tracking branch 'origin/main' into ff/issue-226
claude Oct 15, 2026
8683d8b
fix(blog): point quotation marks in zh, ja and ko prose the right way
claude Oct 6, 2026
b5a8ff9
fix(wechat): join CJK line breaks and direct quotation marks in the e…
claude Oct 6, 2026
832deb3
Merge remote-tracking branch 'origin/main' into ff/issue-227
claude Oct 15, 2026
3263dff
fix(blog): point quotation marks the right way in every locale
claude Oct 6, 2026
8491481
Merge remote-tracking branch 'origin/main' into ff/issue-222
claude Oct 15, 2026
7d72a13
site: non-blog copy sweep — retire token figures, canonical ObjectOS …
claude Oct 6, 2026
6f886c6
content(blog): carried positioning wording in three posts, every locale
claude Oct 6, 2026
1fbfa1c
site(approvals): AI metadata changes are their own reviewed path, not…
claude Oct 6, 2026
fe39b43
site(security): localize the FAQ kicker in ja, de, es, fr and ko
claude Oct 6, 2026
a6eb4b2
Merge remote-tracking branch 'origin/main' into ff/issue-223
claude Oct 15, 2026
c553b70
site(layout): primary CTA above the laptop fold on every marketing pa…
claude Oct 7, 2026
1a056cc
site(layout): card grids lay out by count, so no section ends on a lo…
claude Oct 7, 2026
2cf80c5
site(layout): CJK headings break between phrases, never inside a word
claude Oct 7, 2026
fe4bddc
site(layout): balanced headings, no one-word last lines
claude Oct 7, 2026
f69291f
site(layout): one face per heading role
claude Oct 7, 2026
102db6e
site(home): the hero image's media note takes the dark surface in dar…
claude Oct 7, 2026
1d098f3
site(home): video poster words are localized HTML, legible on phones …
claude Oct 7, 2026
2834605
site(blog): CJK headings break between phrases on the blog list, post…
claude Oct 7, 2026
bfd7804
Merge remote-tracking branch 'origin/main' into ff/issue-209-updated
claude Oct 15, 2026
9196762
content(blog): the sweep's updated dates are the day it went live, 20…
claude Oct 15, 2026
161af6d
Merge remote-tracking branch 'origin/main' into ff/issue-232
claude Oct 15, 2026
898e7fc
site(home): localize the video poster's eyebrow and sub-line in every…
claude Oct 15, 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
11 changes: 4 additions & 7 deletions src/components/MarketingHome.astro
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ const YOUTUBE_CHANNEL_URL = 'https://www.youtube.com/@objectstack';
// VideoEmbed.astro). The title is this locale's video caption, which every
// locale already has, split after the product name: "ObjectStack" over "in 90
// Seconds", "90 秒总览", "を 90 秒で" (a leading particle stays on line one).
// The eyebrow and the sub-line exist in English only: the eyebrow names the
// licence and stays in every locale, the sub-line is a sentence and is drawn
// in English only.
const POSTER_EYEBROW = 'OPEN PROTOCOL & RUNTIME · APACHE-2.0';
const POSTER_NOTE = 'Data model · UI · workflows · permissions — one context window.';
// The eyebrow and the sub-line are this locale's `videoPosterEyebrow` and
// `videoPosterNote` from `homeCopy` (see the interface note there).

interface Props {
locale: Locale;
Expand Down Expand Up @@ -137,9 +134,9 @@ const HERO_SIZES = '(min-width: 898px) 910px, calc(120vw - 2.4rem)';
poster="/images/objectstack-overview-poster-art.svg"
playLabel={copy.videoPlayLabel}
posterText={{
eyebrow: POSTER_EYEBROW,
eyebrow: copy.videoPosterEyebrow,
title: posterTitle,
note: locale === 'en' ? POSTER_NOTE : undefined,
note: copy.videoPosterNote,
}}
/>
<figcaption>
Expand Down
10 changes: 10 additions & 0 deletions src/components/VideoEmbed.astro
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ const eyebrowParts = posterText?.eyebrow?.split(' · ') ?? [];
margin-left: 4px;
}
}
/* Below 400px the longer translated eyebrows ("OFFENES PROTOKOLL & RUNTIME
· APACHE-2.0", es, fr) wrap to two lines, and at 40% the badge's top edge
met the second line's box at 360. At 44% the badge keeps about 6px above a
two-line eyebrow and about 17px above the title at 360, and sits centred
between a one-line eyebrow and the title instead of 10px under it. */
@container (max-width: 400px) {
.video-play .video-badge {
top: 44%;
}
}
.video-scrim {
position: absolute;
inset: 0;
Expand Down
30 changes: 30 additions & 0 deletions src/lib/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ interface HomeCopy {
videoCaption: string;
videoPlayLabel: string;
videoMoreLink: string;
/**
* The words drawn on the video poster besides the title (see
* `VideoEmbed.astro`): an eyebrow and a sub-line. Both quote the objectstack
* README rather than the canonical lines in `./positioning`: the eyebrow is
* its licence sentence ("the open stack — protocol … and the production
* runtime, Apache-2.0"), the sub-line's tail is its size line ("Apps small
* enough for AI to hold whole."), in the wording each locale's `aiCopy`
* already gives that line. The sub-line used to end "one context window":
* that was the title of the proof chip that carried the 150k-token figure,
* both retired by ruling Q5 on #209, and the README no longer says it; so
* no token figure and no context-window framing here. The eyebrow's parts
* are separated by " · ", which is where `VideoEmbed` lets it wrap. The
* nouns use each locale's vocabulary from `aiCopy` and `./positioning`.
*/
videoPosterEyebrow: string;
videoPosterNote: string;
proof: [string, string][];
imageAlt: string;
imageNoteTitle: string;
Expand Down Expand Up @@ -87,6 +103,8 @@ const zhHans: HomeCopy = {
videoCaption: 'ObjectStack 90 秒总览',
videoPlayLabel: '播放视频:ObjectStack 90 秒总览',
videoMoreLink: '在 YouTube 上观看更多视频',
videoPosterEyebrow: '开放协议与运行时 · APACHE-2.0',
videoPosterNote: '数据模型 · 界面 · 流程 · 权限——小到 AI 能一次读全。',
proof: [
[positioning['zh-Hans'].t3[0], '运行时运行它'],
[positioning['zh-Hans'].t3[1], 'AI 编写它'],
Expand Down Expand Up @@ -173,6 +191,8 @@ const en: HomeCopy = {
videoCaption: 'ObjectStack in 90 Seconds',
videoPlayLabel: 'Play the video: ObjectStack in 90 Seconds',
videoMoreLink: 'More videos on YouTube',
videoPosterEyebrow: 'OPEN PROTOCOL & RUNTIME · APACHE-2.0',
videoPosterNote: 'Data model · UI · workflows · permissions — small enough for AI to hold whole.',
proof: [
[positioning.en.t3[0], 'The runtime runs it'],
[positioning.en.t3[1], 'AI writes it'],
Expand Down Expand Up @@ -260,6 +280,8 @@ const ja: HomeCopy = {
videoCaption: 'ObjectStack を 90 秒で',
videoPlayLabel: '動画を再生:ObjectStack を 90 秒で',
videoMoreLink: 'YouTube でほかの動画を見る',
videoPosterEyebrow: 'オープンプロトコル & ランタイム · APACHE-2.0',
videoPosterNote: 'データモデル · UI · ワークフロー · 権限 — AI が一度に把握できる小ささに収まる。',
proof: [
[positioning.ja.t3[0], 'ランタイムが動かす'],
[positioning.ja.t3[1], 'AI が書く'],
Expand Down Expand Up @@ -347,6 +369,8 @@ const de: HomeCopy = {
videoCaption: 'ObjectStack in 90 Sekunden',
videoPlayLabel: 'Video abspielen: ObjectStack in 90 Sekunden',
videoMoreLink: 'Mehr Videos auf YouTube',
videoPosterEyebrow: 'OFFENES PROTOKOLL & RUNTIME · APACHE-2.0',
videoPosterNote: 'Datenmodell · UI · Workflows · Berechtigungen — klein genug, dass AI das Ganze erfasst.',
proof: [
[positioning.de.t3[0], 'Die Runtime führt sie aus'],
[positioning.de.t3[1], 'AI schreibt sie'],
Expand Down Expand Up @@ -434,6 +458,8 @@ const es: HomeCopy = {
videoCaption: 'ObjectStack en 90 segundos',
videoPlayLabel: 'Reproducir el vídeo: ObjectStack en 90 segundos',
videoMoreLink: 'Más vídeos en YouTube',
videoPosterEyebrow: 'PROTOCOLO Y RUNTIME ABIERTOS · APACHE-2.0',
videoPosterNote: 'Modelo de datos · UI · workflows · permisos — tan pequeño que la AI lo abarca entero.',
proof: [
[positioning.es.t3[0], 'El runtime la ejecuta'],
[positioning.es.t3[1], 'La AI la escribe'],
Expand Down Expand Up @@ -521,6 +547,8 @@ const fr: HomeCopy = {
videoCaption: 'ObjectStack en 90 secondes',
videoPlayLabel: 'Lire la vidéo : ObjectStack en 90 secondes',
videoMoreLink: 'Plus de vidéos sur YouTube',
videoPosterEyebrow: 'PROTOCOLE ET RUNTIME OUVERTS · APACHE-2.0',
videoPosterNote: 'Modèle de données · UI · workflows · permissions — si petit que l’AI le tient entier.',
proof: [
[positioning.fr.t3[0], 'Le runtime l’exécute'],
[positioning.fr.t3[1], 'L’AI l’écrit'],
Expand Down Expand Up @@ -608,6 +636,8 @@ const ko: HomeCopy = {
videoCaption: 'ObjectStack 90초 살펴보기',
videoPlayLabel: '동영상 재생: ObjectStack 90초 살펴보기',
videoMoreLink: 'YouTube에서 더 많은 영상 보기',
videoPosterEyebrow: '오픈 프로토콜 & 런타임 · APACHE-2.0',
videoPosterNote: '데이터 모델 · UI · 워크플로 · 권한 — AI가 한 번에 담을 만큼 작습니다.',
proof: [
[positioning.ko.t3[0], '런타임이 실행합니다'],
[positioning.ko.t3[1], 'AI가 작성합니다'],
Expand Down
Loading