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
23 changes: 17 additions & 6 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# The website — the landing page at / and the documentation at /docs/, one
# Hugo site (Hextra vendored as a git submodule) — built with the same pinned
# Hugo version a developer runs locally. Independent of the Node toolchain,
# and of ci.yml: it runs only when website/ changes, and ci.yml ignores
# website/, so a docs-only commit builds the site and nothing else.
# Hugo version a developer runs locally, after the viz bundle it embeds at
# /city/ (so it needs pnpm, and a change to packages/viz is a change to the
# site). Independent of ci.yml: it runs only when the site's inputs change,
# and ci.yml ignores website/, so a docs-only commit builds the site and
# nothing else.

name: website

on:
push:
branches: [main]
paths: ["website/**", ".github/workflows/website.yml"]
paths: ["website/**", "packages/viz/**", ".github/workflows/website.yml"]
pull_request:
paths: ["website/**", ".github/workflows/website.yml"]
paths: ["website/**", "packages/viz/**", ".github/workflows/website.yml"]

permissions:
contents: read
Expand All @@ -29,7 +31,16 @@ jobs:
with:
hugo-version: "0.165.0"
extended: true
- run: cd website && hugo --minify --gc
- uses: pnpm/action-setup@v4
with:
run_install: false
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
# builds the viz bundle into static/city/ (the live city at /city/), then hugo
- run: pnpm --filter @codegraph/website build
- uses: actions/upload-artifact@v4
with:
name: website
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@ extractors/elixir/burrito_out/

# A BEAM crash dump is never a source file
erl_crash.dump

# The viz bundle `pnpm --filter @codegraph/website viz` copies beside the
# corpora cities; the JSONs are content, the bundle is a build product.
website/static/city/index.html
website/static/city/assets/

