Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4b13c27
feat: add dakota sub-page
castrojo May 11, 2026
5a1f2cd
fix: restore DakotaScene to simple text column, no internal raptor grid
castrojo May 11, 2026
3164a93
fix: address reviewer criticals on dakota page
castrojo May 11, 2026
baa11b6
fix: version chip text bold white monospace
castrojo May 11, 2026
a4efc03
fix: revert broken i18n locale cast, legacy mode uses .locale not .lo…
castrojo May 11, 2026
02a72ac
fix: replace placeholder [CNCF] [Apache Foundation] [UAPI Group] link…
castrojo May 11, 2026
9694ea1
feat: side-by-side text+raptor at medium viewport (half 16:9)
castrojo May 11, 2026
ee0ba16
feat: add bootc and nvidia versions to dakota version chips
castrojo May 11, 2026
5f8a530
fix: mobile layout — single-column features grid at 500px, stack down…
castrojo May 11, 2026
f91e235
feat: link section titles to upstream projects (GNOME OS, Freedesktop…
castrojo May 11, 2026
826fa7b
feat: split BuildStream into BuildStream & BuildGrid with separate links
castrojo May 11, 2026
39831f5
feat: add x86-64-v3 baseline pill to version chips
castrojo May 11, 2026
282b3b6
fix: merge user edits + restore links in DakotaHighlights
castrojo May 11, 2026
c1cf866
fix: Dakota not Bluefin in hero description, fix awkward phrasing
castrojo May 11, 2026
bab12eb
feat: add Freedesktop SDK 25.08.11 chip, move x86-64-v3 last with gre…
castrojo May 11, 2026
f1cc6d1
feat: link Freedesktop.org and GNOME OS in hero description
castrojo May 11, 2026
94c418d
feat: match docs navbar — Reports link, Documentation in blue, 0.875r…
castrojo May 11, 2026
d49ad36
fix: dakota meta description from README, not made up
castrojo May 11, 2026
e2f9027
fix: navbar font sizes match docs.projectbluefin.io (16px, weight 500…
castrojo May 11, 2026
b3dc8f9
fix: navbar font 16px/weight 500 matching docs; add Playwright nav tests
castrojo May 11, 2026
a1a544a
fix: move nav tests to tests/ dir, exclude from eslint
castrojo May 11, 2026
11b8b77
fix: replace rem values with px in TopNavbar (no fractional computed …
castrojo May 11, 2026
cd74826
test: expand navbar Playwright suite to 18 assertions (spacing, activ…
castrojo May 11, 2026
e77908b
fix: match docs dark mode exactly — active link rgb(138,151,247) weig…
castrojo May 11, 2026
243ba7d
fix: navbar spacing matches docs pixel-for-pixel
castrojo May 11, 2026
0a2b228
fix: dakota mobile — single-column grid, no button text wrap at 390px
castrojo May 11, 2026
b75f418
fix: mobile download button collapse (flex:0 0 auto), expand navbar t…
castrojo May 11, 2026
2bd2e25
feat: add 'Designed for Contributors' feature card to dakota page
castrojo May 11, 2026
2b8229c
docs: update AGENTS.md with dakota page, tests, lessons learned
castrojo May 11, 2026
e8f81b0
feat: CI auto-update dakota-versions.json from releases API
castrojo May 11, 2026
c35e275
refactor: setLocale utility, vitest chip tests, verify OG assets
castrojo May 11, 2026
a0e3f3a
chore(deps): bump postcss from 8.5.6 to 8.5.14
dependabot[bot] May 11, 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
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
run: npm install
- name: Build
run: npm run build
# TODO: wire navbar-visual.mjs once serve step is stable
- name: Setup Pages
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
- name: Upload artifact
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/update-content.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Update Dakota versions
run: node scripts/update-dakota-versions.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Check for changes
id: changes
run: |
Expand Down Expand Up @@ -77,6 +82,10 @@ jobs:
- `ublue-os/bluefin` (for GTS and Stable streams)
- `ublue-os/bluefin-lts` (for LTS stream)

### Dakota Versions
- Updated `public/dakota-versions.json` release metadata
- Data sourced from latest `projectbluefin/dakota` release tag

### Review Notes
- This is an automated daily update
- Please verify the data looks correct before merging
Expand All @@ -89,6 +98,7 @@ jobs:
add-paths: |
src/assets/svg/growth_bluefins.svg
public/stream-versions.yml
public/dakota-versions.json

- name: Create issue on failure
if: failure()
Expand Down
81 changes: 62 additions & 19 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ npm run lint:fix
- **Vue 3** with Composition API (`<script setup>` syntax preferred)
- **TypeScript** for type safety
- **Vite 7.1.12** for build tooling and development server
- **Vue i18n** for internationalization (12 languages supported: de-DE, en-US, eo, fr-FR, ja-JP, nl-NL, pt-BR, ru-RU, sk-SK, vi-VN, zh-HK, zh-TW)
- **Vue i18n** for internationalization (13 languages supported: de-DE, en-US, eo, fr-FR, ja-JP, ko-KR, nl-NL, pt-BR, ru-RU, sk-SK, vi-VN, zh-HK, zh-TW)

### Styling
- **TailwindCSS 4.1.16** with @tailwindcss/vite plugin
Expand All @@ -149,25 +149,37 @@ npm run lint:fix
/
├── .github/workflows/ # CI/CD pipelines
│ ├── deploy.yml # GitHub Pages deployment (on push to main, releases)
│ ├── images.yml # Image optimization workflow
│ └── update-stream-versions.yml # Version update automation
│ └── update-content.yml # Daily auto-update: stream-versions.yml + growth chart SVG
├── dakota/
│ └── index.html # Dakota sub-page entry (noindex, OG tags)
├── tests/
│ └── navbar-visual.mjs # Playwright navbar assertions (38 tests)
├── public/ # Static assets
│ ├── characters/ # Character artwork (.webp)
│ ├── brands/ # Brand logos (.svg, .png)
│ ├── evening/ # Background images
│ │ └── night-sky.webp # Dakota background
│ ├── favicons/ # Site icons
│ ├── dakota-versions.json # Version chip data (seeded; CI update TODO)
│ └── testing.html # Testing page (also built to dist/public/)
├── src/
│ ├── components/ # Vue components (21 total)
│ │ ├── scenes/ # Major page sections (4 components)
│ │ ├── sections/ # Smaller reusable sections (6 components)
│ │ └── common/ # Shared components (3 components)
│ ├── locales/ # i18n translation files (12 JSON files)
│ ├── components/ # Vue components
│ │ ├── scenes/ # Major page sections (3 components)
│ │ ├── sections/ # Smaller reusable sections (8 components)
│ │ ├── common/ # Shared components (4 components)
│ │ └── dakota/ # Dakota-specific components
│ │ ├── DakotaScene.vue
│ │ ├── DakotaHighlights.vue
│ │ ├── DakotaDownloadCard.vue
│ │ └── DakotaVersionChips.vue
│ ├── locales/ # i18n translation files (13 JSON files)
│ ├── style/ # SCSS styling
│ │ ├── setup/ # Mixins, variables, fonts, reset
│ │ └── app/ # Component-specific styles
│ ├── content.ts # Main content constants
│ ├── composables.ts # Vue composables
│ ├── DakotaApp.vue # Dakota page root component
│ ├── dakota-main.ts # Dakota app entry point
│ └── main.ts # App entry point
├── package.json # Dependencies and scripts
├── vite.config.ts # Vite configuration (multi-page: index.html + testing.html)
Expand All @@ -176,7 +188,7 @@ npm run lint:fix
└── eslint.config.js # Code formatting rules
```

**No test infrastructure exists** - validation is done manually through browser testing.
**Test infrastructure:** Vitest is configured (`npm test` / `npm run test:run`). Manual browser validation is still required for UI changes.

## Code Organization

Expand Down Expand Up @@ -237,10 +249,11 @@ const isVisible = ref(false)
- Utility components: descriptive names (e.g., `PageLoading.vue`, `Navigation.vue`)

#### Existing Components Reference
**Scenes (4):** `SceneLanding.vue`, `SceneDevelopers.vue`, `SceneGamers.vue`, `SceneUsers.vue`
**Sections (6):** `SectionFooter.vue`, `SectionMission.vue`, `SectionNews.vue`, `SectionPicker.vue`, `SectionQuestions.vue`, `SectionVideo.vue`, `ParallaxWrapper.vue`
**Common (3):** `SceneContent.vue`, `SceneVisibilityChecker.vue`, `TextArrow.vue`
**Root Components (7):** `Navigation.vue`, `TopNavbar.vue`, `PageLoading.vue`, `FaqItem.vue`, `ImagePicker.vue`, `ImageChooser.vue`, `RssFeed.vue`
**Scenes (3):** `SceneLanding.vue`, `SceneDevelopers.vue`, `SceneUsers.vue`
**Sections (8):** `SectionBazaar.vue`, `SectionCommunity.vue`, `SectionFooter.vue`, `SectionMission.vue`, `SectionNews.vue`, `SectionPicker.vue`, `SectionVideo.vue`, `ParallaxWrapper.vue`
**Common (4):** `SceneContent.vue`, `SceneQuote.vue`, `SceneVisibilityChecker.vue`, `TextArrow.vue`
**Root Components (5):** `Navigation.vue`, `TopNavbar.vue`, `PageLoading.vue`, `ImageChooser.vue`, `RssFeed.vue`
**Dakota (4):** `DakotaScene.vue`, `DakotaHighlights.vue`, `DakotaDownloadCard.vue`, `DakotaVersionChips.vue`

## Content Management

Expand Down Expand Up @@ -269,14 +282,41 @@ export const LangSectionTitle = 'Default English Text'
</template>
```

**Available languages:** de-DE, en-US, eo, fr-FR, ja-JP, nl-NL, pt-BR, ru-RU, sk-SK, vi-VN, zh-HK, zh-TW (12 total)
**Available languages:** de-DE, en-US, eo, fr-FR, ja-JP, ko-KR, nl-NL, pt-BR, ru-RU, sk-SK, vi-VN, zh-HK, zh-TW (13 total)

### Content Guidelines
- Use markdown support where available (rendered with `marked.parse()`)
- Support HTML in content when necessary
- Include proper citations for quotes using `<cite>` tags
- Maintain consistent voice that reflects Bluefin's mission and character

## Data Pipeline

### Dakota Versions (`public/dakota-versions.json`)
Fetched client-side by `DakotaVersionChips.vue`. Contains kernel/gnome/freedesktop-sdk/mesa/bootc/nvidia/systemd/podman/pipewire/flatpak/baseline versions. Currently seeded with SBOM data. TODO: wire into CI auto-update via `update-content.yml`.

### Stream Versions (`public/stream-versions.yml`)
Fetched **client-side at runtime** by `ImageChooser.vue` via `fetch('/stream-versions.yml')`. Contains kernel/gnome/mesa/nvidia/hwe versions for each stream. Updated daily at 08:00 UTC by `update-content.yml` which parses GitHub Release markdown tables from `ublue-os/bluefin` and `ublue-os/bluefin-lts`. Parsing is fragile (format-dependent) — see TODO comment in `scripts/update-stream-versions.js` for the proper SBOM-based fix.

### Growth Chart (`src/assets/svg/growth_bluefins.svg`)
Fetched from `ublue-os/countme` and dark-theme-patched (white→`#0c1016`, light gray→`#272727`, etc.) by `update-content.yml`.

### Download Flow (ImageChooser.vue)
Step-by-step wizard:
1. **Release** — `lts` or `stable`
2. **Architecture** — `x86_64` or `aarch64` (LTS only for ARM)
3. **GPU** — AMD/Intel or Nvidia
4. **Kernel** (LTS + non-Nvidia only) — Regular or HWE
5. **Download** — generated ISO filename + checksum link

**ISO name format:** `bluefin[-gdx][-nvidia-open]-{stream}[-hwe]-{arch}.iso`
- LTS + Nvidia → `bluefin-gdx-lts-{arch}.iso`
- Stable + Nvidia → `bluefin-nvidia-open-stable-{arch}.iso`
- Stable + AMD/Intel → `bluefin-stable-x86_64.iso`
- LTS + AMD/Intel + HWE → `bluefin-lts-hwe-x86_64.iso`

**Download base URL:** `https://download.projectbluefin.io/`

## Styling Guidelines

### SCSS Mixins (src/style/setup/_mixins.scss)
Expand Down Expand Up @@ -336,17 +376,16 @@ Common mixins available for use:
- **Dev server won't start:** Ensure `npm install --include=dev` was run
- **Server process dies:** Use async mode instead of detached mode
- **Missing images:** Verify paths relative to `public/` directory
- **Translation issues:** Ensure locale keys exist in all 12 language files
- **Translation issues:** Ensure locale keys exist in all 13 language files (de-DE, en-US, eo, fr-FR, ja-JP, ko-KR, nl-NL, pt-BR, ru-RU, sk-SK, vi-VN, zh-HK, zh-TW)
- **Styling problems:** Check for SCSS syntax errors or missing Tailwind classes
- **ESLint errors:** Use Prettier instead (ESLint setup incomplete)
- **Port conflicts:** Vite will auto-select next available port (5174, 5175, etc.)

## CI/CD Pipeline

**GitHub Actions workflows:**
- **deploy.yml:** Builds and deploys to GitHub Pages on push to main, releases, and manual trigger
- **images.yml:** Image optimization workflow
- **update-stream-versions.yml:** Automated version updates
- **deploy.yml:** Builds and deploys to GitHub Pages on push to main, releases, merge_group, and manual trigger
- **update-content.yml:** Daily (08:00 UTC) — fetches growth chart SVG from ublue-os/countme, updates public/stream-versions.yml from GitHub Releases API, opens automated PR via GITHUB_TOKEN (no PAT)

**Deployment process:**
1. Code pushed to main branch or release published
Expand Down Expand Up @@ -379,7 +418,7 @@ npm run lint:fix # Lints and fixes issues in the project
- 🚀 **Run dev server in async mode** to keep it alive
- 🧪 **ALWAYS test manually** after making changes
- 📱 **Test responsive design** on different screen sizes
- 🌍 **Consider i18n impact** for all text changes (12 languages supported)
- 🌍 **Consider i18n impact** for all text changes (13 languages — always update all locale files)
- 📸 **Take screenshots** of UI changes for review
- **Always** follow the conventional commits specification when sending pull requests
- **Always** include screenshots of both desktop and mobile in pull requests
Expand All @@ -388,6 +427,10 @@ npm run lint:fix # Lints and fixes issues in the project
- **Always** ensure images are compressed appropriately for mobile
- **Always** do surgical improvements, keep it simple and readable
- **Always** match conventions that exist, like font sizes and visual style
- 🌐 **vue-i18n is in LEGACY mode:** use `(i18n.global as any).locale = x` — NOT `.locale.value = x` (will silently no-op)
- 📐 **TopNavbar uses `px` not `rem`** — site root font-size is 63.5% (~10 px base); pixel values in Navbar are intentional
- 🔒 **Dakota page is `noindex` / unlisted** — intentionally hidden from search engines and nav; do not add to sitemap or main nav
- ✅ **Run `node tests/navbar-visual.mjs`** to validate navbar rendering against docs.projectbluefin.io (38 Playwright assertions)

### Attribution Requirements

Expand Down
36 changes: 36 additions & 0 deletions dakota/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bluefin Dakotaraptor</title>
<meta name="description" content="Bluefin's final form. Built on GNOME OS using BuildStream, published as a bootc container." />
<!-- Hidden page: not linked from main site, intentionally excluded from search index -->
<meta name="robots" content="noindex, nofollow" />

<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://projectbluefin.io/dakota/" />
<meta property="og:title" content="Bluefin Dakotaraptor" />
<meta property="og:description" content="Bluefin's final form. Built on GNOME OS using BuildStream, published as a bootc container." />
<meta property="og:image" content="https://projectbluefin.io/characters/header/dakota.webp" />

<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Bluefin Dakotaraptor" />
<meta name="twitter:description" content="Bluefin's final form. Built on GNOME OS using BuildStream, published as a bootc container." />
<meta name="twitter:image" content="https://projectbluefin.io/characters/header/dakota.webp" />

<link rel="preload" as="image" href="/evening/night-sky.webp">
<link rel="icon" href="/favicons/favicon.ico" />
<link rel="manifest" href="/favicons/site.webmanifest" />
<style>@view-transition { navigation: auto; }</style>
</head>

<body>
<div id="app"></div>
<script type="module" src="/src/dakota-main.ts"></script>
</body>

</html>
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const ignores = [
'.dist',
'node_modules',
'public',
'tests/**',
]

export default antfu({
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon.svg">
<link rel="manifest" href="/favicons/site.webmanifest">
<!-- <script async src="https://analytics.eu.umami.is/script.js" data-website-id="6f6ea63d-01c2-4539-b84b-fd455210ddcf"></script> -->
<style>@view-transition { navigation: auto; }</style>
</head>

<body>
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

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

16 changes: 16 additions & 0 deletions public/dakota-versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"generatedAt": "2026-05-10T00:00:00.000Z",
"packages": {
"kernel": "6.19.11",
"gnome": "50.0",
"freedesktop-sdk": "25.08.11",
"mesa": "26.0.5",
"bootc": "1.15.2",
"nvidia": "595.71.05",
"systemd": "260.1",
"podman": "5.8.2",
"pipewire": "1.6.1",
"flatpak": "1.16.6",
"baseline": "x86-64-v3"
}
}
Binary file added public/evening/night-sky.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions scripts/update-dakota-versions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env node

/**
* Script to update dakota-versions.json with release metadata from
* projectbluefin/dakota GitHub Releases API.
*
* Current approach: fetches the latest release tag and publication date,
* updates generatedAt and releaseTag while preserving existing package versions.
*
* TODO (proper fix): Query the OCI SBOM attestation for exact installed package
* versions:
* cosign download attestation ghcr.io/projectbluefin/dakota:<tag> \
* | jq -r '.payload' | base64 -d | jq '.predicate.components[] | select(.name == "kernel")'
* This would use the syft JSON schema embedded in the image attestation and is
* immune to any changelog format changes.
*/

import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const OUT = path.join(__dirname, '../public/dakota-versions.json')
const GITHUB_API = 'https://api.github.com'

async function main() {
const headers = {
'User-Agent': 'bluefin-website-updater',
...(process.env.GITHUB_TOKEN ? { Authorization: `token ${process.env.GITHUB_TOKEN}` } : {}),
}

const res = await fetch(`${GITHUB_API}/repos/projectbluefin/dakota/releases/latest`, { headers })
if (!res.ok) {
console.warn(`[dakota-versions] releases API returned ${res.status} — skipping update`)
return
}

const release = await res.json()
const current = JSON.parse(fs.readFileSync(OUT, 'utf8'))

current.generatedAt = release.published_at ?? new Date().toISOString()
current.releaseTag = release.tag_name

fs.writeFileSync(OUT, `${JSON.stringify(current, null, 2)}\n`)
console.info(`[dakota-versions] updated to ${release.tag_name} (${current.generatedAt})`)
}

main().catch((e) => {
console.error('[dakota-versions] error:', e.message)
process.exit(0)
})
3 changes: 2 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import SectionPicker from './components/sections/SectionPicker.vue'
import SectionVideo from './components/sections/SectionVideo.vue'
import TopNavbar from './components/TopNavbar.vue'

import { setLocale } from './composables/useLocale'
import { i18n } from './locales/schema'

const visibleSection = ref<string>('')
Expand Down Expand Up @@ -52,7 +53,7 @@ onBeforeMount(() => {
const urlParams = new URLSearchParams(window.location.search)
const currentLocale = urlParams.get('lang') || window.navigator.language
if (i18n.global.availableLocales.includes(currentLocale)) {
;(i18n.global as any).locale = currentLocale
setLocale(currentLocale)
}
</script>

Expand Down
Loading