Skip to content
Merged
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
28 changes: 22 additions & 6 deletions .github/actions/test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,33 @@ description: >
Is this commit good. Nothing is published here; a failure means the site is
wrong, not that the pipeline is.

Runs AFTER ../build, because everything it asserts is a property of ./dist. A
static site has two ways to be broken that matter -- it did not build, and it
built the wrong thing -- and only the second one needs a test.
Runs AFTER ../build. Everything it asserts about the site is a property of
./dist, except the lint-and-format gate -- a source assertion that goes
first, because it needs nothing from ./dist and is cheaper than the ones
that do. A static site has two ways to be broken that matter -- it did not
build, and it built the wrong thing -- and only the second one needs a dist
assertion.

The assertions are this site's own and differ from its siblings': how many
pages it emits, and what else has to be on them. That is the part worth
keeping per-repo.
The first step is the gate shared by every adopter; the rest are this
site's own and differ from its siblings': how many pages it emits, and what
else has to be on them. That is the part worth keeping per-repo.

runs:
using: composite
steps:
# Lint and format, against the biome.json copied verbatim from the
# archetype: one canonical configuration for every web repository, so
# style is a fleet property rather than a per-repo debate. The engine is
# @biomejs/biome, pinned as an exact devDependency in package.json and
# installed by ../build's frozen install, which runs before this action
# in the Test job -- `bun x` resolves that local binary, so the gate
# always runs the pinned version, never a resolved latest. A source
# assertion, so it goes first: it needs nothing from ./dist and is
# cheaper than the assertions that do.
- name: Lint and format are canonical
shell: bash
run: bun x biome check

# A build that emits nothing still "succeeds", so the artefacts are
# checked rather than the exit code. All three pages, because a broken
# route is invisible from the index alone.
Expand Down
55 changes: 55 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.14/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"includes": ["**", "!dist", "!.astro"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab",
"lineWidth": 120
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "always",
"trailingCommas": "all"
}
},
"json": {
"formatter": {
"indentStyle": "space",
"indentWidth": 2
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
},
"overrides": [
{
"includes": ["**/*.astro"],
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": "off"
}
}
}
}
]
}
19 changes: 19 additions & 0 deletions bun.lock

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
},
"devDependencies": {
"@astrojs/check": "^0.9.10",
"@biomejs/biome": "2.5.14",
"@types/primer__octicons": "^19.21.0",
"typescript": "6"
}
Expand Down
3 changes: 1 addition & 2 deletions src/layouts/Full.astro
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ const {
} = Astro.props;

const canonical = new URL(Astro.url.pathname, 'https://avior.studio');
const icon = (name: keyof typeof octicons, size = 16) =>
octicons[name].toSVG({ width: size, height: size });
const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ width: size, height: size });

const nav = [
{ href: '/devtools', label: 'Devtools' },
Expand Down
9 changes: 4 additions & 5 deletions src/pages/devtools.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
import Full from '../layouts/Full.astro';
import Entry from '../components/Entry.astro';
import octicons from '@primer/octicons';
import Entry from '../components/Entry.astro';
import Full from '../layouts/Full.astro';

const icon = (name: keyof typeof octicons, size = 16) =>
octicons[name].toSVG({ width: size, height: size });
const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ width: size, height: size });

// The addons GDAM was built to carry. Listed alphabetically rather than by
// importance: fourteen is enough that a reader needs to be able to find one,
Expand Down Expand Up @@ -54,7 +53,7 @@ const addons = [
{
name: 'gd-pocketbase',
tagline: 'PocketBase auth and session primitives',
copy: 'Normalizes either a native <code>{token, record}</code> response or a backend proxy\'s <code>{access_token, user}</code> into one shape, then handles JWT expiry, persisted sessions and stable client IDs. Games keep HTTP transport and refresh policy; no superuser credential ever needs to reach the client.',
copy: "Normalizes either a native <code>{token, record}</code> response or a backend proxy's <code>{access_token, user}</code> into one shape, then handles JWT expiry, persisted sessions and stable client IDs. Games keep HTTP transport and refresh policy; no superuser credential ever needs to reach the client.",
},
{
name: 'gd-redis',
Expand Down
7 changes: 3 additions & 4 deletions src/pages/games.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
import Full from '../layouts/Full.astro';
import Entry from '../components/Entry.astro';
import octicons from '@primer/octicons';
import Entry from '../components/Entry.astro';
import Full from '../layouts/Full.astro';

const icon = (name: keyof typeof octicons, size = 16) =>
octicons[name].toSVG({ width: size, height: size });
const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ width: size, height: size });
---

<Full
Expand Down
5 changes: 2 additions & 3 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
---
import Full from '../layouts/Full.astro';
import octicons from '@primer/octicons';
import Full from '../layouts/Full.astro';

const icon = (name: keyof typeof octicons, size = 16) =>
octicons[name].toSVG({ width: size, height: size });
const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ width: size, height: size });

// The two doors, and what is actually behind each one. Naming the contents
// here rather than saying "and more" means the index never promises a page
Expand Down
49 changes: 40 additions & 9 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,50 @@
--bone: #f7f2e9;
--quiet: #a29d97;
--faint: #7c7772;
--sans: system-ui, -apple-system, 'Segoe UI', Roboto, Ubuntu, Cantarell, 'Helvetica Neue', Arial, sans-serif;
--mono: ui-monospace, 'SF Mono', 'Cascadia Code', 'JetBrains Mono', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
--sans: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif;
--mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
font-family: var(--sans);
background: var(--ink);
color: var(--paper);
font-synthesis: none;
color-scheme: dark;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; background: var(--ink); }
body { min-width: 320px; min-height: 100svh; margin: 0; background: var(--ink); text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; }
button, input, textarea, select { font: inherit; }
img { max-width: 100%; height: auto; }
::selection { background: var(--bone); color: var(--ink); }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; transition-duration: .01ms !important; } }
* {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
background: var(--ink);
}
body {
min-width: 320px;
min-height: 100svh;
margin: 0;
background: var(--ink);
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
button,
input,
textarea,
select {
font: inherit;
}
img {
max-width: 100%;
height: auto;
}
::selection {
background: var(--bone);
color: var(--ink);
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}