# Playwright screenshots taken while checking the website
/.playwright-mcp/
4 changes: 3 additions & 1 deletion packages/viz/src/cityView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export interface NavigatorTarget {
export interface CityViewOptions {
/** Start with buildings hidden — the `?landscape=1` of the standalone page. */
readonly landscape?: boolean;
/** Skip the once-per-browser Help auto-open — the `?help=0` of an embed. */
readonly autoHelp?: boolean;
/**
* When given, the details panel offers "Open in navigator". Returns whether
* the host could navigate: an id the navigator model does not know leaves an
Expand Down Expand Up @@ -384,7 +386,7 @@ export function mountCityView(host: HTMLElement, options: CityViewOptions = {}):
applyToggles();
loader.hidden = true;
header.hidden = false;
showHelpOnce();
if (options.autoHelp !== false) showHelpOnce();
}

/**
Expand Down
8 changes: 6 additions & 2 deletions packages/viz/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import { mountCityView } from "./cityView.js";
* `?src=URL` is explicit (loud on failure); `/city.json` is the dev-server /
* `codegraph history|replay --serve` convenience and stays quiet when nothing
* serves it — then drag & drop or the file picker take over. `?landscape=1`
* starts with buildings hidden.
* starts with buildings hidden; `?help=0` skips the first-visit Help popup
* (the website's iframe).
*/
const host = document.getElementById("app");
if (host === null) throw new Error("index.html is missing #app");
const params = new URLSearchParams(window.location.search);
const view = mountCityView(host, { landscape: params.get("landscape") === "1" });
const view = mountCityView(host, {
landscape: params.get("landscape") === "1",
autoHelp: params.get("help") !== "0",
});
const src = params.get("src");
void view.loadUrl(src ?? "city.json", src === null);
6 changes: 5 additions & 1 deletion pnpm-lock.yaml

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

1 change: 1 addition & 0 deletions website/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
public/
resources/
.hugo_build.lock
.wrangler/
1 change: 1 addition & 0 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ one deployment.
| `assets/css/colors_and_type.css` | the design system's token layer, copied from the Defsquare Design System project |
| `assets/css/landing.css` | layout only — every colour, size and space is a token |
| `static/fonts/` | IBM Plex Sans Condensed, self-hosted. EB Garamond and Fira Code come from Google Fonts, as the design system specifies |
| `static/city/` | the live cities: one laid-out `<corpus>-city.json` per corpus (committed) beside the `@codegraph/viz` bundle `pnpm run viz` copies in (gitignored). `/city/?src=<corpus>-city.json` opens one; the landing's corpora tabs embed them in iframes |
| `static/img/` | the codegraph logo (four variants), the generated city, the Defsquare logo, the favicon |
| `themes/hextra/` | the documentation theme, a git submodule |

Expand Down
22 changes: 17 additions & 5 deletions website/assets/css/landing.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ img { max-width: 100%; height: auto; }
gap: var(--space-12) var(--space-16);
align-items: start;
}
.intro .corpora { grid-column: 1 / -1; }
.intro .corpora { grid-column: 1 / -1; min-width: 0; } /* a grid item grows to its content otherwise, and the tab row would never scroll */
.intro__display {
font-family: var(--font-title);
font-weight: var(--weight-regular);
Expand Down Expand Up @@ -103,14 +103,26 @@ img { max-width: 100%; height: auto; }
padding: var(--space-8) 0;
border-top: 1px solid var(--color-border);
border-bottom: 1px solid var(--color-border);
}
/* One row, never wrapped: past the page width the tabs scroll sideways. */
.corpora__tabs {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: var(--space-4) var(--space-12);
gap: var(--space-12);
overflow-x: auto;
padding-bottom: var(--space-2);
}
.corpora__lead { font-size: var(--text-lg); color: var(--color-fg-muted); margin: 0; }
.corpora__item { font-family: var(--font-mono); font-size: var(--text-lg); color: var(--color-primary-300); }
.corpora__lead { font-size: var(--text-lg); color: var(--color-fg-muted); margin: 0; white-space: nowrap; }
.corpora__item { font-family: var(--font-mono); font-size: var(--text-lg); color: var(--color-primary-300); cursor: pointer; white-space: nowrap; padding-bottom: var(--space-1); }
.corpora__item small { font-family: var(--font-body); color: var(--color-fg-subtle); margin-left: var(--space-2); }
/* Tabs without JavaScript: a radio per corpus, its label the tab; the panels
are paired to their radio by the :has() rules the template generates. */
.corpora__radio { position: absolute; opacity: 0; width: 0; height: 0; }
.corpora__radio:checked + .corpora__item { color: var(--color-accent); border-bottom: 2px solid var(--color-accent); }
.corpora__radio:focus-visible + .corpora__item { outline: 2px solid var(--color-accent); outline-offset: 4px; }
.corpora__panel { display: none; margin-top: var(--space-6); }
.corpora__frame { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; background: var(--color-primary-900, #000); }
.corpora__note { margin: 0; color: var(--color-fg-muted); }

/* Essay rows: the design system's asymmetric two-column split. */
.row {
Expand Down
8 changes: 4 additions & 4 deletions website/content/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ corpora:
lead: "Run end to end on"
items:
- name: "google/gson"
note: "3,600 entities"
city: "city/?help=0&src=gson-city.json"
- name: "apache/commons-lang"
note: "15,000 entities"
city: "city/?help=0&src=apache-common-lang-city.json"
- name: "spring-petclinic"
note: "framework wiring"
city: "city/?help=0&src=spring-petclinic-city.json"
- name: "apache/fineract"
note: "127 MB model"
city: "city/?help=0&src=fineract-loan-city.json"
---
22 changes: 19 additions & 3 deletions website/layouts/landing/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,26 @@ <h1 class="intro__display">{{ .before }} <span class="gradient-text">{{ .gradien

{{ with .Params.corpora }}
<div class="corpora" aria-label="Corpora codegraph was verified on">
<p class="corpora__lead">{{ .lead }}</p>
{{ range .items }}
<span class="corpora__item">{{ .name }}<small>{{ .note }}</small></span>
<div class="corpora__tabs">
<p class="corpora__lead">{{ .lead }}</p>
{{ $checked := false }}
{{ range $i, $c := .items }}
<input class="corpora__radio" type="radio" name="corpus" id="corpus-{{ $i }}"{{ if and .city (not $checked) }} checked{{ $checked = true }}{{ end }}>
<label class="corpora__item" for="corpus-{{ $i }}">{{ .name }}<small>{{ .note }}</small></label>
{{ end }}
</div>
{{ range $i, $c := .items }}
<div class="corpora__panel" id="corpus-panel-{{ $i }}">
{{ with .city }}
<iframe class="corpora__frame" src="{{ . | relURL }}" loading="lazy" title="The code city of {{ $c.name }}"></iframe>
{{ else }}
<p class="corpora__note">{{ .name }}: {{ .note }}.</p>
{{ end }}
</div>
{{ end }}
{{/* The tab row scrolls on its own, so a panel is no longer the sibling of
its label: one :has() rule per corpus pairs them, generated here. */}}
<style>{{ range $i, $c := .items }}.corpora:has(#corpus-{{ $i }}:checked) #corpus-panel-{{ $i }}{display:block}{{ end }}</style>
</div>
{{ end }}
</section>
Expand Down
8 changes: 6 additions & 2 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
"private": true,
"description": "The Codegraph website: one Hugo site, one build. The landing page at / (themeless, Defsquare Design System) and the documentation at /docs/ (Hextra, vendored as a submodule). Builds when the hugo binary is on PATH; skips (with a notice) otherwise, so Node-only environments stay green.",
"scripts": {
"build": "if command -v hugo >/dev/null 2>&1; then hugo --minify --gc; else echo 'hugo not installed: website build skipped' >&2; fi",
"dev": "hugo server -D --port 1314",
"viz": "pnpm --filter @codegraph/viz build && rm -rf static/city/assets && cp -R ../packages/viz/dist/. static/city/",
"build": "pnpm run viz && if command -v hugo >/dev/null 2>&1; then hugo --minify --gc; else echo 'hugo not installed: website build skipped' >&2; fi",
"dev": "pnpm run viz && hugo server -D --port 1314",
"typecheck": "true",
"test": "true"
},
"devDependencies": {
"@codegraph/viz": "workspace:*"
}
}
Loading
Loading