@grove-dev/astro 0.2.16 → 0.2.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,8 +40,8 @@ export const STATUS_DISPLAY = {
40
40
  };
41
41
  export function statusDisplay(s) {
42
42
  if (!s)
43
- return STATUS_DISPLAY.unknown;
44
- return STATUS_DISPLAY[s] ?? STATUS_DISPLAY.unknown;
43
+ return STATUS_DISPLAY.unknown ?? "";
44
+ return STATUS_DISPLAY[s] ?? STATUS_DISPLAY.unknown ?? "";
45
45
  }
46
46
  // ── Lens ids (the curated tabs on /items) ────────────────────────────
47
47
  export const LENS_DISPLAY = {
@@ -59,7 +59,7 @@ export const LENS_DISPLAY = {
59
59
  };
60
60
  export function lensDisplay(id) {
61
61
  if (!id)
62
- return LENS_DISPLAY.all;
62
+ return LENS_DISPLAY.all ?? "All";
63
63
  return LENS_DISPLAY[id] ?? id;
64
64
  }
65
65
  // ── Sort ids (the /items sort dropdown) ──────────────────────────────
@@ -72,7 +72,7 @@ export const SORT_DISPLAY = {
72
72
  };
73
73
  export function sortDisplay(id) {
74
74
  if (!id)
75
- return SORT_DISPLAY["recently-updated"];
75
+ return SORT_DISPLAY["recently-updated"] ?? "";
76
76
  return SORT_DISPLAY[id] ?? id;
77
77
  }
78
78
  export function prettySlug(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/lib/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG;IAC3D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAUA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,GAAE,MAAW,GAAG,MAAM,GAAG,IAAI,CAGxF"}
1
+ {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/lib/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG;IAC3D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CASA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,GAAE,MAAW,GAAG,MAAM,GAAG,IAAI,CAGxF"}
package/dist/lib/repo.js CHANGED
@@ -15,10 +15,9 @@ export function getOwnerAndRepoFromRepoUrl(repoUrl) {
15
15
  const m = repoUrl.match(/github\.com\/([^/]+)\/([^/?#]+)/);
16
16
  if (!m)
17
17
  return { owner: null, repo: null };
18
- return {
19
- owner: m[1],
20
- repo: m[2].replace(/\.git$/, ""),
21
- };
18
+ const owner = m[1] ?? null;
19
+ const repo = m[2]?.replace(/\.git$/, "") ?? null;
20
+ return { owner, repo };
22
21
  }
23
22
  /**
24
23
  * Build a GitHub avatar URL for a given owner.
@@ -1 +1 @@
1
- {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/lib/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IAIxD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IACD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC3D,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3C,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACX,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;KACjC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAoB,EAAE,OAAe,EAAE;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,yCAAyC,KAAK,UAAU,IAAI,EAAE,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/lib/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IAIxD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IACD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC3D,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC;IACjD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAoB,EAAE,OAAe,EAAE;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,yCAAyC,KAAK,UAAU,IAAI,EAAE,CAAC;AACxE,CAAC"}
@@ -16,9 +16,9 @@ export type IndexFilters = {
16
16
  /** A curated lens (e.g. "good-to-learn", "production-like"). Single value. */
17
17
  lens?: string;
18
18
  /** Sort order. Single value, defaults to "recently-updated". */
19
- sort?: IndexSort;
19
+ sort?: IndexSort | undefined;
20
20
  /** 1-based page number. */
21
- page?: number;
21
+ page?: number | undefined;
22
22
  };
23
23
  /** Available sort orders, in UI order. */
24
24
  export declare const SORT_OPTIONS: readonly [{
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;EAMf,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAmB/D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,eAAe,GAAG,YAAY,CAsBzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,YAAY,GAAG,eAAe,CAaxE;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO,CAWrD;AAED,2EAA2E;AAC3E,eAAO,MAAM,SAAS,KAAoB,CAAC;AAyB3C,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,WAAW,EAAE,CA8B9E;AAED,iDAAiD;AACjD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,CAAC,EAAE,CAG/E;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,MAAM,CAE1E;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,SAAS,CAExD;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,YAAY,GAAG,WAAW,EAAE,CA8FlF;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,YAAY,GACd;IAAE,GAAG,EAAE,MAAM,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAqC7D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,CAAC,EAAE,YAAY,EACf,GAAG,EAAE,MAAM,YAAY,EACvB,KAAK,EAAE,MAAM,GACZ,YAAY,CAYd;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;EAgC/C"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;EAMf,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAmB/D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,eAAe,GAAG,YAAY,CAwBzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,YAAY,GAAG,eAAe,CAaxE;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO,CAWrD;AAED,2EAA2E;AAC3E,eAAO,MAAM,SAAS,KAAoB,CAAC;AAyB3C,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,WAAW,EAAE,CA8B9E;AAED,iDAAiD;AACjD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,CAAC,EAAE,CAG/E;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,MAAM,CAE1E;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,SAAS,CAExD;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,YAAY,GAAG,WAAW,EAAE,CA8FlF;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,YAAY,GACd;IAAE,GAAG,EAAE,MAAM,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAqC7D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,CAAC,EAAE,YAAY,EACf,GAAG,EAAE,MAAM,YAAY,EACvB,KAAK,EAAE,MAAM,GACZ,YAAY,CAoBd;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;EAgC/C"}
@@ -35,17 +35,19 @@ export function filtersFromSearchParams(sp) {
35
35
  : undefined;
36
36
  const rawPage = Number(sp.get(KEYS.page));
37
37
  const page = Number.isFinite(rawPage) && rawPage >= 1 ? Math.floor(rawPage) : undefined;
38
+ const q = sp.get(KEYS.q);
39
+ const lens = sp.get(KEYS.lens);
38
40
  return {
39
- q: sp.get(KEYS.q) ?? undefined,
41
+ ...(q !== null ? { q } : {}),
40
42
  stacks: sp.getAll(KEYS.stacks).filter(Boolean),
41
43
  platforms: sp.getAll(KEYS.platforms).filter(Boolean),
42
44
  categories: sp.getAll(KEYS.categories).filter(Boolean),
43
45
  labels: sp.getAll(KEYS.labels).filter(Boolean),
44
46
  licenses: sp.getAll(KEYS.licenses).filter(Boolean),
45
47
  statuses: sp.getAll(KEYS.statuses).flatMap((s) => s.split(",")).filter(Boolean),
46
- lens: sp.get(KEYS.lens) ?? undefined,
47
- sort,
48
- page,
48
+ ...(lens !== null ? { lens } : {}),
49
+ ...(sort !== undefined ? { sort } : {}),
50
+ ...(page !== undefined ? { page } : {}),
49
51
  };
50
52
  }
51
53
  /**
@@ -311,14 +313,23 @@ export function activeFilterChips(f) {
311
313
  export function removeFilter(f, key, value) {
312
314
  let next;
313
315
  if (key === "q") {
314
- next = { ...f, q: undefined };
316
+ // `q` is `string | undefined` under exactOptionalPropertyTypes; the
317
+ // cleanest way to drop it is to omit the key entirely (delete-style).
318
+ const { q: _drop, ...rest } = f;
319
+ next = rest;
315
320
  }
316
321
  else {
317
322
  const current = f[key];
318
323
  if (!current)
319
324
  return f;
320
325
  const filtered = current.filter((v) => v !== value);
321
- next = { ...f, [key]: filtered.length ? filtered : undefined };
326
+ if (filtered.length === 0) {
327
+ const { [key]: _drop, ...rest } = f;
328
+ next = rest;
329
+ }
330
+ else {
331
+ next = { ...f, [key]: filtered };
332
+ }
322
333
  }
323
334
  next.page = 1;
324
335
  return next;
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grove-dev/astro",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "type": "module",
5
5
  "description": "Astro framework adapter for Grove. Components, layouts, design tokens, and a default template.",
6
6
  "license": "MIT",
@@ -42,7 +42,9 @@ const group = Astro.props;
42
42
  <div id={group.popoverId} class="grove-filter-popover absolute left-0 top-full z-40 mt-1 hidden w-72 max-w-[calc(100vw-2rem)] rounded-lg border border-ink-200 bg-white p-1.5 shadow-lg dark:border-ink-800 dark:bg-ink-950" role="listbox" hidden>
43
43
  <FilterOptions filterKey={group.filterKey} options={group.options} initial={group.initial} single={group.single} />
44
44
  <div class="mt-1 flex items-center justify-between border-t border-ink-100 px-2 pt-1.5 dark:border-ink-900">
45
- <button type="button" class="grove-filter-clear text-2xs font-medium text-ink-500 hover:text-ink-900 dark:text-ink-400 dark:hover:text-ink-100" hidden={!group.active}>Clear {group.label.toLowerCase()}</button>
45
+ {group.active && (
46
+ <button type="button" class="grove-filter-clear text-2xs font-medium text-ink-500 hover:text-ink-900 dark:text-ink-400 dark:hover:text-ink-100">Clear {group.label.toLowerCase()}</button>
47
+ )}
46
48
  <button type="button" class="grove-filter-apply ml-auto rounded-md bg-ink-900 px-2.5 py-1 text-2xs font-medium text-white dark:bg-ink-100 dark:text-ink-900">Apply</button>
47
49
  </div>
48
50
  </div>
@@ -8,10 +8,14 @@ interface Props {
8
8
  detailHref: string;
9
9
  /** Whether to show stack/platform chips. Default true. */
10
10
  showChips?: boolean;
11
+ /** Set true on the first 1-2 rows of a list to bypass lazy
12
+ * loading for the above-the-fold avatars. Pair with
13
+ * `fetchpriority="high"`. */
14
+ eager?: boolean;
11
15
  class?: string;
12
16
  }
13
17
 
14
- const { record, detailHref, showChips = true, class: className = "" } = Astro.props;
18
+ const { record, detailHref, showChips = true, eager = false, class: className = "" } = Astro.props;
15
19
  const item = record;
16
20
  const project = item.kind === "project" ? item : null;
17
21
  const name = item.kind === "resource" ? item.title : item.name;
@@ -32,7 +36,16 @@ const curated = Boolean(item.curation?.reviewed || (project && (project.bestFor.
32
36
  <header class="flex items-start gap-3">
33
37
  <a href={detailHref} class="relative z-10 flex shrink-0" aria-label={`Open ${name} details`}>
34
38
  {avatar ? (
35
- <img src={avatar} alt={`${name} avatar`} width="44" height="44" loading="lazy" class="h-11 w-11 rounded-md border border-ink-200 bg-white object-cover dark:border-ink-800 dark:bg-ink-900" />
39
+ <img
40
+ src={avatar}
41
+ alt={`${name} avatar`}
42
+ width="44"
43
+ height="44"
44
+ loading={eager ? "eager" : "lazy"}
45
+ fetchpriority={eager ? "high" : undefined}
46
+ decoding="async"
47
+ class="h-11 w-11 rounded-md border border-ink-200 bg-white object-cover dark:border-ink-800 dark:bg-ink-900"
48
+ />
36
49
  ) : (
37
50
  <span class="flex h-11 w-11 items-center justify-center rounded-md border border-ink-200 bg-ink-50 text-sm font-semibold text-ink-700 dark:border-ink-800 dark:bg-ink-900/60 dark:text-ink-300">{initials}</span>
38
51
  )}
@@ -100,6 +100,11 @@ const favicon =
100
100
  <meta name="theme-color" content="#fafafa" media="(prefers-color-scheme: light)" />
101
101
  <link rel="icon" href={favicon} />
102
102
  <link rel="sitemap" href="/sitemap.xml" />
103
+ {/* Preconnect to GitHub's avatar CDN — most pages render at least
104
+ one avatar (record list cards, detail page logo) and the
105
+ connection is reusable across cards. Cross-origin only, no
106
+ document fetch, so the cost is one TLS handshake per page. */}
107
+ <link rel="preconnect" href="https://avatars.githubusercontent.com" crossorigin="anonymous" />
103
108
  <link
104
109
  rel="alternate"
105
110
  type="text/plain"
@@ -270,6 +275,12 @@ const favicon =
270
275
  {gaId && (
271
276
  <script is:inline define:vars={{ gaId }}>
272
277
  (function () {
278
+ // GA4's `gtag('config', id)` call in the <head> already auto-pings
279
+ // `page_view` on full navigations, so this block only needs to
280
+ // catch history changes (back/forward). No history.pushState /
281
+ // replaceState wrap: the package does not install
282
+ // @astrojs/transitions' ClientRouter, and those wraps
283
+ // double-fired page_view events on every navigation.
273
284
  var last = location.pathname + location.search;
274
285
  function report() {
275
286
  var next = location.pathname + location.search;
@@ -282,16 +293,6 @@ const favicon =
282
293
  });
283
294
  }
284
295
  window.addEventListener("popstate", report);
285
- var origPush = history.pushState;
286
- var origReplace = history.replaceState;
287
- history.pushState = function () {
288
- origPush.apply(this, arguments);
289
- report();
290
- };
291
- history.replaceState = function () {
292
- origReplace.apply(this, arguments);
293
- report();
294
- };
295
296
  })();
296
297
  </script>
297
298
  )}
@@ -85,6 +85,14 @@ const organizationLd = {
85
85
  logo: new URL("/og-image.svg", siteUrl).toString(),
86
86
  ...(siteConfig.repoUrl ? { sameAs: [siteConfig.repoUrl] } : {}),
87
87
  };
88
+
89
+ // Pre-stringify the JSON-LD payloads in the frontmatter so the
90
+ // template body just interpolates the resulting strings. For SSR
91
+ // this saves the JSON.stringify call on every render; for static
92
+ // builds the cost is unchanged but the template reads cleaner.
93
+ const websiteLdJson = JSON.stringify(websiteLd);
94
+ const organizationLdJson = JSON.stringify(organizationLd);
95
+ const perPageLdJson = jsonLd ? JSON.stringify(Array.isArray(jsonLd) ? jsonLd : [jsonLd]) : null;
88
96
  ---
89
97
 
90
98
  <!-- Primary meta -->
@@ -113,14 +121,14 @@ const organizationLd = {
113
121
  <meta name="twitter:image:alt" content={`${siteConfig.name} social preview`} />
114
122
 
115
123
  <!-- JSON-LD: site-wide identity -->
116
- <script is:inline type="application/ld+json" set:html={JSON.stringify(websiteLd)} />
117
- <script is:inline type="application/ld+json" set:html={JSON.stringify(organizationLd)} />
124
+ <script is:inline type="application/ld+json" set:html={websiteLdJson} />
125
+ <script is:inline type="application/ld+json" set:html={organizationLdJson} />
118
126
 
119
127
  <!-- JSON-LD: per-page (SoftwareSourceCode for /items/[slug], etc.) -->
120
- {jsonLd && (
128
+ {perPageLdJson && (
121
129
  <script
122
130
  is:inline
123
131
  type="application/ld+json"
124
- set:html={JSON.stringify(Array.isArray(jsonLd) ? jsonLd : [jsonLd])}
132
+ set:html={perPageLdJson}
125
133
  />
126
134
  )}
@@ -45,8 +45,8 @@ export const STATUS_DISPLAY: Record<string, string> = {
45
45
  };
46
46
 
47
47
  export function statusDisplay(s: string | null | undefined): string {
48
- if (!s) return STATUS_DISPLAY.unknown;
49
- return STATUS_DISPLAY[s] ?? STATUS_DISPLAY.unknown;
48
+ if (!s) return STATUS_DISPLAY.unknown ?? "";
49
+ return STATUS_DISPLAY[s] ?? STATUS_DISPLAY.unknown ?? "";
50
50
  }
51
51
 
52
52
  // ── Lens ids (the curated tabs on /items) ────────────────────────────
@@ -65,7 +65,7 @@ export const LENS_DISPLAY: Record<string, string> = {
65
65
  };
66
66
 
67
67
  export function lensDisplay(id: string | null | undefined): string {
68
- if (!id) return LENS_DISPLAY.all;
68
+ if (!id) return LENS_DISPLAY.all ?? "All";
69
69
  return LENS_DISPLAY[id] ?? id;
70
70
  }
71
71
 
@@ -79,7 +79,7 @@ export const SORT_DISPLAY: Record<string, string> = {
79
79
  };
80
80
 
81
81
  export function sortDisplay(id: string | null | undefined): string {
82
- if (!id) return SORT_DISPLAY["recently-updated"];
82
+ if (!id) return SORT_DISPLAY["recently-updated"] ?? "";
83
83
  return SORT_DISPLAY[id] ?? id;
84
84
  }
85
85
 
package/src/lib/repo.ts CHANGED
@@ -17,10 +17,9 @@ export function getOwnerAndRepoFromRepoUrl(repoUrl: string): {
17
17
  }
18
18
  const m = repoUrl.match(/github\.com\/([^/]+)\/([^/?#]+)/);
19
19
  if (!m) return { owner: null, repo: null };
20
- return {
21
- owner: m[1],
22
- repo: m[2].replace(/\.git$/, ""),
23
- };
20
+ const owner = m[1] ?? null;
21
+ const repo = m[2]?.replace(/\.git$/, "") ?? null;
22
+ return { owner, repo };
24
23
  }
25
24
 
26
25
  /**
package/src/lib/search.ts CHANGED
@@ -18,9 +18,9 @@ export type IndexFilters = {
18
18
  /** A curated lens (e.g. "good-to-learn", "production-like"). Single value. */
19
19
  lens?: string;
20
20
  /** Sort order. Single value, defaults to "recently-updated". */
21
- sort?: IndexSort;
21
+ sort?: IndexSort | undefined;
22
22
  /** 1-based page number. */
23
- page?: number;
23
+ page?: number | undefined;
24
24
  };
25
25
 
26
26
  /** Available sort orders, in UI order. */
@@ -65,17 +65,19 @@ export function filtersFromSearchParams(sp: URLSearchParams): IndexFilters {
65
65
  : undefined;
66
66
  const rawPage = Number(sp.get(KEYS.page));
67
67
  const page = Number.isFinite(rawPage) && rawPage >= 1 ? Math.floor(rawPage) : undefined;
68
+ const q = sp.get(KEYS.q);
69
+ const lens = sp.get(KEYS.lens);
68
70
  return {
69
- q: sp.get(KEYS.q) ?? undefined,
71
+ ...(q !== null ? { q } : {}),
70
72
  stacks: sp.getAll(KEYS.stacks).filter(Boolean),
71
73
  platforms: sp.getAll(KEYS.platforms).filter(Boolean),
72
74
  categories: sp.getAll(KEYS.categories).filter(Boolean),
73
75
  labels: sp.getAll(KEYS.labels).filter(Boolean),
74
76
  licenses: sp.getAll(KEYS.licenses).filter(Boolean),
75
77
  statuses: sp.getAll(KEYS.statuses).flatMap((s) => s.split(",")).filter(Boolean),
76
- lens: sp.get(KEYS.lens) ?? undefined,
77
- sort,
78
- page,
78
+ ...(lens !== null ? { lens } : {}),
79
+ ...(sort !== undefined ? { sort } : {}),
80
+ ...(page !== undefined ? { page } : {}),
79
81
  };
80
82
  }
81
83
 
@@ -352,12 +354,20 @@ export function removeFilter(
352
354
  ): IndexFilters {
353
355
  let next: IndexFilters;
354
356
  if (key === "q") {
355
- next = { ...f, q: undefined };
357
+ // `q` is `string | undefined` under exactOptionalPropertyTypes; the
358
+ // cleanest way to drop it is to omit the key entirely (delete-style).
359
+ const { q: _drop, ...rest } = f;
360
+ next = rest;
356
361
  } else {
357
362
  const current = f[key] as string[] | undefined;
358
363
  if (!current) return f;
359
364
  const filtered = current.filter((v) => v !== value);
360
- next = { ...f, [key]: filtered.length ? filtered : undefined };
365
+ if (filtered.length === 0) {
366
+ const { [key]: _drop, ...rest } = f;
367
+ next = rest;
368
+ } else {
369
+ next = { ...f, [key]: filtered };
370
+ }
361
371
  }
362
372
  next.page = 1;
363
373
  return next;
@@ -31,6 +31,7 @@
31
31
  "@tailwindcss/vite": "^4.3.0",
32
32
  "astro": "^6.4.4",
33
33
  "marked": "^18.0.0",
34
+ "sanitize-html": "^2.17.5",
34
35
  "tailwindcss": "^4.3.0",
35
36
  "yaml": "^2.9.0"
36
37
  }
@@ -1,6 +1,6 @@
1
1
  # example.com — full directory
2
2
 
3
- Generated: 2026-06-15T13:49:39.319Z
3
+ Generated: 2026-06-17T13:40:59.793Z
4
4
  Records: 8
5
5
 
6
6
  ---
@@ -2,61 +2,61 @@
2
2
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
3
  <url>
4
4
  <loc>https://example.com/</loc>
5
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
5
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
6
6
  <changefreq>daily</changefreq>
7
7
  <priority>1.0</priority>
8
8
  </url>
9
9
  <url>
10
10
  <loc>https://example.com/projects</loc>
11
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
11
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
12
12
  <changefreq>daily</changefreq>
13
13
  <priority>0.9</priority>
14
14
  </url>
15
15
  <url>
16
16
  <loc>https://example.com/projects/coolify</loc>
17
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
17
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
18
18
  <changefreq>weekly</changefreq>
19
19
  <priority>0.7</priority>
20
20
  </url>
21
21
  <url>
22
22
  <loc>https://example.com/projects/gitea</loc>
23
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
23
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
24
24
  <changefreq>weekly</changefreq>
25
25
  <priority>0.7</priority>
26
26
  </url>
27
27
  <url>
28
28
  <loc>https://example.com/projects/hoppscotch</loc>
29
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
29
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
30
30
  <changefreq>weekly</changefreq>
31
31
  <priority>0.7</priority>
32
32
  </url>
33
33
  <url>
34
34
  <loc>https://example.com/projects/inventree</loc>
35
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
35
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
36
36
  <changefreq>weekly</changefreq>
37
37
  <priority>0.7</priority>
38
38
  </url>
39
39
  <url>
40
40
  <loc>https://example.com/projects/label-studio</loc>
41
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
41
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
42
42
  <changefreq>weekly</changefreq>
43
43
  <priority>0.7</priority>
44
44
  </url>
45
45
  <url>
46
46
  <loc>https://example.com/projects/logseq</loc>
47
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
47
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
48
48
  <changefreq>weekly</changefreq>
49
49
  <priority>0.7</priority>
50
50
  </url>
51
51
  <url>
52
52
  <loc>https://example.com/projects/private-gpt</loc>
53
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
53
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
54
54
  <changefreq>weekly</changefreq>
55
55
  <priority>0.7</priority>
56
56
  </url>
57
57
  <url>
58
58
  <loc>https://example.com/projects/wakapi</loc>
59
- <lastmod>2026-06-15T13:49:38.754Z</lastmod>
59
+ <lastmod>2026-06-17T13:40:59.064Z</lastmod>
60
60
  <changefreq>weekly</changefreq>
61
61
  <priority>0.7</priority>
62
62
  </url>
@@ -24,14 +24,20 @@
24
24
  * blueprints — `project-directory` (default), `resource-hub`, and
25
25
  * `ecosystem-map` — without per-blueprint forks.
26
26
  *
27
- * When the JSON files are missing (e.g. before `grove generate`
28
- * runs, or in a fresh scaffold with no records) this module falls
29
- * back to empty arrays so the Astro build still succeeds every
30
- * page must render a graceful "no records yet" state.
27
+ * JSON imports are static at the top of this module so Vite
28
+ * resolves them at build time. A fresh scaffold that has not yet
29
+ * run `grove generate` will fail the build with a clear Vite
30
+ * resolution error, which is the correct signal a build that
31
+ * silently renders an empty directory hides real config mistakes.
31
32
  */
33
+ import fullPayload from "../../data/generated/records.full.json";
34
+ import indexPayload from "../../data/generated/records.index.json";
35
+ import siteConfigPayload from "../../data/generated/site-config.json";
32
36
  import { existsSync, readFileSync } from "node:fs";
33
37
  import { fileURLToPath } from "node:url";
34
38
  import { dirname, resolve } from "node:path";
39
+ import { marked } from "marked";
40
+ import sanitizeHtml from "sanitize-html";
35
41
  import type {
36
42
  ProjectRecord,
37
43
  ResourceRecord,
@@ -76,87 +82,26 @@ interface SiteConfigPayload {
76
82
  name?: string;
77
83
  }
78
84
 
79
- function loadGenerated<T>(filename: string, parser: (raw: string) => T): T {
80
- // The Astro build resolves JSON imports from `src/data/*.ts`, but
81
- // we want to be defensive about the order of operations: a fresh
82
- // scaffold runs `astro build` without first running
83
- // `grove generate`, in which case the JSON file does not exist.
84
- // Resolve the path relative to this module's URL, then fall back
85
- // to an empty list.
86
- try {
87
- const here = dirname(fileURLToPath(import.meta.url));
88
- const candidates = [
89
- resolve(here, "..", "..", "data", "generated", filename),
90
- resolve(here, "..", "..", "..", "data", "generated", filename),
91
- resolve(process.cwd(), "data", "generated", filename),
92
- ];
93
- const path = candidates.find((p) => existsSync(p));
94
- if (!path) return parser("");
95
- return parser(readFileSync(path, "utf8"));
96
- } catch {
97
- return parser("");
98
- }
99
- }
85
+ const fullRecordsRaw: Resource[] = (fullPayload as FullPayload).records ?? [];
86
+ const indexRecordsRaw: IndexRecord[] = (indexPayload as IndexPayload).records ?? [];
87
+ const siteConfigRaw: SiteConfigPayload = siteConfigPayload as SiteConfigPayload;
100
88
 
101
- const fullRecordsRaw: Resource[] = loadGenerated(
102
- "records.full.json",
103
- (raw) => {
104
- if (!raw) return [];
105
- try {
106
- const parsed = JSON.parse(raw) as FullPayload;
107
- return (parsed.records ?? []) as Resource[];
108
- } catch {
109
- return [];
110
- }
111
- },
112
- );
113
-
114
- const indexRecordsRaw: IndexRecord[] = loadGenerated(
115
- "records.index.json",
116
- (raw) => {
117
- if (!raw) return [];
118
- try {
119
- const parsed = JSON.parse(raw) as IndexPayload;
120
- return (parsed.records ?? []) as IndexRecord[];
121
- } catch {
122
- return [];
123
- }
124
- },
125
- );
126
-
127
- const siteConfigRaw: SiteConfigPayload = loadGenerated(
128
- "site-config.json",
129
- (raw) => {
130
- if (!raw) return {};
131
- try {
132
- return JSON.parse(raw) as SiteConfigPayload;
133
- } catch {
134
- return {};
135
- }
136
- },
137
- );
138
-
139
- /**
140
- * Full records (all visibility). Use this for the detail page,
141
- * where you need `content`, `bestFor`, `whyListed`, `caveats`,
142
- * the full `github.repository` block, etc.
143
- */
89
+ /** Full records (every record, all visibility). Use this for the
90
+ * detail page (where you need `content`, `bestFor`, `whyListed`,
91
+ * `caveats`, the full `github.repository` block, ...) and for
92
+ * the V0-published alias page at `/apps/[recordSlug]` that
93
+ * enumerates all records for `getStaticPaths`. */
144
94
  export const fullRecords: Resource[] = fullRecordsRaw;
145
95
 
146
- /**
147
- * Index-payload records (visible only). Use this for the list
148
- * page and any home-page sectioning, where you only need the
149
- * slim search-index fields.
150
- */
151
- export const records: IndexRecord[] =
152
- indexRecordsRaw.length > 0 ? indexRecordsRaw : [];
96
+ /** Index-payload records (visible-only slim shape). */
97
+ export const records: IndexRecord[] = indexRecordsRaw;
153
98
 
154
- /** Project-kind records only — slim shape, ready for list pages. */
99
+ /** Resource-kind records — slim shape. */
100
+ /** Project-kind records — slim shape, ready for list pages. */
155
101
  export const projects = records.filter(
156
102
  (r): r is IndexProjectRecord => r.kind === "project",
157
103
  );
158
104
 
159
- /** Resource-kind records — slim shape. */
160
105
  export const resources = records.filter(
161
106
  (r): r is IndexResourceRecord => r.kind === "resource",
162
107
  );
@@ -278,3 +223,96 @@ export const items: IndexRecord[] = (() => {
278
223
  export const fullItems: Resource[] = (() => {
279
224
  return fullRecords.filter((r) => r.kind === blueprintKind);
280
225
  })();
226
+
227
+ // ──────────────────────────────────────────────────────────────────────
228
+ // Markdown content rendering (sanitized)
229
+ // ──────────────────────────────────────────────────────────────────────
230
+ //
231
+ // `record.content` is a path to a markdown file under
232
+ // `content/records/<slug>.md` (see the project schema in
233
+ // @grove-dev/core). The previous page-level implementation
234
+ // imported `node:fs`, called `marked.parse` on the result, and
235
+ // inlined the raw HTML through `set:html` — a live XSS footgun
236
+ // the moment a record body is added. This module owns the read
237
+ // + render + sanitize pipeline at build time:
238
+ //
239
+ // 1. Resolve the path relative to this module's URL (or
240
+ // `process.cwd` for tool-driven runs).
241
+ // 2. Read the file (gracefully absent → `null`).
242
+ // 3. `marked.parse` to HTML.
243
+ // 4. `sanitize-html` with a conservative allowlist that
244
+ // matches the elements the `grove-prose` CSS actually
245
+ // styles (h1-h4, p, ul/ol/li, pre/code, blockquote, a).
246
+ // Links are restricted to safe schemes and external links
247
+ // are hardened to `rel="noopener noreferrer" target="_blank"`.
248
+ // javascript: / data: URIs are blocked; event handlers,
249
+ // iframes, and scripts are stripped.
250
+ //
251
+ // The result is computed once at module load (per record) and
252
+ // memoized in `contentHtmlBySlug`. Pages call
253
+ // `getContentHtml(recordSlug)` to receive the sanitized HTML or
254
+ // `null` if the record has no `content` field / the file is
255
+ // missing. No page module needs to import `node:fs` anymore.
256
+
257
+ const here = dirname(fileURLToPath(import.meta.url));
258
+ function resolveContentPath(contentPath: string): string {
259
+ const candidates = [
260
+ resolve(here, "..", "..", contentPath),
261
+ resolve(here, "..", "..", "..", contentPath),
262
+ resolve(process.cwd(), contentPath),
263
+ ];
264
+ return candidates.find((p) => existsSync(p)) ?? "";
265
+ }
266
+
267
+ const contentHtmlBySlug = new Map<string, string>();
268
+ for (const r of fullRecords) {
269
+ if (r.kind !== "project") continue;
270
+ const projectRecord = r as ProjectRecord;
271
+ if (!projectRecord.content) continue;
272
+ const path = resolveContentPath(projectRecord.content);
273
+ if (!path) continue;
274
+ try {
275
+ const text = readFileSync(path, "utf8");
276
+ // `async: false` keeps the call synchronous so we can populate
277
+ // the map at module-load time. (marked v18 defaults to
278
+ // Promise-returning; v9-17 also support this flag.)
279
+ const rawHtml = marked.parse(text, { async: false }) as string;
280
+ const safeHtml = sanitizeHtml(rawHtml, {
281
+ allowedTags: [
282
+ "h1", "h2", "h3", "h4",
283
+ "p", "br", "hr",
284
+ "ul", "ol", "li",
285
+ "strong", "em", "b", "i", "u", "s", "del",
286
+ "a", "code", "pre", "blockquote",
287
+ ],
288
+ allowedAttributes: {
289
+ a: ["href", "title", "rel", "target"],
290
+ },
291
+ allowedSchemes: ["http", "https", "mailto", "tel"],
292
+ allowedSchemesByTag: { a: ["http", "https", "mailto", "tel"] },
293
+ transformTags: {
294
+ a: sanitizeHtml.simpleTransform("a", {
295
+ rel: "noopener noreferrer",
296
+ target: "_blank",
297
+ }, true),
298
+ },
299
+ disallowedTagsMode: "discard",
300
+ });
301
+ contentHtmlBySlug.set(r.slug, safeHtml);
302
+ } catch {
303
+ // Missing / unreadable / parse-failed content: skip the record
304
+ // rather than render broken HTML. The page treats `null` as
305
+ // "no Notes section".
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Pre-sanitized HTML for a record's `content` markdown body, or
311
+ * `null` if the record has no `content` field / the file is
312
+ * missing / parse failed. Safe to feed straight into
313
+ * `set:html` — the render and sanitize steps already ran at
314
+ * module load.
315
+ */
316
+ export function getContentHtml(slug: string): string | null {
317
+ return contentHtmlBySlug.get(slug) ?? null;
318
+ }
@@ -27,6 +27,7 @@ import {
27
27
  resourceBySlug,
28
28
  entityBySlug,
29
29
  indexSlug,
30
+ getContentHtml,
30
31
  } from "../../data/records";
31
32
  import BaseLayout from "@grove-dev/astro/layouts/BaseLayout.astro";
32
33
  import Icon from "@grove-dev/astro/components/Icon.astro";
@@ -35,24 +36,17 @@ import CurationGrid from "@grove-dev/astro/components/CurationGrid.astro";
35
36
  import { getOwnerAndRepoFromRepoUrl, getOwnerAvatarUrl } from "@grove-dev/astro";
36
37
  import { formatRelative, formatStars } from "@grove-dev/astro";
37
38
  import { statusDisplay, prettySlug, labelDisplay } from "@grove-dev/astro";
38
- import { readFileSync, existsSync } from "node:fs";
39
- import { fileURLToPath } from "node:url";
40
- import { dirname, resolve } from "node:path";
39
+ import type { LabelId } from "@grove-dev/astro";
41
40
  import type { ProjectRecord } from "@grove-dev/core";
42
- import { marked } from "marked";
43
41
 
44
- export async function getStaticPaths() {
42
+ export function getStaticPaths() {
45
43
  // Walk every record and emit a path for it. The directory slug
46
- // (`projects` / `resources` / `entities`) is taken from the
47
- // blueprint config so a `resource-hub` blueprint produces
48
- // `/resources/<slug>` URLs without any per-blueprint fork.
49
- let dirSlug = "projects";
50
- try {
51
- const raw = await import("../../../data/generated/site-config.json");
52
- dirSlug = raw.default?.blueprintConfig?.routeSlug ?? "projects";
53
- } catch {
54
- /* not present */
55
- }
44
+ // is read from the static site-config import at the top of this
45
+ // file (Vite resolves the JSON at build time). This template
46
+ // ships with the `project-directory` blueprint, so the slug is
47
+ // always `projects`; swapping in a different blueprint means
48
+ // changing the blueprint config that drives this value.
49
+ const dirSlug = siteConfig.blueprintConfig?.routeSlug ?? "projects";
56
50
  return fullRecords.map((record) => ({
57
51
  params: { slug: dirSlug, recordSlug: record.slug },
58
52
  }));
@@ -107,25 +101,27 @@ const tags = record.tags ?? [];
107
101
  const healthStatus = proj?.health?.status;
108
102
  const healthLabel = healthStatus ? statusDisplay(healthStatus) : null;
109
103
 
104
+ // ── Badge class lookup ────────────────────────────────────────────
105
+ // The previous code interpolated `LabelId` straight into the class
106
+ // string (`grove-badge-{l}`), which Astro renders as a literal class
107
+ // name — every badge became `grove-badge-{l}` regardless of value.
108
+ // Map each known id to its stable CSS class in the package
109
+ // stylesheet. Unknown ids (e.g. legacy "featured") fall back to the
110
+ // neutral `.grove-badge` look instead of producing broken classes.
111
+ const labelClassMap: Record<LabelId, string> = {
112
+ new: "grove-badge-new",
113
+ hot: "grove-badge-hot",
114
+ mature: "grove-badge-mature",
115
+ featured: "grove-badge",
116
+ };
117
+
110
118
  // ── Optional content markdown (record.content is a path under
111
119
  // content/records/<slug>.md) ────────────────────────────────────
112
- let contentHtml: string | null = null;
113
- if (isProject && proj?.content) {
114
- const here = dirname(fileURLToPath(import.meta.url));
115
- const candidates = [
116
- resolve(here, "..", "..", "..", proj.content),
117
- resolve(process.cwd(), proj.content),
118
- ];
119
- const contentPath = candidates.find((p) => existsSync(p));
120
- if (contentPath) {
121
- try {
122
- const text = readFileSync(contentPath, "utf8");
123
- contentHtml = await marked.parse(text);
124
- } catch {
125
- contentHtml = null;
126
- }
127
- }
128
- }
120
+ // The read + marked.parse + sanitize-html pipeline lives in
121
+ // `data/records.ts` and runs once at module load. The page just
122
+ // looks up the pre-sanitized HTML by record slug; no node:fs
123
+ // import needed here.
124
+ const contentHtml: string | null = isProject ? getContentHtml(recordSlug) : null;
129
125
 
130
126
  // ── Detail-page decision-signal data (5 sections) ────────────
131
127
  // Hoist out of the template body so the JSX stays free of
@@ -296,7 +292,7 @@ if (isProject && proj) {
296
292
  </span>
297
293
  )}
298
294
  {curationLabels.map((l) => (
299
- <span class="grove-badge grove-badge-{l}" title={`Curated: ${labelDisplay(l) ?? l}`}>
295
+ <span class={`grove-badge ${labelClassMap[l as LabelId] ?? ""}`} title={`Curated: ${labelDisplay(l) ?? l}`}>
300
296
  {labelDisplay(l) ?? prettySlug(l)}
301
297
  </span>
302
298
  ))}
@@ -13,6 +13,12 @@
13
13
  * `/entities/`) is derived from the blueprint via `getStaticPaths`,
14
14
  * so the same page works for every blueprint without per-blueprint
15
15
  * forks.
16
+ *
17
+ * Navigation model: full-page render. The form posts via `method="get"`
18
+ * so the browser navigates to `?q=...&sort=...&stack=...`, and the
19
+ * server re-runs `filterRecords` / `applySort` / `paginate` from
20
+ * those query params. No client-side filter shim, no duplicated
21
+ * logic. The URL stays the single source of truth for filter state.
16
22
  */
17
23
  import siteConfig from "../../../data/generated/site-config.json";
18
24
  import { items, itemLabel, itemLabelPlural } from "../../data/records";
@@ -34,24 +40,19 @@ import {
34
40
  effectiveSort,
35
41
  filterRecords,
36
42
  filtersFromSearchParams,
37
- paginate,
38
43
  searchParamsFromFilters,
39
44
  sortDisplay,
40
45
  SORT_OPTIONS,
41
46
  totalPages,
42
47
  } from "@grove-dev/astro";
43
48
 
44
- export async function getStaticPaths() {
45
- let activeSlug = "projects";
46
- try {
47
- const raw = await import("../../../data/generated/site-config.json");
48
- activeSlug = raw.default?.blueprintConfig?.routeSlug ?? "projects";
49
- } catch {
50
- /* not present */
51
- }
52
- const all = ["projects", "resources", "entities"];
53
- if (!all.includes(activeSlug)) all.push(activeSlug);
54
- return all.map((slug) => ({ params: { slug } }));
49
+ // This template ships with the `project-directory` blueprint, so the
50
+ // only directory slug it ever needs is `projects`. While it ships
51
+ // as the project directory, pre-generate the single path the build
52
+ // actually needs. Swapping in a different blueprint is a one-config
53
+ // change that flows through the static import at the top.
54
+ export function getStaticPaths() {
55
+ return [{ params: { slug: "projects" } }];
55
56
  }
56
57
 
57
58
  const slug = Astro.params.slug as string;
@@ -64,36 +65,7 @@ const filtered = filterRecords(items, filters);
64
65
  const sorted = applySort(filtered, sort);
65
66
  const pages = totalPages(sorted.length);
66
67
  const page = Math.min(requestedPage, pages);
67
- const visibleItems = paginate(sorted, page);
68
68
  const chips = activeFilterChips(filters);
69
- const clientItems = items.map((item) => ({
70
- slug: item.slug,
71
- name: item.kind === "resource" ? item.title : item.name,
72
- description: item.description,
73
- category: item.category,
74
- tags: item.tags,
75
- labels: item.curation?.labels ?? [],
76
- lenses: item.curation?.lenses ?? [],
77
- reviewed: Boolean(item.curation?.reviewed),
78
- addedAt: item.curation?.reviewedAt ?? "",
79
- stacks: item.kind === "project" ? [item.stack, ...item.stacks].filter(Boolean) : [],
80
- platforms: item.kind === "project" ? item.platforms : [],
81
- license: item.kind === "project" ? item.github?.license ?? "" : "",
82
- status: item.kind === "project" ? item.health?.status ?? "" : "",
83
- stars: item.kind === "project" ? item.github?.stars ?? 0 : 0,
84
- updatedAt:
85
- item.kind === "project"
86
- ? item.github?.pushedAt ?? ""
87
- : item.kind === "resource"
88
- ? item.publishedAt ?? ""
89
- : "",
90
- extra:
91
- item.kind === "project"
92
- ? [item.repoUrl, item.projectType, item.difficulty, item.codebaseSize, ...item.bestFor, ...item.whyListed]
93
- : item.kind === "resource"
94
- ? [item.type, item.topic, item.author ?? ""]
95
- : [item.type, item.location ?? "", item.parent ?? ""],
96
- }));
97
69
 
98
70
  const title = `Browse ${slug} — ${siteConfig.name}`;
99
71
  const description = `A searchable directory of ${itemLabelPlural()} for ${siteConfig.name}.`;
@@ -291,9 +263,13 @@ function hrefForRemove(key: keyof IndexFilters, value: string): string {
291
263
  </div>
292
264
 
293
265
  <ul id="results-list" class="m-0 flex list-none flex-col gap-3 p-0">
294
- {sorted.map((item) => (
266
+ {sorted.map((item, i) => (
295
267
  <li class="m-0 p-0" data-record-slug={item.slug}>
296
- <IndexRow record={item as Parameters<typeof IndexRow>[0]["record"]} detailHref={`/${slug}/${item.slug}`} />
268
+ <IndexRow
269
+ record={item as Parameters<typeof IndexRow>[0]["record"]}
270
+ detailHref={`/${slug}/${item.slug}`}
271
+ eager={i < 2}
272
+ />
297
273
  </li>
298
274
  ))}
299
275
  </ul>
@@ -324,231 +300,8 @@ function hrefForRemove(key: keyof IndexFilters, value: string): string {
324
300
  >
325
301
  {`Submit ${itemLabel()}`}
326
302
  </a>
303
+
327
304
  </div>
328
305
  </div>
329
306
  </section>
330
-
331
- <script is:inline define:vars={{ clientItems, slug, itemSingular: itemLabel(), itemPlural: itemLabelPlural() }}>
332
- (function () {
333
- var PAGE_SIZE = 20;
334
- var list = document.getElementById("results-list");
335
- if (!list) return;
336
-
337
- // Sort dropdown: navigate on change so the server re-renders
338
- // the sorted list (URL is the source of truth for filters/sort).
339
- var sortSelect = document.getElementById("sort-select");
340
- if (sortSelect) {
341
- sortSelect.addEventListener("change", function () {
342
- var params = new URLSearchParams(location.search);
343
- if (sortSelect.value && sortSelect.value !== "recently-updated") {
344
- params.set("sort", sortSelect.value);
345
- } else {
346
- params.delete("sort");
347
- }
348
- params.delete("page");
349
- var qs = params.toString();
350
- location.assign(qs ? "?" + qs : location.pathname);
351
- });
352
- }
353
-
354
- // Search: 250ms debounce; pressing Enter still submits
355
- // immediately via the form's normal submit handler.
356
- var searchInput = document.getElementById("search-input");
357
- var searchForm = document.getElementById("search-form");
358
- if (searchInput && searchForm) {
359
- var debounceTimer = null;
360
- var submit = function () {
361
- var params = new URLSearchParams(location.search);
362
- var term = searchInput.value.trim();
363
- if (term) params.set("q", term);
364
- else params.delete("q");
365
- params.delete("page");
366
- var qs = params.toString();
367
- location.assign(qs ? "?" + qs : location.pathname);
368
- };
369
- searchInput.addEventListener("input", function () {
370
- if (debounceTimer) window.clearTimeout(debounceTimer);
371
- debounceTimer = window.setTimeout(submit, 250);
372
- });
373
- searchForm.addEventListener("submit", function (event) {
374
- event.preventDefault();
375
- if (debounceTimer) window.clearTimeout(debounceTimer);
376
- submit();
377
- });
378
- }
379
-
380
- function values(params, key) {
381
- return params.getAll(key).filter(Boolean);
382
- }
383
-
384
- function display(value) {
385
- return String(value || "")
386
- .split(/[-_]+/)
387
- .filter(Boolean)
388
- .map(function (part) { return part.charAt(0).toUpperCase() + part.slice(1); })
389
- .join(" ");
390
- }
391
-
392
- function sortLabel(value) {
393
- return {
394
- "recently-updated": "Recently updated",
395
- "most-starred": "Most starred",
396
- "recently-added": "Recently added",
397
- "best-overall": "Best overall",
398
- alphabetical: "Alphabetical",
399
- }[value] || "Recently updated";
400
- }
401
-
402
- function pageHref(params, page) {
403
- var next = new URLSearchParams(params);
404
- if (page <= 1) next.delete("page");
405
- else next.set("page", String(page));
406
- var query = next.toString();
407
- return query ? "/" + slug + "?" + query : "/" + slug;
408
- }
409
-
410
- function apply() {
411
- var params = new URLSearchParams(location.search);
412
- var query = (params.get("q") || "").trim().toLowerCase();
413
- var stacks = values(params, "stack");
414
- var platforms = values(params, "platform");
415
- var categories = values(params, "category");
416
- var labels = values(params, "label");
417
- var licenses = values(params, "license");
418
- var statuses = (params.get("status") || "").split(",").filter(Boolean);
419
- var lens = params.get("lens") || "";
420
- var sort = params.get("sort") || "recently-updated";
421
- var page = Math.max(1, Number(params.get("page")) || 1);
422
-
423
- var filtered = clientItems.filter(function (item) {
424
- var haystack = [
425
- item.name,
426
- item.description,
427
- item.category,
428
- item.tags,
429
- item.stacks,
430
- item.platforms,
431
- item.license,
432
- item.status,
433
- item.extra,
434
- ].flat(3).join(" ").toLowerCase();
435
- if (query && !haystack.includes(query)) return false;
436
- if (stacks.length && !item.stacks.some(function (value) { return stacks.includes(value); })) return false;
437
- if (platforms.length && !item.platforms.some(function (value) { return platforms.includes(value); })) return false;
438
- if (categories.length && !categories.includes(item.category)) return false;
439
- if (labels.length && !item.labels.some(function (value) { return labels.includes(value); })) return false;
440
- if (licenses.length && !licenses.includes(item.license)) return false;
441
- if (statuses.length && !statuses.includes(item.status)) return false;
442
- if (lens && !item.lenses.includes(lens)) return false;
443
- return true;
444
- });
445
-
446
- filtered.sort(function (a, b) {
447
- if (sort === "most-starred") return b.stars - a.stars;
448
- if (sort === "recently-added") return Date.parse(b.addedAt || 0) - Date.parse(a.addedAt || 0);
449
- if (sort === "best-overall") return Number(b.reviewed) - Number(a.reviewed) || b.stars - a.stars;
450
- if (sort === "alphabetical") return a.name.localeCompare(b.name);
451
- return Date.parse(b.updatedAt || 0) - Date.parse(a.updatedAt || 0);
452
- });
453
-
454
- var totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
455
- page = Math.min(page, totalPages);
456
- var visible = new Set(
457
- filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE).map(function (item) { return item.slug; }),
458
- );
459
- var order = new Map(filtered.map(function (item, index) { return [item.slug, index]; }));
460
- Array.from(list.children)
461
- .sort(function (a, b) {
462
- return (order.get(a.dataset.recordSlug) ?? Number.MAX_SAFE_INTEGER) -
463
- (order.get(b.dataset.recordSlug) ?? Number.MAX_SAFE_INTEGER);
464
- })
465
- .forEach(function (node) {
466
- node.hidden = !visible.has(node.dataset.recordSlug);
467
- list.appendChild(node);
468
- });
469
-
470
- var count = document.getElementById("results-count");
471
- if (count) count.textContent = filtered.length + " " + (filtered.length === 1 ? itemSingular : itemPlural);
472
- var sortText = document.getElementById("results-sort");
473
- if (sortText) sortText.textContent = " · sorted by " + sortLabel(sort);
474
- var pageText = document.getElementById("results-page");
475
- if (pageText) pageText.textContent = totalPages > 1 ? " · page " + page + " of " + totalPages : "";
476
- document.getElementById("empty-state")?.classList.toggle("hidden", filtered.length > 0);
477
-
478
- var search = document.querySelector('input[name="q"]');
479
- if (search) search.value = params.get("q") || "";
480
- document.querySelectorAll("select").forEach(function (select) {
481
- var selected = values(params, select.name);
482
- if (select.name === "sort") selected = [sort];
483
- Array.from(select.options).forEach(function (option) {
484
- option.selected = selected.includes(option.value);
485
- });
486
- });
487
-
488
- // Pagination is server-rendered (see <Pagination /> in the
489
- // template) so the static HTML contains the page-number
490
- // links for SEO. No client-side rendering loop here.
491
-
492
- var chipHost = document.getElementById("active-filters");
493
- if (chipHost) {
494
- chipHost.innerHTML = "";
495
- var specs = [
496
- ["q", params.get("q") ? "“" + params.get("q") + "”" : ""],
497
- ...stacks.map(function (v) { return ["stack", "Stack: " + v]; }),
498
- ...platforms.map(function (v) { return ["platform", "Platform: " + v]; }),
499
- ...categories.map(function (v) { return ["category", "Category: " + v]; }),
500
- ...labels.map(function (v) { return ["label", display(v)]; }),
501
- ...licenses.map(function (v) { return ["license", "License: " + v]; }),
502
- ...(lens ? [["lens", display(lens)]] : []),
503
- ...statuses.map(function (v) { return ["status", display(v)]; }),
504
- ].filter(function (entry) { return entry[1]; });
505
- specs.forEach(function (entry) {
506
- var key = entry[0];
507
- var chip = document.createElement("a");
508
- var next = new URLSearchParams(params);
509
- if (key === "status") {
510
- var remaining = statuses.filter(function (value) { return display(value) !== entry[1]; });
511
- next.delete("status");
512
- if (remaining.length) next.set("status", remaining.join(","));
513
- } else {
514
- next.delete(key);
515
- }
516
- next.delete("page");
517
- chip.href = next.toString() ? "/" + slug + "?" + next : "/" + slug;
518
- chip.className = "grove-badge transition-colors hover:border-ink-400";
519
- chip.textContent = entry[1] + " x";
520
- chipHost.appendChild(chip);
521
- });
522
- if (specs.length) {
523
- var clear = document.createElement("a");
524
- clear.href = "/" + slug;
525
- clear.className = "text-2xs font-medium text-ink-500 hover:text-ink-900";
526
- clear.textContent = "Clear all";
527
- chipHost.appendChild(clear);
528
- }
529
- chipHost.classList.toggle("hidden", specs.length === 0);
530
- }
531
- }
532
-
533
- document.querySelectorAll("form").forEach(function (form) {
534
- form.addEventListener("submit", function (event) {
535
- if (!form.closest("main")) return;
536
- event.preventDefault();
537
- var params = new URLSearchParams(location.search);
538
- form.querySelectorAll("input, select").forEach(function (field) {
539
- if (!field.name) return;
540
- params.delete(field.name);
541
- if (field instanceof HTMLSelectElement && field.multiple) {
542
- Array.from(field.selectedOptions).forEach(function (option) { params.append(field.name, option.value); });
543
- } else if (field.value) {
544
- params.set(field.name, field.value);
545
- }
546
- });
547
- params.delete("page");
548
- location.assign(params.toString() ? "?" + params : location.pathname);
549
- });
550
- });
551
- apply();
552
- })();
553
- </script>
554
307
  </BaseLayout>