diff --git a/.gitignore b/.gitignore index f47250e1f2..d9d89c907e 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ __pycache__/ # Debug/analysis docs docs/*-analysis.md +docs/.viewport-audit/ docs/.astro/ # Swift Package Manager metadata (leave sources tracked) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f15422743..606badb45a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 0.38.1 — Unreleased +### Changed +- Website: redesign codexbar.app around faster download, provider discovery, feature, CLI, and widget paths with responsive dark/light and localized layouts. Thanks @vyctorbrzezowski! + ## 0.38.0 — 2026-07-03 ### Added diff --git a/Scripts/build-site-css.sh b/Scripts/build-site-css.sh new file mode 100755 index 0000000000..e87f7ade42 --- /dev/null +++ b/Scripts/build-site-css.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +npx --yes tailwindcss@3.4.19 \ + --config Scripts/tailwind.site.config.cjs \ + --input Scripts/site-tailwind.input.css \ + --output docs/site-utilities.css \ + --minify diff --git a/Scripts/check-site-locales.mjs b/Scripts/check-site-locales.mjs index 0adf7d6e09..429f7283e0 100644 --- a/Scripts/check-site-locales.mjs +++ b/Scripts/check-site-locales.mjs @@ -7,6 +7,10 @@ import { localeCatalog, localeMessages } from "../docs/site-locales.mjs"; const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const indexHtml = fs.readFileSync(path.join(repoRoot, "docs/index.html"), "utf8"); +assert(!indexHtml.includes("cdn.tailwindcss.com"), "site must not load Tailwind from a runtime CDN"); +for (const match of indexHtml.matchAll(/([^<]+)<\/option>/g)]; -assertEqual(optionMatches.map((match) => match[1]), catalogCodes, "language selector locales"); -assertEqual(optionMatches.map((match) => match[2]), localeCatalog.map((locale) => locale.name), "language selector labels"); +const siteJs = fs.readFileSync(path.join(repoRoot, 'docs/site.js'), 'utf8'); +const hasLanguagePicker = indexHtml.includes('id="language-picker-list"') + && (indexHtml.includes('localeCatalog') || siteJs.includes('localeCatalog')); +assert(hasLanguagePicker, 'site must include the language picker backed by localeCatalog'); for (const code of catalogCodes) { assert(indexHtml.includes(`href="https://codexbar.app/?lang=${code}"`), `missing hreflang URL for ${code}`); } -const providerCards = [...indexHtml.matchAll(/]*>([\s\S]*?)<\/a>/g)]; -for (const [, classes, body] of providerCards) { - if (!classes.split(/\s+/).includes("add")) { - assert(body.includes('class="chip-logo'), "provider cards must use logo assets instead of text placeholders"); - for (const match of body.matchAll(/(?:src|data-dark-src)="\.\/([^"]+)"/g)) { - assert(fs.existsSync(path.join(repoRoot, "docs", match[1])), `missing provider logo asset ${match[1]}`); +const providerCards = [...indexHtml.matchAll(/
  • ]*)>([\s\S]*?)<\/li>/g)]; +for (const [, attrs, body] of providerCards) { + if (!attrs.includes('hidden')) { + assert(body.includes('class="provider-card-link"'), 'provider cards must link to provider documentation'); + assert(body.includes('class="provider-logo'), 'provider cards must use logo assets'); + for (const match of body.matchAll(/src="\.\/([^"]+)"/g)) { + assert(fs.existsSync(path.join(repoRoot, 'docs', match[1])), `missing provider logo asset ${match[1]}`); } } } diff --git a/Scripts/site-tailwind.input.css b/Scripts/site-tailwind.input.css new file mode 100644 index 0000000000..b5c61c9567 --- /dev/null +++ b/Scripts/site-tailwind.input.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/Scripts/tailwind.site.config.cjs b/Scripts/tailwind.site.config.cjs new file mode 100644 index 0000000000..afa1342b5f --- /dev/null +++ b/Scripts/tailwind.site.config.cjs @@ -0,0 +1,14 @@ +module.exports = { + content: ["./docs/index.html", "./docs/site.js"], + theme: { + extend: { + screens: { + tablet: "769px", + }, + fontFamily: { + sans: ["Inter", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "sans-serif"], + mono: ["SFMono-Regular", "SF Mono", "Menlo", "monospace"], + }, + }, + }, +}; diff --git a/docs/features/feature-credits.webp b/docs/features/feature-credits.webp new file mode 100644 index 0000000000..72b1d46ef0 Binary files /dev/null and b/docs/features/feature-credits.webp differ diff --git a/docs/features/feature-resets.webp b/docs/features/feature-resets.webp new file mode 100644 index 0000000000..00211bf991 Binary files /dev/null and b/docs/features/feature-resets.webp differ diff --git a/docs/features/feature-status.webp b/docs/features/feature-status.webp new file mode 100644 index 0000000000..d6dc6f8847 Binary files /dev/null and b/docs/features/feature-status.webp differ diff --git a/docs/hero-mockup.svg b/docs/hero-mockup.svg new file mode 100644 index 0000000000..e6d727ed31 --- /dev/null +++ b/docs/hero-mockup.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/apple.svg b/docs/images/apple.svg new file mode 100644 index 0000000000..915e890991 --- /dev/null +++ b/docs/images/apple.svg @@ -0,0 +1 @@ +Apple \ No newline at end of file diff --git a/docs/images/menubar/github-circle-fill.png b/docs/images/menubar/github-circle-fill.png new file mode 100644 index 0000000000..2aa9d3f268 Binary files /dev/null and b/docs/images/menubar/github-circle-fill.png differ diff --git a/docs/images/menubar/openclaw-menubar.svg b/docs/images/menubar/openclaw-menubar.svg new file mode 100644 index 0000000000..92e7bfe55d --- /dev/null +++ b/docs/images/menubar/openclaw-menubar.svg @@ -0,0 +1,11 @@ + diff --git a/docs/images/menubar/person-circle.png b/docs/images/menubar/person-circle.png new file mode 100644 index 0000000000..4e217c882e Binary files /dev/null and b/docs/images/menubar/person-circle.png differ diff --git a/docs/images/menubar/personalhotspot.png b/docs/images/menubar/personalhotspot.png new file mode 100644 index 0000000000..dbbe8bfd5e Binary files /dev/null and b/docs/images/menubar/personalhotspot.png differ diff --git a/docs/images/menubar/wifi.png b/docs/images/menubar/wifi.png new file mode 100644 index 0000000000..4b5b8d59d4 Binary files /dev/null and b/docs/images/menubar/wifi.png differ diff --git a/docs/index.html b/docs/index.html index 9205394f31..9a4517ef6c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,9 +1,9 @@ - + - CodexBar — every AI coding limit in your menu bar + CodexBar — every AI coding limit, in your menu bar - - - + - + + + - - -
    - - - CodexBar + + +
    + + + CodexBar - -
    -
    -
    -

    Every AI coding limit, in your menu bar.

    -

    - CodexBar tracks usage windows, credit balances, and reset countdowns across the providers you actually pay for — - one status item each, or merge them into one. -

    -
    - Download for macOS -
    - brew install --cask steipete/tap/codexbar - + +
    + + + + + download + + +
    + +
    +
    + + +
    +
    +
    +
    + AI usage limits + + for macOS +
    + +

    + Every AI coding limit, + in your menu bar. +

    + +

    + Track usage windows, credit balances, and reset countdowns across the AI tools you actually pay for. +

    + +
    + + + Download for macOS + +
    + +

    + Free & open source · macOS 14+ +

    +
    +
    -

    Free & open source · macOS 14+ · Universal via GitHub Releases and Homebrew

    -
    -
    -

    56 providers, one menu bar

    -

    Popular providers become status items with their own usage windows, reset countdowns, charts, and provider menus.

    +
    +
    +
    +

    + 56 providers,{mobileBreak}one menu bar +

    +

    + Popular providers become status items with their own usage windows, reset countdowns, charts, and provider menus. +

    -
    +
    + +
    +
    +

    Limits, spend, and status

    + +
    +
    +
    +

    Resets you can plan around

    +

    Per-provider session, weekly, and monthly windows with countdowns to the next reset — no more guessing whether to start a long task.

    +
    + +
    +
    +
    +

    Credits, spend, and cost scans

    +

    Credit balances and monthly spend where the provider exposes them, plus configurable local cost scans for Codex and Claude.

    +
    + +
    +
    +
    +

    Status & incidents

    +

    Provider status polling surfaces incident badges in the menu and an indicator overlay on the bar icon.

    +
    + +
    +
    +
    +
    + +
    +
    +
    + + +
    +

    + CodexBar + on CLI +

    +

    + A bundled {codexbar} binary with the same usage output as the menu bar — scripts, CI, and quick terminal checks. +

    +

    + Standalone tarballs for macOS and Linux on every release. +

    +

    + + CodexBar reuses existing provider sessions — no passwords stored on disk. +

    +
    +
    +
    -
    -
    - CodexBar menu bar popover showing provider tiles with usage bars, reset countdowns, and credit details. -
    -
    -
    -

    Resets you can plan around

    -

    Per-provider session, weekly, and monthly windows with countdowns to the next reset — no more guessing whether to start a long task.

    -
    -
    -

    Credits, spend, and cost scans

    -

    Credit balances and monthly spend where the provider exposes them, plus configurable local cost scans for Codex and Claude.

    -
    -
    -

    Status & incidents

    -

    Provider status polling surfaces incident badges in the menu and an indicator overlay on the bar icon.

    -
    -
    -

    CLI & widgets

    -

    WidgetKit widgets for supported providers and a bundled codexbar CLI for scripts and CI — macOS and Linux builds on every release.

    -
    -
    +
    +
    +
    +
    +

    + CodexBar + widgets +

    +

    + WidgetKit widgets for supported providers — usage windows, reset countdowns, and spend where available. Drop them on your Home Screen and desktop. +

    +

    + Small, medium, and large sizes. Switch providers without leaving the widget. +

    +
    + +
    + +
    +
    +
    -
    -
    -

    Install & updates

    -

    - Universal app via GitHub Releases with Sparkle auto-updates, or via - brew install --cask steipete/tap/codexbar (updates via brew upgrade). -

    -
    -
    -

    CLI

    -

    - A bundled codexbar binary plus standalone tarballs for macOS and Linux on each release. On Linux: - brew install steipete/tap/codexbar. -

    -
    -
    -

    Privacy

    -

    - Reuses existing provider sessions — OAuth, device flow, API keys, browser cookies, local files — so no passwords are stored. - Audit notes in issue #12. -

    -
    -
    -

    macOS permissions

    -

    - Full Disk Access for Safari cookies, Keychain access for cookie decryption and OAuth flows, and Files & Folders prompts - when provider helpers read project directories. -

    -
    +
    +
    +

    More

    + +
    +
    +

    Install & updates

    +

    + Universal app via {releases} with Sparkle auto-updates, or via {cask} (updates via {upgrade}). +

    +
    +
    +

    CLI

    +

    + A bundled {codexbar} binary plus standalone tarballs for macOS and Linux on each release. On Linux: {linuxCommand}. +

    +
    +
    +

    Privacy

    +

    + Reuses existing provider sessions — OAuth, device flow, API keys, browser cookies, local files — so no passwords are stored. Audit notes in {issue}. +

    +
    +
    +

    macOS permissions

    +

    + Full Disk Access for Safari cookies, Keychain access for cookie decryption and OAuth flows, and Files & Folders prompts when provider helpers read project directories. +

    +
    +
    +
    -