Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 31 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ jobs:
- name: Cache cargo registry and target
uses: Swatinem/rust-cache@v2

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"

- name: Install npm dependencies (UnoCSS)
run: npm ci

- name: Install Trunk
run: |
wget -qO- https://github.com/trunk-rs/trunk/releases/download/v0.21.14/trunk-x86_64-unknown-linux-gnu.tar.gz \
Expand Down Expand Up @@ -195,10 +204,31 @@ jobs:
fi
}
check 'odp-*_bg.wasm' 'wasm' 230
check 'tailwind-*.css' 'tailwind CSS' 10
check 'base-*.css' 'base CSS' 5
check 'uno.generated-*.css' 'UnoCSS bundle' 10
check 'repo_graph.css' 'repo_graph CSS' 2
check 'odp-*.js' 'wasm-bindgen JS' 20
if [ "$fail" -ne 0 ]; then
echo "::error::One or more assets exceeded their size budget."
exit 1
fi

- name: Critical icon classes present
# UnoCSS preset-icons silently emits nothing when an icon class
# cannot be resolved (missing iconify pack, typo, etc.), which
# would ship a working build with invisible buttons. Assert that
# the icons we actually rely on made it into the generated CSS.
run: |
set -euo pipefail
css=$(ls dist/uno.generated-*.css | head -n1)
required="i-lucide-moon i-lucide-sun i-lucide-menu i-lucide-x i-lucide-arrow-right i-lucide-github"
missing=""
for cls in $required; do
grep -qF ".$cls" "$css" || missing="$missing $cls"
done
if [ -n "$missing" ]; then
echo "::error::UnoCSS did not emit rules for:$missing"
echo "::error::Likely cause: missing iconify pack in node_modules (run 'npm ci'), or class typo in src/."
exit 1
fi
echo "OK: all required icon utilities present in $css"
9 changes: 9 additions & 0 deletions .github/workflows/cloudflare-pages-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ jobs:
# - name: Download and install tailwindcss binary
# run: npm install -D tailwindcss && npx tailwindcss -i <INPUT/PATH.css> -o <OUTPUT/PATH.css> # run tailwind

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"

- name: Install npm dependencies (UnoCSS)
run: npm ci

- name: Download and install Trunk binary
run: wget -qO- https://github.com/trunk-rs/trunk/releases/download/v0.21.14/trunk-x86_64-unknown-linux-gnu.tar.gz | tar -xzf-

Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
/target
/dist/

# UnoCSS pipeline -- generated stylesheet and Node tooling are not
# committed; consumers run `npm install` once and `trunk build` after.
/node_modules/
/style/uno.generated.css

45 changes: 45 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ console_error_panic_hook = "0.1.7"
leptos = { version = "0.8.2", features = ["csr"] }
leptos_meta = "0.8.2"
leptos_router = "0.8.2"
unocss-classes = "2"
wasm-bindgen = "0.2.100"
# All the web-sys features we use directly (Window, Document, Console)
# are already enabled transitively by leptos's `csr` feature, so we
# don't need to opt into them again here. We still depend on web-sys
# directly for the `web_sys::js_sys` re-export and `web_sys::window()`
# in `repo_view.rs`.
web-sys = "0.3.77"
web-sys = { version = "0.3.77", features = ["Storage", "MediaQueryList"] }

[dev-dependencies]
js-sys = "0.3"
Expand Down
130 changes: 130 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# OpenDevicePartnership.github.io

Website for the Open Device Partnership, built with Rust, Leptos, and Trunk.

## Prerequisites

Install these once on your machine:

