@grove-dev/astro 0.2.13 → 0.2.14

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.
package/README.md CHANGED
@@ -12,33 +12,40 @@ pnpm add @grove-dev/astro
12
12
 
13
13
  ```txt
14
14
  src/
15
- ├── components/ # ItemCard, CategoryGrid, HealthBadge, ScoreBars,
16
- │ # DirectoryFilters, DirectoryHero, LensTabs,
17
- │ # ActiveFilterChips, MethodologyPanel, Pagination,
18
- │ # ProjectDetail, SubmitDraft
15
+ ├── components/ # ItemCard, CategoryGrid, ScoreBars, IndexRow,
16
+ │ # Pagination, RecordSection, RefinePanel, Hero,
17
+ │ # Icon, SmartLensTabs, ExploreByCategory,
18
+ │ # ExploreByStack, WhyThisExists, CurationGrid,
19
+ │ # ContributorsGrid, StackGrid, MinimalAbout,
20
+ │ # OriginalCollection, DecisionRow, FilterGroupMenu,
21
+ │ # FilterOptions
19
22
  ├── layouts/ # BaseLayout
20
23
  ├── styles.css # design tokens + utility classes
21
- └── index.ts # re-exports @grove-dev/ui
24
+ └── index.ts # re-exports @grove-dev/core + @grove-dev/ui
22
25
 
23
26
  templates/
24
27
  └── default/ # full Astro starter: pages/, layouts/, public/, data/,
25
- # .github/, astro.config.mjs, tailwind.config.mjs
28
+ # .github/, astro.config.mjs
26
29
  ```
27
30
 
28
31
  The package publishes `dist/`, `src/`, and `templates/`. The `templates/` directory is **not** imported by consumers; it is copied by `@grove-dev/cli` at scaffold time.
29
32
 
33
+ > **Component naming:** `ItemCard` is the V1 published API name (kept for stability — it appears in user docs and downstream sites). The internal `IndexRow` / `Pagination` / `RecordSection` aliases are V1 canonical names; the old `AppsIndexRow` / `AppsPagination` / `ItemSection` V0 names have been removed.
34
+
30
35
  ## Usage in a space
31
36
 
32
37
  ```astro
33
38
  ---
34
- import { ItemCard, ScoreBars, HealthBadge, DirectoryFilters } from "@grove-dev/astro";
39
+ import ItemCard from "@grove-dev/astro/components/ItemCard.astro";
40
+ import IndexRow from "@grove-dev/astro/components/IndexRow.astro";
41
+ import { ScoreBars, filterRecords, sortDisplay } from "@grove-dev/astro";
35
42
  import "@grove-dev/astro/styles.css";
36
43
  import BaseLayout from "@grove-dev/astro/layouts/BaseLayout.astro";
37
- import apps from "../data/generated/apps.json";
44
+ import records from "../data/generated/records.json";
38
45
  ---
39
46
  <BaseLayout title="My Grove space">
40
- <DirectoryFilters facets={...} />
41
- {apps.map((app) => <ItemCard item={app} />)}
47
+ <RefinePanel initial={filters} facets={facets} />
48
+ {records.map((r) => <ItemCard record={r} href={`/projects/${r.slug}`} />)}
42
49
  </BaseLayout>
43
50
  ```
44
51
 
@@ -48,16 +55,17 @@ Components are imported by path, not through the barrel — that lets `astro che
48
55
 
49
56
  `templates/default/` is a complete Astro starter. It contains:
50
57
 
51
- - `src/pages/` — index, item detail, search, about, methodology, submit, sitemap
52
- - `src/components/` — layout primitives, page sections
53
- - `src/data/`placeholder dataset; replaced by `grove build-data`
58
+ - `src/pages/` — index, contributors, about, submit, 404, sitemap.xml, plus blueprint-aware dynamic routes at `[slug]/index.astro` (list) and `[slug]/[recordSlug].astro` (detail), plus `apps/[recordSlug].astro` (V0→V1 301 redirect)
59
+ - `src/components/` — site-specific page sections (none by default; the V1 surface is in `packages/astro/src/components/`)
60
+ - `src/data/records.ts`typed loader for `data/generated/records.full.json` (V0 `src/data/config.ts` is replaced)
54
61
  - `src/lib/` — site-specific helpers (no business logic)
55
- - `public/` — icons, OG image, robots
56
- - `data/` — empty tree for the gardener to populate
57
- - `astro.config.mjs`, `tailwind.config.mjs`
58
- - `.github/` issue templates
62
+ - `scripts/` — `build-llms.mjs` (regenerates `llms-full.txt` only, preserves committed `llms.txt`), `fetch-icons.mjs`, `migrate-legacy-to-schema-v1.mjs`
63
+ - `public/` — icons, OG image, robots, `llms.txt`, `llms-full.txt`
64
+ - `data/` — empty tree for the gardener to populate; `data/records/<slug>.yml` is the V1 layout (V0 was `data/apps/*.yml`)
65
+ - `astro.config.mjs` (no `tailwind.config.mjs` by default; plain CSS + design tokens)
66
+ - `.github/` — issue templates + 11 GitHub Actions workflows (validate, build, deploy, sync, cleanup, …)
59
67
 
60
- Business logic (filtering, sorting, scoring, faceting) is **imported from `@grove-dev/ui`**, never re-implemented in the template.
68
+ Business logic (filtering, sorting, scoring, faceting) is **imported from `@grove-dev/ui`**, never re-implemented in the template. The V0 commands (`grove build-data`, `grove build-llms-full`, `grove analyze`, `grove enrich`) have been replaced with V1 names (`grove generate`, `grove llms`, `grove sync github`).
61
69
 
62
70
  ## Layering
63
71
 
@@ -3,7 +3,8 @@
3
3
  * Returns nulls if the URL doesn't match github.com/{owner}/{repo}.
4
4
  *
5
5
  * Used in:
6
- * - ItemCard avatar fallback (owner avatar via GitHub avatars API)
6
+ * - ItemCard avatar fallback (owner avatar via GitHub avatars
7
+ * API; component name retained for V1 published API stability)
7
8
  * - App detail page (showing owner + repo name in breadcrumb / header)
8
9
  * - Anywhere we need to display "@owner / repo" or link to the owner
9
10
  */
