commit 6fc834a27d36dac34f6ef7597e8a09463643587b Author: Breadway Date: Wed Jul 22 11:57:53 2026 +0800 random commit message, read it yourself diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..364fdec --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +public/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cb2aee2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Breadway Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..18d363e --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# breadway.dev + +Personal portfolio site — built with [Zola](https://www.getzola.org/) and the Bread Design System. + +## Developing + +```bash +zola serve +``` + +## Building + +```bash +zola build +``` + +Output goes to `public/`. diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..4792bb2 --- /dev/null +++ b/config.toml @@ -0,0 +1,7 @@ +base_url = "https://breadway.dev" +title = "breadway.dev" +description = "Projects by Breadway" +compile_sass = false +minify_html = true +generate_feeds = false +build_search_index = false diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..ef6083b --- /dev/null +++ b/content/_index.md @@ -0,0 +1,3 @@ ++++ +template = "index.html" ++++ diff --git a/data/projects.toml b/data/projects.toml new file mode 100644 index 0000000..e86230d --- /dev/null +++ b/data/projects.toml @@ -0,0 +1,154 @@ +[[category]] +name = "Bread Desktop Ecosystem" + +[[category.project]] +name = "bos" +role = "distro" +lang = "rust" +description = "Arch-based Hyprland desktop distribution shipping the whole bread ecosystem preconfigured, via a Calamares installer." +tags = ["Lua", "Shell"] +source = "https://git.breadway.dev/Breadway/bos" +flagship = true + +[[category.project]] +name = "bos-settings" +role = "settings app" +lang = "rust" +description = "GTK4 system settings app for BOS — configures every bread app plus core system settings." +tags = ["GTK4"] +source = "https://git.breadway.dev/Breadway/bos-settings" + +[[category.project]] +name = "bread" +role = "daemon" +lang = "rust" +description = "Reactive automation daemon for Linux desktops — reacts to system state via a Lua scripting API over Hyprland, udev, power, network, and Bluetooth events." +tags = ["Lua"] +source = "https://git.breadway.dev/Breadway/bread" +flagship = true + +[[category.project]] +name = "bread-ecosystem" +role = "registry" +lang = "rust" +description = "Package registry (\"bakery\") distributing the bread-ecosystem tools with a one-line installer, plus the shared bread-theme crate." +tags = [] +source = "https://git.breadway.dev/Breadway/bread-ecosystem" + +[[category.project]] +name = "breadbar" +role = "status bar" +lang = "rust" +description = "Minimal Hyprland status bar and notification daemon — workspaces, media widget, clock, system tray, OSDs." +tags = ["GTK4"] +source = "https://git.breadway.dev/Breadway/breadbar" +flagship = true + +[[category.project]] +name = "breadbox" +role = "launcher" +lang = "rust" +description = "GTK4 app launcher for Hyprland and Wayland." +tags = ["GTK4"] +source = "https://git.breadway.dev/Breadway/breadbox" + +[[category.project]] +name = "breadclip" +role = "clipboard" +lang = "rust" +description = "Wayland clipboard history manager for Hyprland — daemon plus a GTK4 popup." +tags = ["GTK4", "SQLite"] +source = "https://git.breadway.dev/Breadway/breadclip" + +[[category.project]] +name = "breadcrumbs" +role = "wifi daemon" +lang = "rust" +description = "Profile-aware Wi-Fi state machine with Tailscale exit-node management and a self-healing watch daemon." +tags = [] +source = "https://git.breadway.dev/Breadway/breadcrumbs" + +[[category.project]] +name = "breadlock" +role = "locker" +lang = "rust" +description = "Session locker and greetd greeter for Hyprland — a replacement for hyprlock and tuigreet." +tags = [] +source = "https://git.breadway.dev/Breadway/breadlock" + +[[category.project]] +name = "breadmon" +role = "monitor tool" +lang = "rust" +description = "Terminal UI monitor manager for Hyprland — position, configure, and mirror displays live via hyprctl." +tags = [] +source = "https://git.breadway.dev/Breadway/breadmon" + +[[category.project]] +name = "breadpad" +role = "scratchpad" +lang = "rust" +description = "Quick-capture scratchpad and note viewer for Hyprland, with AI-powered classification, reminders, and snooze." +tags = [] +source = "https://git.breadway.dev/Breadway/breadpad" + +[[category.project]] +name = "breadpaper" +role = "wallpaper" +lang = "rust" +description = "Wallpaper manager for the bread desktop — sets wallpaper, generates a pywal palette, and reloads the bread theme." +tags = [] +source = "https://git.breadway.dev/Breadway/breadpaper" + +[[category.project]] +name = "breadsearch" +role = "search" +lang = "rust" +description = "Semantic document search for BOS — embeds and indexes docs, serves ranked results via a GTK4 overlay." +tags = ["Python", "ONNX"] +source = "https://git.breadway.dev/Breadway/breadsearch" + +[[category.project]] +name = "breadshot" +role = "screenshot" +lang = "rust" +description = "Wayland screenshot utility for the bread ecosystem, wrapping grim/slurp/wl-copy with Hyprland-aware geometry." +tags = [] +source = "https://git.breadway.dev/Breadway/breadshot" + +[[category]] +name = "Hardware & Firmware" + +[[category.project]] +name = "ESP32-P2P-Laser-Tag" +role = "firmware" +lang = "c++" +description = "Peer-to-peer laser tag firmware for ESP32 nodes — IR transmit/receive, HMAC-secured packets, per-device IDs." +tags = ["ESP32"] +source = "https://github.com/Breadway/ESP32-P2P-Laser-Tag" + +[[category.project]] +name = "redox-layout-viewer" +role = "viewer" +lang = "rust" +description = "Reads a Redox keyboard's live Vial/VIA layout over raw HID and renders it as an on-screen keyboard with layer tracking." +tags = [] +source = "https://github.com/Breadway/redox-layout-viewer" + +[[category.project]] +name = "vial-qmk" +role = "firmware fork" +lang = "c" +description = "Personal fork of Vial QMK, pruned down to just the Redox keyboard build." +tags = ["QMK"] +source = "https://github.com/Breadway/vial-qmk" + +[[category]] +name = "Misc & Utilities" + +[[category.project]] +name = "mathspace-dark-mode" +role = "extension" +lang = "javascript" +description = "Browser extension that adds a dark-mode theme to Mathspace." +tags = [] diff --git a/static/css/base.css b/static/css/base.css new file mode 100644 index 0000000..c248060 --- /dev/null +++ b/static/css/base.css @@ -0,0 +1,101 @@ +@font-face { + font-family: "Varela Round"; + src: url("/fonts/varela-round-regular.woff2") format("woff2"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "JetBrains Mono"; + src: url("/fonts/jetbrains-mono-regular.woff2") format("woff2"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "JetBrains Mono"; + src: url("/fonts/jetbrains-mono-bold.woff2") format("woff2"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +* { + box-sizing: border-box; +} + +html, body { + margin: 0; + padding: 0; +} + +body { + background: var(--bg); + color: var(--fg); + font-family: var(--font-sans); + font-size: 15px; + line-height: 1.65; +} + +h1, h2 { + font-weight: 400; + margin: 0; +} + +a { + color: var(--accent); + text-decoration: none; +} + +ul { + list-style: none; + margin: 0; + padding: 0; +} + +::selection { + background: var(--accent-dim); + color: var(--accent); +} + +:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; + border-radius: var(--radius-tertiary); +} + +html { + scrollbar-color: var(--surface-3) var(--bg); + scrollbar-width: thin; +} + +::-webkit-scrollbar { + width: 10px; +} + +::-webkit-scrollbar-track { + background: var(--bg); +} + +::-webkit-scrollbar-thumb { + background: var(--surface-3); + border-radius: var(--radius-pill); + border: 2px solid var(--bg); +} + +::-webkit-scrollbar-thumb:hover { + background: var(--accent-line); +} + +@keyframes rise { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/static/css/layout.css b/static/css/layout.css new file mode 100644 index 0000000..9898842 --- /dev/null +++ b/static/css/layout.css @@ -0,0 +1,318 @@ +html { + background-color: var(--bg); + background-image: + url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E"), + radial-gradient(680px 380px at 15% -120px, var(--bg-glow), transparent 65%), + radial-gradient(520px 320px at 100% 0%, rgba(250, 179, 135, 0.08), transparent 60%); + background-blend-mode: overlay, normal, normal; + background-attachment: fixed; +} + +body { + max-width: 760px; + margin: 0 auto; + padding: 64px 24px 40px; +} + +/* ---------- Header ---------- */ + +.site-header { + margin-bottom: 40px; + animation: rise 550ms ease-out both; +} + +.eyebrow { + display: block; + font-family: var(--font-mono); + font-size: 12px; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--accent); + margin-bottom: var(--space-lg); +} + +.brand { + display: flex; + align-items: center; + gap: var(--space-md); +} + +.mark { + color: var(--accent); + flex: none; +} + +.site-header h1 { + font-family: var(--font-mono); + font-weight: 700; + font-size: clamp(30px, 6vw, 42px); + letter-spacing: -0.01em; + color: var(--fg); +} + +.tagline { + color: var(--muted); + font-size: 15px; + max-width: 46ch; + margin: var(--space-lg) 0 0; +} + +.stats { + font-family: var(--font-mono); + font-size: 12px; + color: var(--muted); + margin: var(--space-sm) 0 0; + font-variant-numeric: tabular-nums; +} + +.stats strong { + color: var(--accent); + font-weight: 700; +} + +/* ---------- Featured ---------- */ + +.featured { + margin-bottom: 48px; + animation: rise 550ms ease-out both; + animation-delay: 30ms; +} + +.featured-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-md); +} + +.feature-card { + padding: var(--space-lg); + background: rgba(24, 24, 37, 0.72); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border: 1px solid var(--border); + border-left: 3px solid var(--accent); + border-radius: var(--radius-primary); + box-shadow: var(--shadow-ambient); +} + +.feature-card .entry-name { + font-size: 16px; +} + +.feature-card .entry-desc { + margin-bottom: 0; + font-size: 13px; +} + +/* ---------- Category groups ---------- */ + +.group { + margin-bottom: 48px; + animation: rise 550ms ease-out both; +} + +.group:nth-of-type(1) { animation-delay: 60ms; } +.group:nth-of-type(2) { animation-delay: 120ms; } +.group:nth-of-type(3) { animation-delay: 180ms; } +.group:nth-of-type(4) { animation-delay: 240ms; } + +.cat-ecosystem { --cat-color: var(--accent); } +.cat-hardware { --cat-color: #74c7ec; } +.cat-misc { --cat-color: #a6e3a1; } + +.group-head { + position: relative; + display: flex; + align-items: center; + gap: var(--space-sm); + padding-bottom: var(--space-md); + margin-bottom: var(--space-lg); +} + +.group-head::after { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 1px; + background: linear-gradient(90deg, var(--cat-color, var(--border)), transparent 85%); + opacity: 0.5; +} + +.group-icon { + color: var(--cat-color, var(--accent)); + flex: none; +} + +.group h2 { + font-family: var(--font-mono); + font-size: 13px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--fg); +} + +.group-count { + font-family: var(--font-mono); + font-size: 11px; + color: var(--cat-color, var(--muted)); + background: var(--surface-2); + border: 1px solid var(--border); + border-radius: var(--radius-pill); + padding: 1px var(--space-sm); + font-variant-numeric: tabular-nums; +} + +/* ---------- Entries ---------- */ + +.entries { + display: flex; + flex-direction: column; + gap: var(--space-md); +} + +.entry { + position: relative; + padding: var(--space-lg); + background: rgba(24, 24, 37, 0.72); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border: 1px solid var(--border); + border-left: 3px solid transparent; + border-radius: var(--radius-primary); + box-shadow: var(--shadow-ambient); + transition: border-color 150ms ease, background 150ms ease, box-shadow 150ms ease; +} + +.entry:hover { + border-color: var(--border); + border-left-color: var(--cat-color, var(--accent)); + background: rgba(36, 36, 58, 0.78); + box-shadow: var(--shadow-hover); +} + +.entry-head { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: var(--space-md); +} + +.entry-name { + font-family: var(--font-mono); + font-weight: 700; + font-size: 15px; + color: var(--fg); +} + +.entry-name::before { + content: "./"; + color: var(--muted); + font-weight: 400; +} + +.entry-meta { + font-family: var(--font-mono); + font-size: 11px; + color: var(--muted); + margin-top: 2px; +} + +.entry-meta .lang { + color: var(--cat-color, var(--accent)); +} + +.entry-meta .sep { + margin: 0 var(--space-xs); + opacity: 0.6; +} + +.entry-source { + font-family: var(--font-mono); + font-size: 12px; + color: var(--muted); + white-space: nowrap; + padding: 3px var(--space-sm); + border-radius: var(--radius-pill); + border: 1px solid var(--border); + transition: color 150ms ease, border-color 150ms ease, background 150ms ease; +} + +.entry-source::after { + content: " \2192"; +} + +.entry-source:hover { + color: var(--cat-color, var(--accent)); + border-color: var(--accent-line); + background: var(--accent-dim); +} + +.entry-desc { + margin: var(--space-sm) 0 var(--space-md); + color: var(--muted); +} + +.tags { + display: flex; + flex-wrap: wrap; + gap: var(--space-xs); +} + +.tag { + font-family: var(--font-mono); + font-size: 11px; + color: var(--accent); + background: var(--accent-dim); + border: 1px solid var(--accent-line); + border-radius: var(--radius-pill); + padding: 2px var(--space-sm); +} + +/* ---------- Footer ---------- */ + +.site-footer { + margin-top: 56px; + padding-top: var(--space-lg); + border-top: 1px solid var(--border); + display: flex; + justify-content: space-between; + align-items: baseline; + font-family: var(--font-mono); + color: var(--muted); + font-size: 12px; +} + +@media (max-width: 640px) { + body { + padding: 40px 16px 32px; + } + + .featured-grid { + grid-template-columns: 1fr; + } + + .entry-head { + flex-direction: column; + gap: var(--space-sm); + } + + .site-footer { + flex-direction: column; + gap: var(--space-xs); + } +} + +@media (prefers-reduced-motion: reduce) { + .site-header, + .featured, + .group { + animation: none; + } + + .entry { + transition: none; + } +} diff --git a/static/css/tokens.css b/static/css/tokens.css new file mode 100644 index 0000000..16f76c3 --- /dev/null +++ b/static/css/tokens.css @@ -0,0 +1,30 @@ +:root { + --bg: #1e1e2e; + --bg-glow: #2a2440; + --fg: #cdd6f4; + --surface: #181825; + --surface-2: #24243a; + --surface-3: #2e2e46; + --accent: #fab387; + --accent-dim: rgba(250, 179, 135, 0.12); + --accent-line: rgba(250, 179, 135, 0.28); + --muted: #9399b2; + --border: #313147; + + --font-sans: "Varela Round", sans-serif; + --font-mono: "JetBrains Mono", ui-monospace, monospace; + + --space-xs: 4px; + --space-sm: 8px; + --space-md: 12px; + --space-lg: 16px; + --space-xl: 20px; + + --radius-primary: 8px; + --radius-secondary: 6px; + --radius-tertiary: 4px; + --radius-pill: 999px; + + --shadow-ambient: 0 1px 2px rgba(0, 0, 0, 0.24); + --shadow-hover: 0 12px 28px -10px rgba(250, 179, 135, 0.28); +} diff --git a/static/favicon.svg b/static/favicon.svg new file mode 100644 index 0000000..f1ac294 --- /dev/null +++ b/static/favicon.svg @@ -0,0 +1,4 @@ + + + b + diff --git a/static/fonts/jetbrains-mono-bold.woff2 b/static/fonts/jetbrains-mono-bold.woff2 new file mode 100644 index 0000000..e68aa44 Binary files /dev/null and b/static/fonts/jetbrains-mono-bold.woff2 differ diff --git a/static/fonts/jetbrains-mono-regular.woff2 b/static/fonts/jetbrains-mono-regular.woff2 new file mode 100644 index 0000000..a099c06 Binary files /dev/null and b/static/fonts/jetbrains-mono-regular.woff2 differ diff --git a/static/fonts/varela-round-regular.woff2 b/static/fonts/varela-round-regular.woff2 new file mode 100644 index 0000000..9e15784 Binary files /dev/null and b/static/fonts/varela-round-regular.woff2 differ diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..0d418f7 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,16 @@ + + + + + +{% block title %}breadway.dev{% endblock title %} + + + + + + + +{% block content %}{% endblock content %} + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..7360096 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,104 @@ +{% extends "base.html" %} + +{% block content %} +{% set data = load_data(path="data/projects.toml") %} +{% set_global total = 0 %} +{% set_global flagships = [] %} +{% for category in data.category %} + {% set n = category.project | length %} + {% set_global total = total + n %} + {% for p in category.project %} + {% if p.flagship %}{% set_global flagships = flagships | concat(with=[p]) %}{% endif %} + {% endfor %} +{% endfor %} + + + + + +
+{% for category in data.category %} + {% if category.name == "Bread Desktop Ecosystem" %}{% set cat_class = "cat-ecosystem" %} + {% elif category.name == "Hardware & Firmware" %}{% set cat_class = "cat-hardware" %} + {% else %}{% set cat_class = "cat-misc" %}{% endif %} +
+
+ {% if category.name == "Bread Desktop Ecosystem" %} + + {% elif category.name == "Hardware & Firmware" %} + + {% else %} + + {% endif %} +

{{ category.name }}

+ {{ category.project | length }} +
+
    + {% for p in category.project %} + {% if not p.flagship %} +
  • +
    + {{ p.name }} + {% if p.source %}source{% endif %} +
    + +

    {{ p.description }}

    + {% if p.tags and p.tags | length > 0 %} +
    + {% for t in p.tags %}{{ t }}{% endfor %} +
    + {% endif %} +
  • + {% endif %} + {% endfor %} +
+
+{% endfor %} +
+ + +{% endblock content %}