1. **Rust** (nightly toolchain) — [https://rustup.rs/](https://rustup.rs/)

```cmd
rustup toolchain install nightly
rustup default nightly
```

2. **WebAssembly target**

```cmd
rustup target add wasm32-unknown-unknown
```

3. **Trunk** — bundles the Rust → WASM app and serves it.

```cmd
cargo binstall trunk
:: or
cargo install trunk
```

4. **Node.js 20+** — needed by the UnoCSS pipeline that Trunk invokes as a
pre-build hook (see `Trunk.toml [[hooks]]`). Install from
[https://nodejs.org/](https://nodejs.org/) or via your package manager.

## First-time setup

After cloning, install the JavaScript dependencies that UnoCSS needs:

```cmd
npm ci
```

> **Important:** use `npm ci` (not `npm install`) so the lockfile is honored
> exactly. The `@iconify-json/lucide` package is required for every icon on
> the site (theme toggle, mobile menu, card arrows, etc.). If it is missing,
> UnoCSS silently emits no CSS for icon utilities and buttons appear empty
> with **no build error**. CI guards against this with an explicit
> "Critical icon classes present" check, but locally you must keep
> `node_modules/` in sync with `package-lock.json`.

If you ever see invisible icons or hit `i-lucide-*` classes that don't
render, the fix is almost always:

```cmd
npm ci
trunk build
```

## Development

Run the dev server:

```cmd
trunk serve
```

This will:

- Run the UnoCSS pre-build hook (`npm run build:css`) to regenerate
`style/uno.generated.css` from `src/**/*.rs` and `index.html`
- Build the project in debug mode
- Start a development server at <http://127.0.0.1:3000>
- Watch for file changes and auto-reload the browser

If you are editing CSS classes heavily and want a tighter loop, run the
UnoCSS watcher alongside `trunk serve` in a second terminal:

```cmd
npm run watch:css
```

## Production build

```cmd
trunk build --release
```

The optimized output is written to `dist/`. This is exactly what the
Cloudflare Pages deploy workflow runs.

## Tests and lint

```cmd
cargo test --all-targets
cargo fmt --all -- --check
cargo clippy --target wasm32-unknown-unknown --all-targets -- -D warnings
leptosfmt --check src
```

Browser-side tests (requires `wasm-pack` and Firefox):

```cmd
wasm-pack test --headless --firefox --test wasm
```

## Project structure

- `src/` — Rust source code
- `components/` — reusable UI components
- `pages/` — page components
- `data/` — content modules (projects, announcements, etc.)
- `style/` — CSS files
- `base.css` — design tokens and reset (single source of truth for colors,
type, spacing). Uses `color-scheme: light dark` + `light-dark()` so
each token is defined once and the active theme is chosen automatically.
- `repo_graph.css` — styles for the lazy-loaded D3 dependency graph.
- `uno.generated.css` — generated by UnoCSS; do not edit by hand.
- `public/` — static assets (images, fonts).
- `index.html` — main HTML template (loaded by Trunk).
- `Trunk.toml` — Trunk configuration; declares the `npm run build:css`
pre-build hook.
- `unocss.config.ts` — UnoCSS configuration; declares the icon presets,
design-token aliases, and scan globs.
- `package.json` / `package-lock.json` — UnoCSS + iconify dependencies.
- `Cargo.toml` — Rust dependencies.

## Technology stack

- **Leptos** — reactive web framework for Rust (CSR build)
- **Trunk** — WASM web application bundler
- **UnoCSS** — atomic CSS engine (Wind3 preset + iconify lucide icons)
63 changes: 0 additions & 63 deletions Readme.md

This file was deleted.

23 changes: 21 additions & 2 deletions Trunk.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ minify = "always"
[watch]
# Paths to watch. The `build.target`'s parent folder is watched by default.
watch = []
# Paths to ignore.
ignore = []
# Paths to ignore. The UnoCSS pre-build hook writes
# `style/uno.generated.css`; without this, Trunk would see that write
# and immediately re-trigger another build, looping forever. Same for
# `node_modules` (npm install churns it on its own schedule) and
# `dist` (Trunk's own output).
ignore = ["style/uno.generated.css", "node_modules", "dist"]

[serve]
# The address to serve on.
Expand Down Expand Up @@ -60,3 +64,18 @@ open = false
# tls_cert_path = "self_signed_certs/cert.pem"
# Additional headers to send. NOTE: header names must be valid HTTP headers.
# headers = { "X-Foo" = "bar" }

# UnoCSS pre-build hook.
#
# We use the `unocss-classes` Rust crate (`uno!` macro) to author
# class strings inline in `view!` blocks, then ask `@unocss/cli` to
# scan src/**/*.rs and emit `style/uno.generated.css`. Trunk runs the
# hook before compiling Rust, so the generated CSS is in place by the
# time the asset graph is built.
#
# The CLI is provided by `package.json`. Run `npm install` once after
# pulling, then Trunk handles the rest.
[[hooks]]
stage = "pre_build"
command = "npm"
command_arguments = ["run", "--silent", "build:css"]
Loading
Loading