@@ -1 +1 @@
1
- {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/lib/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;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,CAUA;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
@@ -3,7 +3,8 @@
3
3
  * Returns nulls if the URL doesn't match github.com/{owner}/{repo}.
4
4
  *
5
5
  * Used in:
6
- * - ItemCard avatar fallback (owner avatar via GitHub avatars API)
6
+ * - ItemCard avatar fallback (owner avatar via GitHub avatars
7
+ * API; component name retained for V1 published API stability)
7
8
  * - App detail page (showing owner + repo name in breadcrumb / header)
8
9
  * - Anywhere we need to display "@owner / repo" or link to the owner
9
10
  */
@@ -1 +1 @@
1
- {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/lib/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;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,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"}
@@ -5,7 +5,7 @@ import type { IndexRecord } from "@grove-dev/core";
5
5
  * Multi-value fields use repeated keys in the URL: `?stack=Flutter&stack=React+Native`.
6
6
  * Empty / undefined fields mean "no filter on this dimension".
7
7
  */
8
- export type ItemsFilters = {
8
+ export type IndexFilters = {
9
9
  q?: string;
10
10
  stacks?: string[];
11
11
  platforms?: string[];
@@ -16,7 +16,7 @@ export type ItemsFilters = {
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?: ItemsSort;
19
+ sort?: IndexSort;
20
20
  /** 1-based page number. */
21
21
  page?: number;
22
22
  };
@@ -37,31 +37,31 @@ export declare const SORT_OPTIONS: readonly [{
37
37
  readonly value: "alphabetical";
38
38
  readonly label: "Alphabetical";
39
39
  }];
40
- export type ItemsSort = (typeof SORT_OPTIONS)[number]["value"];
40
+ export type IndexSort = (typeof SORT_OPTIONS)[number]["value"];
41
41
  /**
42
42
  * Read filters from a URLSearchParams (or anything URLSearchParams-shaped,
43
43
  * e.g. the result of `new URL(req.url).searchParams`).
44
44
  */
45
- export declare function filtersFromSearchParams(sp: URLSearchParams): ItemsFilters;
45
+ export declare function filtersFromSearchParams(sp: URLSearchParams): IndexFilters;
46
46
  /**
47
47
  * Serialize a filters object back to URLSearchParams.
48
48
  * Undefined / empty values are dropped. Defaults (sort, page 1, comfortable
49
49
  * density) are also dropped to keep URLs short and canonical.
50
50
  */
51
- export declare function searchParamsFromFilters(f: ItemsFilters): URLSearchParams;
51
+ export declare function searchParamsFromFilters(f: IndexFilters): URLSearchParams;
52
52
  /** True if any filter is active (i.e. the result list isn't "all items"). */
53
- export declare function hasAnyFilter(f: ItemsFilters): boolean;
53
+ export declare function hasAnyFilter(f: IndexFilters): boolean;
54
54
  /** How many items per page. Constant for now; future versions may vary. */
55
55
  export declare const PAGE_SIZE = 20;
56
- export declare function applySort(items: IndexRecord[], sort: ItemsSort): IndexRecord[];
56
+ export declare function applySort(items: IndexRecord[], sort: IndexSort): IndexRecord[];
57
57
  /** Slice an array for a given page (1-based). */
58
58
  export declare function paginate<T>(items: T[], page: number, pageSize?: number): T[];
59
59
  /** Total number of pages given an item count. Always >= 1. */
60
60
  export declare function totalPages(itemCount: number, pageSize?: number): number;
61
61
  /** Resolve the effective sort from a filters object, applying default. */
62
- export declare function effectiveSort(f: ItemsFilters): ItemsSort;
62
+ export declare function effectiveSort(f: IndexFilters): IndexSort;
63
63
  /** Resolve the effective page from a filters object, applying default. */
64
- export declare function effectivePage(f: ItemsFilters): number;
64
+ export declare function effectivePage(f: IndexFilters): number;
65
65
  /**
66
66
  * Return the subset of items that match all active filters (AND across
67
67
  * dimensions, OR within a dimension).
@@ -69,10 +69,10 @@ export declare function effectivePage(f: ItemsFilters): number;
69
69
  * `q` is a case-insensitive substring search across name, owner,
70
70
  * description, and category. Other dimensions are exact match.
71
71
  */
72
- export declare function filterItems(items: IndexRecord[], f: ItemsFilters): IndexRecord[];
72
+ export declare function filterRecords(items: IndexRecord[], f: IndexFilters): IndexRecord[];
73
73
  /** Build a flat list of "active filter" chips for display + removal. */
74
- export declare function activeFilterChips(f: ItemsFilters): {
75
- key: keyof ItemsFilters;
74
+ export declare function activeFilterChips(f: IndexFilters): {
75
+ key: keyof IndexFilters;
76
76
  value: string;
77
77
  label: string;
78
78
  }[];
@@ -84,7 +84,7 @@ export declare function activeFilterChips(f: ItemsFilters): {
84
84
  * Also resets page to 1 so the user doesn't get stranded on a high page
85
85
  * that no longer has results.
86
86
  */
87
- export declare function removeFilter(f: ItemsFilters, key: keyof ItemsFilters, value: string): ItemsFilters;
87
+ export declare function removeFilter(f: IndexFilters, key: keyof IndexFilters, value: string): IndexFilters;
88
88
  /**
89
89
  * Build the full list of facet values from the items array, preserving
90
90
  * a sensible order (frequency desc, then alphabetical for ties).
@@ -111,7 +111,4 @@ export declare function buildFacets(items: IndexRecord[]): {
111
111
  count: number;
112
112
  }[];
113
113
  };
114
- export declare const filterApps: typeof filterItems;
115
- export type AppsFilters = ItemsFilters;
116
- export type AppsSort = ItemsSort;
117
114
  //# sourceMappingURL=search.d.ts.map
@@ -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,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,YAAY,GAAG,WAAW,EAAE,CA8FhF;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;AASD,eAAO,MAAM,UAAU,oBAAc,CAAC;AACtC,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC;AACvC,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC"}
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"}
@@ -170,7 +170,7 @@ export function effectivePage(f) {
170
170
  * `q` is a case-insensitive substring search across name, owner,
171
171
  * description, and category. Other dimensions are exact match.
172
172
  */
173
- export function filterItems(items, f) {
173
+ export function filterRecords(items, f) {
174
174
  const q = f.q?.trim().toLowerCase();
175
175
  const stacks = f.stacks?.length ? new Set(f.stacks) : null;
176
176
  const platforms = f.platforms?.length ? new Set(f.platforms) : null;
@@ -361,12 +361,9 @@ export function buildFacets(items) {
361
361
  licenses: sortByCountThenName(counts.license),
362
362
  };
363
363
  }
364
- // ── V1-published API aliases ─────────────────────────────────────────
365
- // The published `@grove-dev/astro@0.2.10` package exports these
366
- // under different names (`filterApps` for the filter function and
367
- // `AppsFilters` for the filter-state type). Re-export them under
368
- // the V1 names so templates can use either spelling, and so the
369
- // template's `apps/index.astro` (built against the published API)
370
- // also works against the local workspace source.
371
- export const filterApps = filterItems;
364
+ // ── V1-published API ─────────────────────────────────────────────────
365
+ // `IndexFilters` / `IndexSort` are the canonical V1 names for the
366
+ // filter-state type. The internal functions (filterRecords, applySort,
367
+ // paginate, buildFacets, etc.) operate on the generic `IndexRecord`
368
+ // shape and are intentionally framework-agnostic.
372
369
  //# sourceMappingURL=search.js.map
@@ -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.13",
3
+ "version": "0.2.14",
4
4
  "type": "module",
5
5
  "description": "Astro framework adapter for Grove. Components, layouts, design tokens, and a default template.",
6
6
  "license": "MIT",
@@ -43,8 +43,8 @@
43
43
  "./layouts/*": "./src/layouts/*.astro"
44
44
  },
45
45
  "dependencies": {
46
- "@grove-dev/core": "0.2.13",
47
- "@grove-dev/ui": "1.0.3",
46
+ "@grove-dev/core": "0.2.14",
47
+ "@grove-dev/ui": "1.0.4",
48
48
  "astro": "^6.4.6"
49
49
  },
50
50
  "peerDependencies": {
@@ -3,7 +3,8 @@
3
3
  * RecordSection — generic lens-style section wrapper for the
4
4
  * home page.
5
5
  *
6
- * Renders a SectionHeader + a 3-column grid of `ItemCard`s, with an
6
+ * Renders a SectionHeader + a 3-column grid of `ItemCard`s (a
7
+ * record card; kept as `ItemCard` for V1 published API stability),
7
8
  * optional "View all" link in the header. Generic: takes any
8
9
  * `IndexRecord[]` (the slim list-page shape, discriminated union
9
10
  * over `kind`).
@@ -11,11 +11,11 @@
11
11
  * repeated key. Empty values are dropped, so the URL stays clean.
12
12
  *
13
13
  * Generic: takes a `facets` map of `{ value, label, count }[]` per
14
- * dimension and an `initial` `ItemsFilters` for preselecting the
14
+ * dimension and an `initial` `IndexFilters` for preselecting the
15
15
  * current URL state.
16
16
  */
17
17
 
18
- import type { ItemsFilters } from "../lib/search";
18
+ import type { IndexFilters } from "../lib/search";
19
19
  import { SORT_OPTIONS } from "../lib/search";
20
20
  import FilterGroupMenu from "./FilterGroupMenu.astro";
21
21
 
@@ -35,7 +35,7 @@ interface Facets {
35
35
 
36
36
  interface Props {
37
37
  facets: Facets;
38
- initial: ItemsFilters;
38
+ initial: IndexFilters;
39
39
  pathPrefix?: string;
40
40
  class?: string;
41
41
  /** Hide specific facets. Default: all shown. */
package/src/lib/repo.ts CHANGED
@@ -3,7 +3,8 @@
3
3
  * Returns nulls if the URL doesn't match github.com/{owner}/{repo}.
4
4
  *
5
5
  * Used in:
6
- * - ItemCard avatar fallback (owner avatar via GitHub avatars API)
6
+ * - ItemCard avatar fallback (owner avatar via GitHub avatars
7
+ * API; component name retained for V1 published API stability)
7
8
  * - App detail page (showing owner + repo name in breadcrumb / header)
8
9
  * - Anywhere we need to display "@owner / repo" or link to the owner
9
10
  */
package/src/lib/search.ts CHANGED
@@ -7,7 +7,7 @@ import { labelDisplay, lensDisplay, statusDisplay } from "./display.js";
7
7
  * Multi-value fields use repeated keys in the URL: `?stack=Flutter&stack=React+Native`.
8
8
  * Empty / undefined fields mean "no filter on this dimension".
9
9
  */
10
- export type ItemsFilters = {
10
+ export type IndexFilters = {
11
11
  q?: string;
12
12
  stacks?: string[];
13
13
  platforms?: string[];
@@ -18,7 +18,7 @@ export type ItemsFilters = {
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?: ItemsSort;
21
+ sort?: IndexSort;
22
22
  /** 1-based page number. */
23
23
  page?: number;
24
24
  };
@@ -32,9 +32,9 @@ export const SORT_OPTIONS = [
32
32
  { value: "alphabetical", label: "Alphabetical" },
33
33
  ] as const;
34
34
 
35
- export type ItemsSort = (typeof SORT_OPTIONS)[number]["value"];
35
+ export type IndexSort = (typeof SORT_OPTIONS)[number]["value"];
36
36
 
37
- const DEFAULT_SORT: ItemsSort = "recently-updated";
37
+ const DEFAULT_SORT: IndexSort = "recently-updated";
38
38
  const DEFAULT_PAGE = 1;
39
39
  const DEFAULT_PAGE_SIZE = 20;
40
40
 
@@ -55,13 +55,13 @@ const KEYS = {
55
55
  * Read filters from a URLSearchParams (or anything URLSearchParams-shaped,
56
56
  * e.g. the result of `new URL(req.url).searchParams`).
57
57
  */
58
- export function filtersFromSearchParams(sp: URLSearchParams): ItemsFilters {
58
+ export function filtersFromSearchParams(sp: URLSearchParams): IndexFilters {
59
59
  const rawSort = sp.get(KEYS.sort);
60
60
  // Backwards-compat: old "most-mature" sort now maps to "best-overall".
61
61
  const normalizedSort = rawSort === "most-mature" ? "best-overall" : rawSort;
62
- const sort: ItemsSort | undefined =
63
- normalizedSort && SORT_OPTIONS.some((o) => o.value === normalizedSort)
64
- ? (normalizedSort as ItemsSort)
62
+ const sort: IndexSort | undefined =
63
+ normalizedSort && (SORT_OPTIONS as readonly { value: string }[]).some((o) => o.value === normalizedSort)
64
+ ? (normalizedSort as IndexSort)
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;
@@ -84,7 +84,7 @@ export function filtersFromSearchParams(sp: URLSearchParams): ItemsFilters {
84
84
  * Undefined / empty values are dropped. Defaults (sort, page 1, comfortable
85
85
  * density) are also dropped to keep URLs short and canonical.
86
86
  */
87
- export function searchParamsFromFilters(f: ItemsFilters): URLSearchParams {
87
+ export function searchParamsFromFilters(f: IndexFilters): URLSearchParams {
88
88
  const sp = new URLSearchParams();
89
89
  if (f.q) sp.set(KEYS.q, f.q);
90
90
  for (const v of f.stacks ?? []) sp.append(KEYS.stacks, v);
@@ -100,7 +100,7 @@ export function searchParamsFromFilters(f: ItemsFilters): URLSearchParams {
100
100
  }
101
101
 
102
102
  /** True if any filter is active (i.e. the result list isn't "all items"). */
103
- export function hasAnyFilter(f: ItemsFilters): boolean {
103
+ export function hasAnyFilter(f: IndexFilters): boolean {
104
104
  if (f.q && f.q.trim()) return true;
105
105
  if (f.lens) return true;
106
106
  return Boolean(
@@ -139,7 +139,7 @@ function recordAddedAt(record: IndexRecord): string | null {
139
139
  return record.curation?.reviewedAt ?? null;
140
140
  }
141
141
 
142
- export function applySort(items: IndexRecord[], sort: ItemsSort): IndexRecord[] {
142
+ export function applySort(items: IndexRecord[], sort: IndexSort): IndexRecord[] {
143
143
  const arr = items.slice();
144
144
  const ts = (s?: string | null): number => (s ? new Date(s).valueOf() : 0);
145
145
  switch (sort) {
@@ -183,12 +183,12 @@ export function totalPages(itemCount: number, pageSize = PAGE_SIZE): number {
183
183
  }
184
184
 
185
185
  /** Resolve the effective sort from a filters object, applying default. */
186
- export function effectiveSort(f: ItemsFilters): ItemsSort {
186
+ export function effectiveSort(f: IndexFilters): IndexSort {
187
187
  return f.sort ?? DEFAULT_SORT;
188
188
  }
189
189
 
190
190
  /** Resolve the effective page from a filters object, applying default. */
191
- export function effectivePage(f: ItemsFilters): number {
191
+ export function effectivePage(f: IndexFilters): number {
192
192
  return f.page ?? DEFAULT_PAGE;
193
193
  }
194
194
 
@@ -199,7 +199,7 @@ export function effectivePage(f: ItemsFilters): number {
199
199
  * `q` is a case-insensitive substring search across name, owner,
200
200
  * description, and category. Other dimensions are exact match.
201
201
  */
202
- export function filterItems(items: IndexRecord[], f: ItemsFilters): IndexRecord[] {
202
+ export function filterRecords(items: IndexRecord[], f: IndexFilters): IndexRecord[] {
203
203
  const q = f.q?.trim().toLowerCase();
204
204
  const stacks = f.stacks?.length ? new Set(f.stacks) : null;
205
205
  const platforms = f.platforms?.length ? new Set(f.platforms) : null;
@@ -297,9 +297,9 @@ export function filterItems(items: IndexRecord[], f: ItemsFilters): IndexRecord[
297
297
 
298
298
  /** Build a flat list of "active filter" chips for display + removal. */
299
299
  export function activeFilterChips(
300
- f: ItemsFilters,
301
- ): { key: keyof ItemsFilters; value: string; label: string }[] {
302
- const out: { key: keyof ItemsFilters; value: string; label: string }[] = [];
300
+ f: IndexFilters,
301
+ ): { key: keyof IndexFilters; value: string; label: string }[] {
302
+ const out: { key: keyof IndexFilters; value: string; label: string }[] = [];
303
303
 
304
304
  if (f.q && f.q.trim()) {
305
305
  out.push({ key: "q", value: "", label: `“${f.q}”` });
@@ -346,11 +346,11 @@ export function activeFilterChips(
346
346
  * that no longer has results.
347
347
  */
348
348
  export function removeFilter(
349
- f: ItemsFilters,
350
- key: keyof ItemsFilters,
349
+ f: IndexFilters,
350
+ key: keyof IndexFilters,
351
351
  value: string,
352
- ): ItemsFilters {
353
- let next: ItemsFilters;
352
+ ): IndexFilters {
353
+ let next: IndexFilters;
354
354
  if (key === "q") {
355
355
  next = { ...f, q: undefined };
356
356
  } else {
@@ -401,13 +401,8 @@ export function buildFacets(items: IndexRecord[]) {
401
401
  };
402
402
  }
403
403
 
404
- // ── V1-published API aliases ─────────────────────────────────────────
405
- // The published `@grove-dev/astro@0.2.10` package exports these
406
- // under different names (`filterApps` for the filter function and
407
- // `AppsFilters` for the filter-state type). Re-export them under
408
- // the V1 names so templates can use either spelling, and so the
409
- // template's `apps/index.astro` (built against the published API)
410
- // also works against the local workspace source.
411
- export const filterApps = filterItems;
412
- export type AppsFilters = ItemsFilters;
413
- export type AppsSort = ItemsSort;
404
+ // ── V1-published API ─────────────────────────────────────────────────
405
+ // `IndexFilters` / `IndexSort` are the canonical V1 names for the
406
+ // filter-state type. The internal functions (filterRecords, applySort,
407
+ // paginate, buildFacets, etc.) operate on the generic `IndexRecord`
408
+ // shape and are intentionally framework-agnostic.
package/src/styles.css CHANGED
@@ -513,7 +513,8 @@
513
513
  * names (`card`, `btn-primary`, `btn-outline`, `btn-ghost`). New
514
514
  * components should use the `grove-` prefix. These rules mirror
515
515
  * the `grove-*` definitions above so the openapps-derived
516
- * components (ItemCard, AppCard, etc.) work without per-component
516
+ * components (ItemCard, AppCard, etc. kept as `ItemCard` for V1
517
+ * published API stability) work without per-component
517
518
  * edits.
518
519
  * ────────────────────────────────────────────────────────────────────*/
519
520
  .card {
@@ -539,6 +540,7 @@
539
540
 
540
541
  /* Chip — small inline label used for platforms/stacks/etc. on
541
542
  * ItemCard. Mirrors openapps' `.chip` from the ItemCard.astro
543
+ * (component name retained for V1 published API stability).
542
544
  * `<style>` block so the @apply in the component still works. */
543
545
  .chip {
544
546
  display: inline-flex;
@@ -25,9 +25,9 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@astrojs/check": "^0.9.9",
28
- "@grove-dev/astro": "0.2.13",
29
- "@grove-dev/cli": "0.2.13",
30
- "@grove-dev/core": "0.2.13",
28
+ "@grove-dev/astro": "0.2.14",
29
+ "@grove-dev/cli": "0.2.14",
30
+ "@grove-dev/core": "0.2.14",
31
31
  "@tailwindcss/vite": "^4.3.0",
32
32
  "astro": "^6.4.4",
33
33
  "marked": "^18.0.0",
@@ -1,6 +1,6 @@
1
1
  # example.com — full directory
2
2
 
3
- Generated: 2026-06-13T10:16:37.910Z
3
+ Generated: 2026-06-13T15:14:22.567Z
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-13T10:16:37.466Z</lastmod>
5
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
11
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
17
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
23
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
29
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
35
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
41
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
47
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
53
+ <lastmod>2026-06-13T15:14:22.098Z</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-13T10:16:37.466Z</lastmod>
59
+ <lastmod>2026-06-13T15:14:22.098Z</lastmod>
60
60
  <changefreq>weekly</changefreq>
61
61
  <priority>0.7</priority>
62
62
  </url>
@@ -67,6 +67,9 @@ interface SiteConfigPayload {
67
67
  kind?: "project" | "resource" | "entity";
68
68
  routeSlug?: string;
69
69
  itemSlug?: string;
70
+ /** V1 canonical field name for the record detail slug
71
+ * (replaces the V0 `itemSlug` field). */
72
+ recordSlug?: string;
70
73
  labelSingular?: string;
71
74
  labelPlural?: string;
72
75
  };
@@ -226,10 +229,11 @@ export function indexSlug(): string {
226
229
  return blueprintConfig.routeSlug ?? "projects";
227
230
  }
228
231
 
229
- /** URL slug for a single item detail page (the dynamic
230
- * `[itemSlug]` segment). */
231
- export function itemSlug(): string {
232
- return blueprintConfig.itemSlug ?? "project";
232
+ /** URL slug for a single record detail page (the dynamic
233
+ * `[recordSlug]` segment). Default "project" for backwards-compat
234
+ * with V0-published configs that exposed the field as `itemSlug`. */
235
+ export function recordSlugConfig(): string {
236
+ return blueprintConfig.recordSlug ?? blueprintConfig.itemSlug ?? "project";
233
237
  }
234
238
 
235
239
  /** Singular human label, e.g. "project", "resource", "entity". */
@@ -17,7 +17,7 @@
17
17
  * Generic across the 3 record kinds (project / resource / entity) —
18
18
  * non-project fields simply render nothing. The URL is dynamic on
19
19
  * both `[slug]` (blueprint route, e.g. `projects`/`resources`/
20
- * `entities`) and `[itemSlug]` (the record slug), so a single page
20
+ * `entities`) and `[recordSlug]` (the record slug), so a single page
21
21
  * file serves every blueprint and every record.
22
22
  */
23
23
  import siteConfig from "../../../data/generated/site-config.json";
@@ -54,12 +54,12 @@ export async function getStaticPaths() {
54
54
  /* not present */
55
55
  }
56
56
  return fullRecords.map((record) => ({
57
- params: { slug: dirSlug, itemSlug: record.slug },
57
+ params: { slug: dirSlug, recordSlug: record.slug },
58
58
  }));
59
59
  }
60
60
 
61
61
  const slug = Astro.params.slug ?? indexSlug();
62
- const recordSlug = Astro.params.itemSlug ?? "";
62
+ const recordSlug = Astro.params.recordSlug ?? "";
63
63
  const project = projectBySlug(recordSlug);
64
64
  const resource = resourceBySlug(recordSlug);
65
65
  const entity = entityBySlug(recordSlug);
@@ -5,7 +5,8 @@
5
5
  * Mirrors the openapps list structure:
6
6
  * - SmartLensTabs (All / Trending / Recently added / Established / Featured)
7
7
  * - RefinePanel (Stack / Platform / Category / License / Sort)
8
- * - ItemSection rows (full record cards via RecordSection)
8
+ * - RecordSection rows (full record cards; the `ItemSection` V0
9
+ * name was renamed to `RecordSection` in V1)
9
10
  * - ExploreByCategory / ExploreByStack (compact pill lists)
10
11
  *
11
12
  * Generic: the URL slug (e.g. `/projects/`, `/resources/`,
@@ -15,11 +16,11 @@
15
16
  */
16
17
  import siteConfig from "../../../data/generated/site-config.json";
17
18
  import { items, itemLabel, itemLabelPlural } from "../../data/records";
18
- import type { AppsFilters } from "@grove-dev/astro";
19
+ import type { IndexFilters } from "@grove-dev/astro";
19
20
  import BaseLayout from "@grove-dev/astro/layouts/BaseLayout.astro";
20
21
  import SmartLensTabs from "@grove-dev/astro/components/SmartLensTabs.astro";
21
22
  import RefinePanel from "@grove-dev/astro/components/RefinePanel.astro";
22
- import AppsIndexRow from "@grove-dev/astro/components/AppsIndexRow.astro";
23
+ import IndexRow from "@grove-dev/astro/components/IndexRow.astro";
23
24
  import ExploreByCategory from "@grove-dev/astro/components/ExploreByCategory.astro";
24
25
  import ExploreByStack from "@grove-dev/astro/components/ExploreByStack.astro";
25
26
  import {
@@ -30,7 +31,7 @@ import {
30
31
  countByStack,
31
32
  effectivePage,
32
33
  effectiveSort,
33
- filterApps,
34
+ filterRecords,
34
35
  filtersFromSearchParams,
35
36
  paginate,
36
37
  searchParamsFromFilters,
@@ -57,7 +58,7 @@ const filters = filtersFromSearchParams(Astro.url.searchParams);
57
58
  const facets = buildFacets(items);
58
59
  const sort = effectiveSort(filters);
59
60
  const requestedPage = effectivePage(filters);
60
- const filtered = filterApps(items, filters);
61
+ const filtered = filterRecords(items, filters);
61
62
  const sorted = applySort(filtered, sort);
62
63
  const pages = totalPages(sorted.length);
63
64
  const page = Math.min(requestedPage, pages);
@@ -106,15 +107,15 @@ const stackEntries = [...countByStack(items as Parameters<typeof countByStack>[0
106
107
  .map(([name, count]) => ({ name, slug: name, count }));
107
108
 
108
109
  function hrefForPage(target: number): string {
109
- const next: AppsFilters = { ...filters, page: target };
110
+ const next: IndexFilters = { ...filters, page: target };
110
111
  const query = searchParamsFromFilters(next).toString();
111
112
  return query ? `/${slug}?${query}` : `/${slug}`;
112
113
  }
113
114
 
114
- function hrefForRemove(key: keyof AppsFilters, value: string): string {
115
- const params = new URLSearchParams(Astro.url.searchParams);
116
- params.delete("page");
117
- const urlKey: Partial<Record<keyof AppsFilters, string>> = {
115
+ function hrefForRemove(key: keyof IndexFilters, value: string): string {
116
+ const params = new URLSearchParams();
117
+ const next: IndexFilters = { ...filters, page: 1 };
118
+ const urlKey: Partial<Record<keyof IndexFilters, string>> = {
118
119
  stacks: "stack",
119
120
  platforms: "platform",
120
121
  categories: "category",
@@ -266,8 +267,8 @@ function hrefForRemove(key: keyof AppsFilters, value: string): string {
266
267
 
267
268
  <ul id="results-list" class="m-0 flex list-none flex-col gap-3 p-0">
268
269
  {sorted.map((item) => (
269
- <li class="m-0 p-0" data-item-slug={item.slug}>
270
- <AppsIndexRow record={item as Parameters<typeof AppsIndexRow>[0]["record"]} detailHref={`/${slug}/${item.slug}`} />
270
+ <li class="m-0 p-0" data-record-slug={item.slug}>
271
+ <IndexRow record={item as Parameters<typeof IndexRow>[0]["record"]} detailHref={`/${slug}/${item.slug}`} />
271
272
  </li>
272
273
  ))}
273
274
  </ul>
@@ -369,11 +370,11 @@ function hrefForRemove(key: keyof AppsFilters, value: string): string {
369
370
  var order = new Map(filtered.map(function (item, index) { return [item.slug, index]; }));
370
371
  Array.from(list.children)
371
372
  .sort(function (a, b) {
372
- return (order.get(a.dataset.itemSlug) ?? Number.MAX_SAFE_INTEGER) -
373
- (order.get(b.dataset.itemSlug) ?? Number.MAX_SAFE_INTEGER);
373
+ return (order.get(a.dataset.recordSlug) ?? Number.MAX_SAFE_INTEGER) -
374
+ (order.get(b.dataset.recordSlug) ?? Number.MAX_SAFE_INTEGER);
374
375
  })
375
376
  .forEach(function (node) {
376
- node.hidden = !visible.has(node.dataset.itemSlug);
377
+ node.hidden = !visible.has(node.dataset.recordSlug);
377
378
  list.appendChild(node);
378
379
  });
379
380
 
@@ -0,0 +1,33 @@
1
+ ---
2
+ /**
3
+ * /apps/<slug> — V0-published alias URL → V1 canonical.
4
+ *
5
+ * The canonical V1 detail URL is `/<blueprint>/<recordSlug>` (e.g.
6
+ * `/projects/coolify`). The V0 published Astro template exposed
7
+ * `/apps/<slug>` as a static alias to keep the openapps-style URL
8
+ * working for project-directory blueprints. Now that the V1
9
+ * template uses the blueprint-aware dynamic route everywhere,
10
+ * this page is a pure redirect: any `/apps/<slug>` request is
11
+ * sent to the blueprint-canonical path.
12
+ */
13
+ import { indexSlug, fullRecords, projectBySlug, recordBySlug } from "../../data/records";
14
+
15
+ export async function getStaticPaths() {
16
+ return fullRecords.map((r) => ({ params: { recordSlug: r.slug } }));
17
+ }
18
+
19
+ const slug = indexSlug();
20
+ const recordSlug = Astro.params.recordSlug ?? "";
21
+
22
+ if (slug !== "projects") {
23
+ return Astro.redirect(`/${slug}/${recordSlug}`);
24
+ }
25
+
26
+ const record = recordBySlug(recordSlug);
27
+ if (!record) {
28
+ return Astro.redirect(`/${slug}`);
29
+ }
30
+
31
+ // Canonical V1 URL.
32
+ return Astro.redirect(`/${slug}/${recordSlug}`, 301);
33
+ ---
@@ -1,301 +0,0 @@
1
- ---
2
- /**
3
- * /apps/<slug> — alternate detail URL.
4
- *
5
- * Mirrors `/[slug]/[itemSlug].astro` (the blueprint-aware dynamic
6
- * detail page) at a static URL. For non-project blueprints
7
- * (resource-hub, ecosystem-map), redirect to the matching dynamic
8
- * route.
9
- */
10
- import { indexSlug, fullRecords, projectBySlug, recordBySlug } from "../../data/records";
11
- import BaseLayout from "@grove-dev/astro/layouts/BaseLayout.astro";
12
- import Icon from "@grove-dev/astro/components/Icon.astro";
13
- import ScoreBars from "@grove-dev/astro/components/ScoreBars.astro";
14
- import siteConfig from "../../../data/generated/site-config.json";
15
- import { getOwnerAndRepoFromRepoUrl, getOwnerAvatarUrl, formatRelative, formatStars, statusDisplay, prettySlug, labelDisplay } from "@grove-dev/astro";
16
-
17
- export async function getStaticPaths() {
18
- return fullRecords.map((r) => ({ params: { itemSlug: r.slug } }));
19
- }
20
-
21
- const slug = indexSlug();
22
- const itemSlug = Astro.params.itemSlug ?? "";
23
-
24
- if (slug !== "projects") {
25
- return Astro.redirect(`/${slug}/${itemSlug}`);
26
- }
27
-
28
- const record = recordBySlug(itemSlug);
29
- if (!record) {
30
- return Astro.redirect("/apps");
31
- }
32
-
33
- const project = projectBySlug(itemSlug);
34
- const isProject = record.kind === "project";
35
- const name = record.kind === "resource" ? record.title : record.name;
36
- const repoUrl = project?.repoUrl ?? (record.links as { github?: string } | undefined)?.github ?? "";
37
- const homepageUrl = record.links?.website ?? "";
38
- const logoUrl = project?.logoUrl;
39
- const stacks = project?.stacks ?? (project?.stack ? [project.stack] : []);
40
- const platforms = project?.platforms ?? [];
41
- const github = project?.github?.repository;
42
- const stars = github?.stargazers_count ?? 0;
43
- const starsLabel = formatStars(stars);
44
- const pushedAt = github?.pushed_at ?? null;
45
- const pushedLabel = formatRelative(pushedAt);
46
- const ownerRepo = repoUrl ? getOwnerAndRepoFromRepoUrl(repoUrl) : null;
47
- const avatarSrc = logoUrl ?? (ownerRepo ? getOwnerAvatarUrl(ownerRepo.owner, 80) : null);
48
- const initials = (name || "").replace(/[^a-z0-9]/gi, "").slice(0, 2).toUpperCase();
49
- const bestFor = project?.bestFor ?? [];
50
- const whyListed = project?.whyListed ?? [];
51
- const caveats = project?.caveats ?? [];
52
- const distribution = project?.distribution?.channels ?? [];
53
- const scores = project?.scores ?? null;
54
- const curationLabels = record.curation?.labels ?? [];
55
- const tags = record.tags ?? [];
56
- const healthStatus = project?.health?.status;
57
- const healthLabel = healthStatus ? statusDisplay(healthStatus) : null;
58
-
59
- const title = `${name} — ${siteConfig.name}`;
60
- const description = record.description ?? `${name} on ${siteConfig.name}`;
61
-
62
- const jsonLd: Record<string, unknown> | null = project
63
- ? {
64
- "@context": "https://schema.org",
65
- "@type": "SoftwareSourceCode",
66
- name,
67
- description: record.description ?? undefined,
68
- url: repoUrl || homepageUrl || undefined,
69
- codeRepository: repoUrl || undefined,
70
- programmingLanguage: github?.language ?? undefined,
71
- license: github?.license?.spdx_id ?? undefined,
72
- author: ownerRepo
73
- ? { "@type": "Organization", name: ownerRepo.owner, url: `https://github.com/${ownerRepo.owner}` }
74
- : undefined,
75
- }
76
- : null;
77
- ---
78
-
79
- <BaseLayout
80
- title={title}
81
- description={description}
82
- site={siteConfig}
83
- type="article"
84
- jsonLd={jsonLd ?? undefined}
85
- submitHref="/submit"
86
- submitLabel={`Submit ${name}`}
87
- >
88
- <article class="grove-section">
89
- <div class="grove-container-wide mx-auto px-5 sm:px-7">
90
- <nav class="mb-6 text-2xs text-ink-500 dark:text-ink-400" aria-label="Breadcrumb">
91
- <a href="/apps" class="hover:text-ink-900 dark:hover:text-ink-100">Apps</a>
92
- <span class="mx-1.5 text-ink-300 dark:text-ink-700">/</span>
93
- <span class="text-ink-700 dark:text-ink-300">{name}</span>
94
- </nav>
95
-
96
- <header class="grove-card flex flex-col gap-5 p-6 sm:flex-row sm:items-start">
97
- <div class="flex-shrink-0">
98
- {avatarSrc ? (
99
- <img
100
- src={avatarSrc}
101
- alt=""
102
- width="64"
103
- height="64"
104
- loading="lazy"
105
- decoding="async"
106
- class="h-16 w-16 rounded-lg border border-ink-200 object-contain bg-white p-1 dark:border-ink-800 dark:bg-ink-950"
107
- />
108
- ) : (
109
- <span
110
- aria-hidden="true"
111
- class="inline-flex h-16 w-16 items-center justify-center rounded-lg border border-ink-200 bg-ink-50 text-2xl font-semibold text-ink-700 dark:border-ink-800 dark:bg-ink-900 dark:text-ink-200"
112
- >
113
- {initials || "·"}
114
- </span>
115
- )}
116
- </div>
117
-
118
- <div class="min-w-0 flex-1">
119
- <div class="flex flex-wrap items-center gap-2">
120
- <span class="rounded-full border border-ink-200 px-2 py-0.5 text-2xs font-medium uppercase tracking-wider text-ink-700 dark:border-ink-800 dark:text-ink-300">
121
- {record.kind}
122
- </span>
123
- {record.category && (
124
- <span class="rounded-full border border-ink-200 px-2 py-0.5 text-2xs font-medium text-ink-700 dark:border-ink-800 dark:text-ink-300">
125
- {record.category}
126
- </span>
127
- )}
128
- {curationLabels.map((l) => (
129
- <span class="grove-badge" title={`Curated: ${labelDisplay(l) ?? l}`}>
130
- {labelDisplay(l) ?? prettySlug(l)}
131
- </span>
132
- ))}
133
- {healthLabel && (
134
- <span class="grove-badge grove-badge-stale">{healthLabel}</span>
135
- )}
136
- </div>
137
-
138
- <h1 class="m-0 mt-2 text-[1.75rem] sm:text-[2rem] font-semibold tracking-tight text-ink-900 dark:text-ink-100">
139
- {name}
140
- </h1>
141
-
142
- {ownerRepo && (
143
- <p class="m-0 mt-1 text-sm text-ink-500 dark:text-ink-400">
144
- <a
145
- href={`https://github.com/${ownerRepo.owner}`}
146
- target="_blank"
147
- rel="noopener noreferrer"
148
- class="text-inherit no-underline hover:text-ink-900 dark:hover:text-ink-100"
149
- >
150
- @{ownerRepo.owner}
151
- </a>
152
- <span class="mx-1 text-ink-300 dark:text-ink-700">/</span>
153
- <a
154
- href={repoUrl}
155
- target="_blank"
156
- rel="noopener noreferrer"
157
- class="text-inherit no-underline hover:text-ink-900 dark:hover:text-ink-100"
158
- >
159
- {ownerRepo.repo}
160
- </a>
161
- </p>
162
- )}
163
-
164
- {record.description && (
165
- <p class="m-0 mt-3 max-w-[68ch] text-base leading-relaxed text-ink-700 dark:text-ink-200">
166
- {record.description}
167
- </p>
168
- )}
169
-
170
- <div class="mt-5 flex flex-wrap gap-2">
171
- {repoUrl && (
172
- <a href={repoUrl} target="_blank" rel="noopener noreferrer" class="grove-btn grove-btn-primary">
173
- View on GitHub →
174
- </a>
175
- )}
176
- {homepageUrl && (
177
- <a href={homepageUrl} target="_blank" rel="noopener noreferrer" class="grove-btn grove-btn-outline">
178
- Homepage
179
- </a>
180
- )}
181
- </div>
182
- </div>
183
- </header>
184
-
185
- {project && (
186
- <section class="mt-8 grove-card p-6" aria-labelledby="scores-heading">
187
- <h2 id="scores-heading" class="m-0 text-lg font-semibold tracking-tight text-ink-900 dark:text-ink-100">
188
- Scores
189
- </h2>
190
- <div class="mt-4">
191
- <ScoreBars scores={scores} />
192
- </div>
193
- </section>
194
- )}
195
-
196
- {/* BestFor / WhyListed / Caveats grid */}
197
- {isProject && (bestFor.length > 0 || whyListed.length > 0 || caveats.length > 0) && (
198
- <section class="mt-8 grid grid-cols-1 gap-4 md:grid-cols-3" aria-label="Curation notes">
199
- {bestFor.length > 0 && (
200
- <div class="grove-card p-5">
201
- <h3 class="m-0 text-sm font-semibold uppercase tracking-wider text-ink-500 dark:text-ink-400">Best for</h3>
202
- <ul class="mt-3 m-0 flex list-none flex-col gap-1.5 p-0">
203
- {bestFor.map((b) => <li class="text-sm text-ink-700 dark:text-ink-200">— {b}</li>)}
204
- </ul>
205
- </div>
206
- )}
207
- {whyListed.length > 0 && (
208
- <div class="grove-card p-5">
209
- <h3 class="m-0 text-sm font-semibold uppercase tracking-wider text-ink-500 dark:text-ink-400">Why listed</h3>
210
- <ul class="mt-3 m-0 flex list-none flex-col gap-1.5 p-0">
211
- {whyListed.map((w) => <li class="text-sm text-ink-700 dark:text-ink-200">— {w}</li>)}
212
- </ul>
213
- </div>
214
- )}
215
- {caveats.length > 0 && (
216
- <div class="grove-card p-5">
217
- <h3 class="m-0 text-sm font-semibold uppercase tracking-wider text-ink-500 dark:text-ink-400">Caveats</h3>
218
- <ul class="mt-3 m-0 flex list-none flex-col gap-1.5 p-0">
219
- {caveats.map((c) => <li class="text-sm text-ink-700 dark:text-ink-200">— {c}</li>)}
220
- </ul>
221
- </div>
222
- )}
223
- </section>
224
- )}
225
-
226
- {/* Stack + Platform chips */}
227
- {isProject && (stacks.length > 0 || platforms.length > 0) && (
228
- <section class="mt-8" aria-labelledby="stacks-heading">
229
- <h2 id="stacks-heading" class="m-0 text-lg font-semibold tracking-tight text-ink-900 dark:text-ink-100">
230
- Stack & platforms
231
- </h2>
232
- <div class="mt-4 flex flex-col gap-3">
233
- {stacks.length > 0 && (
234
- <div class="flex flex-wrap items-center gap-2">
235
- <span class="text-2xs font-medium uppercase tracking-wider text-ink-500 dark:text-ink-400">Stack</span>
236
- {stacks.map((s) => (
237
- <span class="grove-badge inline-flex items-center gap-1.5">
238
- <Icon name={s} category="stack" size={14} />
239
- {s}
240
- </span>
241
- ))}
242
- </div>
243
- )}
244
- {platforms.length > 0 && (
245
- <div class="flex flex-wrap items-center gap-2">
246
- <span class="text-2xs font-medium uppercase tracking-wider text-ink-500 dark:text-ink-400">Platform</span>
247
- {platforms.map((p) => (
248
- <span class="grove-badge inline-flex items-center gap-1.5">
249
- <Icon name={p} category="platform" size={14} />
250
- {p}
251
- </span>
252
- ))}
253
- </div>
254
- )}
255
- </div>
256
- </section>
257
- )}
258
-
259
- {/* Tags */}
260
- {tags.length > 0 && (
261
- <section class="mt-8" aria-labelledby="tags-heading">
262
- <h2 id="tags-heading" class="m-0 text-lg font-semibold tracking-tight text-ink-900 dark:text-ink-100">
263
- Tags
264
- </h2>
265
- <ul class="mt-4 m-0 flex list-none flex-wrap gap-1.5 p-0">
266
- {tags.map((t) => (
267
- <li>
268
- <a href={`/apps?q=${encodeURIComponent(t)}`} class="grove-badge inline-flex items-center gap-1.5">{t}</a>
269
- </li>
270
- ))}
271
- </ul>
272
- </section>
273
- )}
274
-
275
- {/* Distribution channels */}
276
- {distribution.length > 0 && (
277
- <section class="mt-8" aria-labelledby="dist-heading">
278
- <h2 id="dist-heading" class="m-0 text-lg font-semibold tracking-tight text-ink-900 dark:text-ink-100">
279
- Distribution channels
280
- </h2>
281
- <ul class="mt-4 m-0 flex list-none flex-col gap-2 p-0">
282
- {distribution.map((c) => (
283
- <li class="grove-card flex flex-wrap items-baseline justify-between gap-2 p-3">
284
- <div class="flex flex-col">
285
- <span class="text-sm font-semibold text-ink-900 dark:text-ink-100">
286
- {c.label ?? c.type}
287
- {c.verified && <span class="ml-2 grove-badge grove-badge-new">Verified</span>}
288
- </span>
289
- {c.notes && <span class="text-xs text-ink-500 dark:text-ink-400">{c.notes}</span>}
290
- </div>
291
- <a href={c.url} target="_blank" rel="noopener noreferrer" class="grove-btn grove-btn-outline">
292
- {c.platform ?? c.type} →
293
- </a>
294
- </li>
295
- ))}
296
- </ul>
297
- </section>
298
- )}
299
- </div>
300
- </article>
301
- </BaseLayout>
@@ -1,146 +0,0 @@
1
- ---
2
- /**
3
- * /apps — alternate list URL.
4
- *
5
- * Mirrors `/[slug]/index.astro` (the blueprint-aware dynamic list
6
- * page) at a static URL so the openapps-style `/apps` route works
7
- * for project-directory blueprints without per-blueprint forks.
8
- *
9
- * For non-project blueprints (resource-hub → /resources,
10
- * ecosystem-map → /entities), this page redirects to the matching
11
- * dynamic route.
12
- */
13
- import { indexSlug, itemLabelPlural, items } from "../../data/records";
14
- import BaseLayout from "@grove-dev/astro/layouts/BaseLayout.astro";
15
- import SmartLensTabs from "@grove-dev/astro/components/SmartLensTabs.astro";
16
- import RefinePanel from "@grove-dev/astro/components/RefinePanel.astro";
17
- import AppsIndexRow from "@grove-dev/astro/components/AppsIndexRow.astro";
18
- import ExploreByCategory from "@grove-dev/astro/components/ExploreByCategory.astro";
19
- import ExploreByStack from "@grove-dev/astro/components/ExploreByStack.astro";
20
- import siteConfig from "../../../data/generated/site-config.json";
21
- import {
22
- activeFilterChips,
23
- applySort,
24
- buildFacets,
25
- effectivePage,
26
- effectiveSort,
27
- filterApps,
28
- filtersFromSearchParams,
29
- paginate,
30
- totalPages,
31
- } from "@grove-dev/astro";
32
-
33
- const slug = indexSlug();
34
-
35
- // Only render the static /apps route when the active blueprint is
36
- // project-directory (the openapps-style URL). For other blueprints,
37
- // redirect to the dynamic `/<slug>/` route.
38
- if (slug !== "projects") {
39
- return Astro.redirect(`/${slug}${Astro.url.search}`);
40
- }
41
-
42
- const total = items.length;
43
- const filters = filtersFromSearchParams(Astro.url.searchParams);
44
- const facets = buildFacets(items);
45
- const sort = effectiveSort(filters);
46
- const requestedPage = effectivePage(filters);
47
- const filtered = filterApps(items, filters);
48
- const sorted = applySort(filtered, sort);
49
- const pages = totalPages(sorted.length);
50
- const page = Math.min(requestedPage, pages);
51
- const visibleItems = paginate(sorted, page);
52
- const chips = activeFilterChips(filters);
53
- const itemPlural = itemLabelPlural();
54
-
55
- const title = `${itemPlural.charAt(0).toUpperCase()}${itemPlural.slice(1)} — ${siteConfig.name}`;
56
- const description = `Browse every curated ${itemPlural.replace(/s$/, "")} in the ${siteConfig.name} directory.`;
57
- ---
58
-
59
- <BaseLayout title={title} description={description} site={siteConfig}>
60
- <section class="grove-section">
61
- <div class="grove-container-wide mx-auto px-5 sm:px-7">
62
- <header class="mb-6">
63
- <span class="text-2xs font-medium uppercase tracking-wider text-ink-500 dark:text-ink-400">
64
- {itemPlural}
65
- </span>
66
- <h1 class="m-0 mt-1 text-[1.75rem] sm:text-[2.25rem] font-semibold tracking-tight text-ink-900 dark:text-ink-100">
67
- Browse the directory
68
- </h1>
69
- <p class="m-0 mt-2 max-w-2xl text-base leading-relaxed text-ink-700 dark:text-ink-200">
70
- Search and filter every curated {itemPlural.replace(/s$/, "")}. Use the
71
- lens tabs to focus on a curated angle, or refine by stack,
72
- platform, license, and status.
73
- </p>
74
- </header>
75
-
76
- <div class="mb-6">
77
- <SmartLensTabs
78
- currentParams={Astro.url.searchParams}
79
- pathPrefix="/apps"
80
- />
81
- </div>
82
-
83
- <div class="mb-8">
84
- <RefinePanel
85
- facets={facets}
86
- initial={filters}
87
- pathPrefix="/apps"
88
- />
89
- </div>
90
-
91
- {chips.length > 0 && (
92
- <ul class="mb-6 flex flex-wrap items-center gap-1.5" aria-label="Active filters">
93
- {chips.map((chip) => (
94
- <li>
95
- <a
96
- href={chip.removeHref}
97
- class="grove-badge inline-flex items-center gap-1.5 hover:border-ink-300 dark:hover:border-ink-700"
98
- title={`Remove filter: ${chip.label}`}
99
- >
100
- <span>{chip.label}</span>
101
- <span aria-hidden="true">×</span>
102
- </a>
103
- </li>
104
- ))}
105
- </ul>
106
- )}
107
-
108
- {visibleItems.length === 0 ? (
109
- <p class="grove-card p-8 text-center text-sm text-ink-500 dark:text-ink-400">
110
- No {itemPlural} match these filters. Try clearing a filter or two.
111
- </p>
112
- ) : (
113
- <ul class="m-0 grid list-none grid-cols-1 gap-3 p-0">
114
- {visibleItems.map((item) => (
115
- <li class="m-0 p-0">
116
- <AppsIndexRow record={item as Parameters<typeof AppsIndexRow>[0]["record"]} detailHref={`/apps/${item.slug}`} />
117
- </li>
118
- ))}
119
- </ul>
120
- )}
121
- </div>
122
- </section>
123
-
124
- <ExploreByCategory
125
- categories={[
126
- ...new Set(
127
- items
128
- .filter((i) => i.kind === "project")
129
- .map((i) => (i as { category?: string }).category ?? "")
130
- .filter(Boolean),
131
- ),
132
- ].map((name) => ({ name, slug: name }))}
133
- pathPrefix="/apps"
134
- />
135
- <ExploreByStack
136
- stacks={[
137
- ...new Set(
138
- items
139
- .filter((i) => i.kind === "project")
140
- .flatMap((i) => [(i as { stack?: string }).stack ?? "", ...(i as { stacks?: string[] }).stacks])
141
- .filter(Boolean),
142
- ),
143
- ].map((name) => ({ name, slug: name }))}
144
- pathPrefix="/apps"
145
- />
146
- </BaseLayout>