@grove-dev/astro 0.2.6 → 0.2.13

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.
Files changed (136) hide show
  1. package/dist/lib/display.d.ts +11 -17
  2. package/dist/lib/display.d.ts.map +1 -1
  3. package/dist/lib/display.js +43 -43
  4. package/dist/lib/display.js.map +1 -1
  5. package/dist/lib/format.d.ts +6 -7
  6. package/dist/lib/format.d.ts.map +1 -1
  7. package/dist/lib/format.js +11 -12
  8. package/dist/lib/format.js.map +1 -1
  9. package/dist/lib/lenses.d.ts +35 -73
  10. package/dist/lib/lenses.d.ts.map +1 -1
  11. package/dist/lib/lenses.js +144 -126
  12. package/dist/lib/lenses.js.map +1 -1
  13. package/dist/lib/repo.d.ts +11 -22
  14. package/dist/lib/repo.d.ts.map +1 -1
  15. package/dist/lib/repo.js +12 -25
  16. package/dist/lib/repo.js.map +1 -1
  17. package/dist/lib/scores.d.ts +15 -16
  18. package/dist/lib/scores.d.ts.map +1 -1
  19. package/dist/lib/scores.js +4 -11
  20. package/dist/lib/scores.js.map +1 -1
  21. package/dist/lib/search.d.ts +47 -129
  22. package/dist/lib/search.d.ts.map +1 -1
  23. package/dist/lib/search.js +195 -180
  24. package/dist/lib/search.js.map +1 -1
  25. package/dist/lib/taxonomy-counts.d.ts +7 -21
  26. package/dist/lib/taxonomy-counts.d.ts.map +1 -1
  27. package/dist/lib/taxonomy-counts.js +12 -31
  28. package/dist/lib/taxonomy-counts.js.map +1 -1
  29. package/package.json +4 -4
  30. package/src/components/AppsIndexRow.astro +55 -184
  31. package/src/components/AppsPagination.astro +45 -108
  32. package/src/components/CategoryGrid.astro +43 -31
  33. package/src/components/ContributorsGrid.astro +3 -3
  34. package/src/components/CurationGrid.astro +41 -0
  35. package/src/components/ExploreByStack.astro +6 -0
  36. package/src/components/FilterGroupMenu.astro +49 -0
  37. package/src/components/FilterOptions.astro +44 -0
  38. package/src/components/Hero.astro +198 -147
  39. package/src/components/Icon.astro +10 -3
  40. package/src/components/ItemCard.astro +266 -248
  41. package/src/components/RecordSection.astro +68 -33
  42. package/src/components/RefinePanel.astro +115 -141
  43. package/src/components/StackGrid.astro +32 -24
  44. package/src/components/WhyThisExists.astro +32 -32
  45. package/src/layouts/BaseLayout.astro +104 -49
  46. package/src/layouts/Container.astro +5 -44
  47. package/src/layouts/Footer.astro +31 -20
  48. package/src/layouts/Header.astro +40 -19
  49. package/src/layouts/SectionHeader.astro +27 -43
  50. package/src/layouts/Seo.astro +38 -56
  51. package/src/layouts/ThemeToggle.astro +35 -48
  52. package/src/lib/display.ts +46 -53
  53. package/src/lib/format.ts +11 -12
  54. package/src/lib/lenses.ts +151 -172
  55. package/src/lib/repo.ts +16 -28
  56. package/src/lib/scores.ts +15 -19
  57. package/src/lib/search.ts +222 -290
  58. package/src/lib/taxonomy-counts.ts +12 -46
  59. package/src/styles.css +207 -1
  60. package/templates/default/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  61. package/templates/default/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  62. package/templates/default/.github/ISSUE_TEMPLATE/record_submission.md +48 -0
  63. package/templates/default/.github/pull_request_template.md +27 -0
  64. package/templates/default/.github/workflows/build.yml +55 -0
  65. package/templates/default/.github/workflows/cleanup-stale-records.yml +48 -0
  66. package/templates/default/.github/workflows/daily-refresh.yml +53 -0
  67. package/templates/default/.github/workflows/sync-contributors.yml +53 -0
  68. package/templates/default/.github/workflows/sync-github-metadata.yml +58 -0
  69. package/templates/default/.github/workflows/validate-data.yml +35 -0
  70. package/templates/default/data/records/coolify.yml +46 -0
  71. package/templates/default/data/records/gitea.yml +46 -0
  72. package/templates/default/data/records/hoppscotch.yml +47 -0
  73. package/templates/default/data/records/inventree.yml +47 -0
  74. package/templates/default/data/records/label-studio.yml +46 -0
  75. package/templates/default/data/records/logseq.yml +48 -0
  76. package/templates/default/data/records/private-gpt.yml +47 -0
  77. package/templates/default/data/records/wakapi.yml +44 -0
  78. package/templates/default/data/taxonomy/categories.yml +47 -0
  79. package/templates/default/data/taxonomy/distribution-channels.yml +43 -0
  80. package/templates/default/data/taxonomy/platforms.yml +27 -0
  81. package/templates/default/data/taxonomy/stacks.yml +41 -0
  82. package/templates/default/grove.config.ts +1 -1
  83. package/templates/default/package.json +5 -4
  84. package/templates/default/public/icons/stacks/bun.svg +1 -0
  85. package/templates/default/public/icons/stacks/clojure.svg +1 -0
  86. package/templates/default/public/icons/stacks/clojurescript.svg +1 -0
  87. package/templates/default/public/icons/stacks/deno.svg +1 -0
  88. package/templates/default/public/icons/stacks/django.svg +1 -0
  89. package/templates/default/public/icons/stacks/docker.svg +1 -0
  90. package/templates/default/public/icons/stacks/go.svg +1 -0
  91. package/templates/default/public/icons/stacks/llm.svg +1 -0
  92. package/templates/default/public/icons/stacks/node.js.svg +1 -0
  93. package/templates/default/public/icons/stacks/sveltekit.svg +1 -0
  94. package/templates/default/public/icons/stacks/vue.svg +1 -0
  95. package/templates/default/public/llms-full.txt +197 -5
  96. package/templates/default/public/llms.txt +107 -6
  97. package/templates/default/public/sitemap.xml +63 -0
  98. package/templates/default/scripts/build-llms.mjs +123 -0
  99. package/templates/default/scripts/build-records-json.mjs +27 -0
  100. package/templates/default/scripts/build-sitemap.mjs +20 -0
  101. package/templates/default/scripts/cleanup-stale-records.mjs +20 -0
  102. package/templates/default/scripts/enrich-github-metadata.mjs +99 -0
  103. package/templates/default/scripts/fetch-icons.mjs +137 -0
  104. package/templates/default/scripts/migrate-legacy-to-schema-v1.mjs +86 -0
  105. package/templates/default/scripts/parse-legacy-readme.mjs +59 -0
  106. package/templates/default/scripts/refresh-records-activity.mjs +24 -0
  107. package/templates/default/scripts/repair-license-format.mjs +72 -0
  108. package/templates/default/scripts/report-cleanup-candidates.mjs +21 -0
  109. package/templates/default/scripts/seed-from-github.mjs +62 -0
  110. package/templates/default/scripts/sync-contributors.mjs +145 -0
  111. package/templates/default/scripts/sync-github-metadata.mjs +28 -0
  112. package/templates/default/scripts/validate-records.mjs +27 -0
  113. package/templates/default/src/data/records.ts +134 -51
  114. package/templates/default/src/pages/404.astro +64 -0
  115. package/templates/default/src/pages/{projects/[slug].astro → [slug]/[itemSlug].astro} +236 -66
  116. package/templates/default/src/pages/[slug]/index.astro +476 -0
  117. package/templates/default/src/pages/about.astro +165 -82
  118. package/templates/default/src/pages/apps/[itemSlug].astro +301 -0
  119. package/templates/default/src/pages/apps/index.astro +146 -0
  120. package/templates/default/src/pages/contributors.astro +184 -0
  121. package/templates/default/src/pages/index.astro +119 -162
  122. package/templates/default/src/pages/submit.astro +276 -114
  123. package/templates/default/wrangler.jsonc +28 -0
  124. package/LICENSE +0 -21
  125. package/templates/default/data/generated/apps.json +0 -1
  126. package/templates/default/data/generated/records.full.json +0 -8
  127. package/templates/default/data/generated/records.index.json +0 -7
  128. package/templates/default/data/generated/records.json +0 -8
  129. package/templates/default/data/generated/repo-stats.json +0 -1
  130. package/templates/default/data/generated/site-config.json +0 -31
  131. package/templates/default/src/components/layout/BaseLayout.astro +0 -47
  132. package/templates/default/src/components/layout/Container.astro +0 -18
  133. package/templates/default/src/components/layout/Footer.astro +0 -27
  134. package/templates/default/src/components/layout/Header.astro +0 -43
  135. package/templates/default/src/lib/markdown.ts +0 -171
  136. package/templates/default/src/pages/projects/index.astro +0 -193
@@ -1,60 +1,26 @@
1
- /**
2
- * Build-time helpers that compute taxonomy counts from an array of
3
- * records. Generic over any object that carries the index-payload
4
- * fields the UI cares about (`category`, `stack` / `stacks`,
5
- * `curation.labels`). No filesystem / data import — consumers pass
6
- * the records explicitly so this stays testable.
7
- *
8
- * All functions are synchronous and cheap — they're called from
9
- * Astro page frontmatter at build time, never on the client.
10
- */
11
-
12
- export interface Taxonomable {
1
+ type TaxonomyRecord = {
13
2
  category?: string;
14
3
  stack?: string;
15
4
  stacks?: string[];
16
- curation?: { labels?: string[] };
17
- }
5
+ };
18
6
 
19
- /** Number of records per category name. */
20
- export function countByCategory<T extends Taxonomable>(
21
- records: T[],
22
- ): Map<string, number> {
7
+ /** Number of items in the directory, per category name. */
8
+ export function countByCategory(items: TaxonomyRecord[] = []): Map<string, number> {
23
9
  const m = new Map<string, number>();
24
- for (const r of records) {
25
- const k = r.category || "Other";
10
+ for (const a of items) {
11
+ const k = a.category || "Other";
26
12
  m.set(k, (m.get(k) ?? 0) + 1);
27
13
  }
28
14
  return m;
29
15
  }
30
16
 
31
- /** Number of records per primary stack (combines `stack` and `stacks`). */
32
- export function countByStack<T extends Taxonomable>(
33
- records: T[],
34
- ): Map<string, number> {
35
- const m = new Map<string, number>();
36
- for (const r of records) {
37
- const keys = new Set(
38
- [r.stack, ...(r.stacks ?? [])].filter(
39
- (s): s is string => Boolean(s),
40
- ),
41
- );
42
- for (const k of keys) {
43
- m.set(k, (m.get(k) ?? 0) + 1);
44
- }
45
- }
46
- return m;
47
- }
48
-
49
- /** Number of records per curated label (curation.labels). */
50
- export function countByLabel<T extends Taxonomable>(
51
- records: T[],
52
- ): Map<string, number> {
17
+ /** Number of items in the directory, per primary stack. */
18
+ export function countByStack(items: TaxonomyRecord[] = []): Map<string, number> {
53
19
  const m = new Map<string, number>();
54
- for (const r of records) {
55
- for (const l of r.curation?.labels ?? []) {
56
- m.set(l, (m.get(l) ?? 0) + 1);
57
- }
20
+ for (const a of items) {
21
+ const stacks = new Set([a.stack, ...(a.stacks ?? [])].filter(Boolean) as string[]);
22
+ if (stacks.size === 0) stacks.add("Other");
23
+ for (const stack of stacks) m.set(stack, (m.get(stack) ?? 0) + 1);
58
24
  }
59
25
  return m;
60
26
  }
package/src/styles.css CHANGED
@@ -16,6 +16,9 @@
16
16
  * removed) prefix. Only `grove-*` remains.
17
17
  */
18
18
 
19
+ @import "tailwindcss";
20
+ @source "./**/*.{astro,html,js,jsx,ts,tsx}";
21
+
19
22
  @theme {
20
23
  /* ── Neutral ink scale (V1 default) ───────────────────────────── */
21
24
  --color-ink-50: #fafafa;
@@ -154,7 +157,7 @@
154
157
  line-height: 1.55;
155
158
  }
156
159
 
157
- body.dark {
160
+ .dark body {
158
161
  background: var(--color-ink-950);
159
162
  color: var(--color-ink-100);
160
163
  }
@@ -199,6 +202,84 @@
199
202
  }
200
203
  }
201
204
 
205
+ /* ──────────────────────────────────────────────────────────────────
206
+ * Rendered record Markdown
207
+ * ────────────────────────────────────────────────────────────────── */
208
+ .grove-prose {
209
+ max-width: 72ch;
210
+ color: var(--color-ink-700);
211
+ font-size: 0.9375rem;
212
+ line-height: 1.75;
213
+ }
214
+
215
+ .dark .grove-prose {
216
+ color: var(--color-ink-200);
217
+ }
218
+
219
+ .grove-prose :where(h1, h2, h3, h4) {
220
+ margin: 1.75em 0 0.65em;
221
+ color: var(--color-ink-900);
222
+ font-weight: 650;
223
+ line-height: 1.25;
224
+ }
225
+
226
+ .dark .grove-prose :where(h1, h2, h3, h4) {
227
+ color: var(--color-ink-100);
228
+ }
229
+
230
+ .grove-prose :where(p, ul, ol, pre, blockquote) {
231
+ margin: 1em 0;
232
+ }
233
+
234
+ .grove-prose :where(ul, ol) {
235
+ padding-left: 1.5rem;
236
+ }
237
+
238
+ .grove-prose a {
239
+ color: var(--color-accent);
240
+ text-decoration: underline;
241
+ text-underline-offset: 0.18em;
242
+ }
243
+
244
+ .grove-prose :where(code, pre) {
245
+ font-family: var(--font-mono);
246
+ }
247
+
248
+ .grove-prose code {
249
+ border-radius: 0.25rem;
250
+ background: var(--color-ink-100);
251
+ padding: 0.1em 0.3em;
252
+ font-size: 0.875em;
253
+ }
254
+
255
+ .dark .grove-prose code {
256
+ background: var(--color-ink-800);
257
+ }
258
+
259
+ .grove-prose pre {
260
+ overflow-x: auto;
261
+ border: 1px solid var(--color-ink-200);
262
+ border-radius: var(--radius-lg);
263
+ background: var(--color-ink-50);
264
+ padding: 1rem;
265
+ }
266
+
267
+ .dark .grove-prose pre {
268
+ border-color: var(--color-ink-800);
269
+ background: var(--color-ink-900);
270
+ }
271
+
272
+ .grove-prose pre code {
273
+ background: transparent;
274
+ padding: 0;
275
+ }
276
+
277
+ .grove-prose blockquote {
278
+ border-left: 3px solid var(--color-ink-300);
279
+ padding-left: 1rem;
280
+ color: var(--color-ink-500);
281
+ }
282
+
202
283
  /* ──────────────────────────────────────────────────────────────────
203
284
  * Component classes — shared by the showcase component library.
204
285
  * Use these directly; you can also use the equivalent Tailwind
@@ -206,6 +287,31 @@
206
287
  * ────────────────────────────────────────────────────────────────── */
207
288
 
208
289
  @layer components {
290
+ /*
291
+ * Stable container classes for consumers of the packaged stylesheet.
292
+ * Tailwind does not emit utilities referenced only inside a dependency,
293
+ * so relying on `max-w-container` alone can leave template content
294
+ * unconstrained.
295
+ */
296
+ .grove-container,
297
+ .grove-container-wide,
298
+ .grove-container-narrow {
299
+ width: 100%;
300
+ margin-inline: auto;
301
+ }
302
+
303
+ .grove-container {
304
+ max-width: var(--container-container);
305
+ }
306
+
307
+ .grove-container-wide {
308
+ max-width: var(--container-wide);
309
+ }
310
+
311
+ .grove-container-narrow {
312
+ max-width: var(--container-narrow);
313
+ }
314
+
209
315
  /* Section spacing — consistent vertical rhythm */
210
316
  .grove-section {
211
317
  padding-top: 3rem;
@@ -401,3 +507,103 @@
401
507
  background: #ffffff;
402
508
  }
403
509
  }
510
+
511
+ /* ────────────────────────────────────────────────────────────────────
512
+ * Backwards-compat aliases — openapps used the unprefixed utility
513
+ * names (`card`, `btn-primary`, `btn-outline`, `btn-ghost`). New
514
+ * components should use the `grove-` prefix. These rules mirror
515
+ * the `grove-*` definitions above so the openapps-derived
516
+ * components (ItemCard, AppCard, etc.) work without per-component
517
+ * edits.
518
+ * ────────────────────────────────────────────────────────────────────*/
519
+ .card {
520
+ border: 1px solid var(--color-ink-200);
521
+ background: #ffffff;
522
+ border-radius: 0.5rem;
523
+ transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
524
+ }
525
+ .dark .card {
526
+ border-color: var(--color-ink-800);
527
+ background: var(--color-ink-950);
528
+ }
529
+ .card-hover:hover {
530
+ border-color: var(--color-ink-300);
531
+ background: rgba(244, 244, 245, 0.6);
532
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 4px 12px -2px rgba(0, 0, 0, 0.06);
533
+ }
534
+ .dark .card-hover:hover {
535
+ border-color: var(--color-ink-700);
536
+ background: rgba(24, 24, 27, 0.4);
537
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px -2px rgba(0, 0, 0, 0.3);
538
+ }
539
+
540
+ /* Chip — small inline label used for platforms/stacks/etc. on
541
+ * ItemCard. Mirrors openapps' `.chip` from the ItemCard.astro
542
+ * `<style>` block so the @apply in the component still works. */
543
+ .chip {
544
+ display: inline-flex;
545
+ align-items: center;
546
+ gap: 0.25rem;
547
+ border-radius: 0.375rem;
548
+ border: 1px solid var(--color-ink-200);
549
+ background: #ffffff;
550
+ padding: 0.125rem 0.375rem;
551
+ font-size: 0.6875rem;
552
+ font-weight: 500;
553
+ color: var(--color-ink-700);
554
+ transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease;
555
+ }
556
+ .dark .chip {
557
+ border-color: var(--color-ink-200);
558
+ background: var(--color-ink-950);
559
+ color: var(--color-ink-300);
560
+ }
561
+ .chip-stack {
562
+ background: var(--color-ink-50);
563
+ }
564
+ .dark .chip-stack {
565
+ background: rgba(24, 24, 27, 0.6);
566
+ }
567
+ .btn-primary,
568
+ .btn-outline,
569
+ .btn-ghost {
570
+ display: inline-flex;
571
+ align-items: center;
572
+ justify-content: center;
573
+ gap: 0.375rem;
574
+ border-radius: 0.5rem;
575
+ padding: 0.5rem 0.875rem;
576
+ font-size: 0.875rem;
577
+ font-weight: 500;
578
+ white-space: nowrap;
579
+ transition: color 0.15s, background-color 0.15s, border-color 0.15s;
580
+ cursor: pointer;
581
+ border: 1px solid transparent;
582
+ text-decoration: none;
583
+ }
584
+ .btn-primary {
585
+ border-color: var(--color-ink-900);
586
+ background: var(--color-ink-900);
587
+ color: var(--color-ink-50);
588
+ }
589
+ .btn-primary:hover {
590
+ background: var(--color-ink-700);
591
+ border-color: var(--color-ink-700);
592
+ }
593
+ .btn-outline {
594
+ border-color: var(--color-ink-200);
595
+ background: var(--color-ink-50);
596
+ color: var(--color-ink-700);
597
+ }
598
+ .btn-outline:hover {
599
+ border-color: var(--color-ink-300);
600
+ background: var(--color-ink-100);
601
+ }
602
+ .btn-ghost {
603
+ background: transparent;
604
+ color: var(--color-ink-500);
605
+ }
606
+ .btn-ghost:hover {
607
+ color: var(--color-ink-900);
608
+ background: var(--color-ink-100);
609
+ }
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something is broken on the site
4
+ title: "[bug] "
5
+ labels: ["bug"]
6
+ assignees: []
7
+ ---
8
+
9
+ ## What happened
10
+
11
+ A clear, concise description of the bug.
12
+
13
+ ## Steps to reproduce
14
+
15
+ 1. Go to '…'
16
+ 2. Click on '…'
17
+ 3. Scroll down to '…'
18
+ 4. See error
19
+
20
+ ## What I expected
21
+
22
+ A clear, concise description of what you expected to happen.
23
+
24
+ ## What I saw
25
+
26
+ Screenshots, error messages, console output — anything that helps.
27
+
28
+ ## Environment
29
+
30
+ - Browser:
31
+ - OS:
32
+ - Page URL:
33
+ - Viewport size (rough):
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an improvement to the site
4
+ title: "[feature] "
5
+ labels: ["enhancement"]
6
+ assignees: []
7
+ ---
8
+
9
+ ## The problem
10
+
11
+ What's missing or awkward today?
12
+
13
+ ## The proposed solution
14
+
15
+ What would you like to see? Mockups, links, references — anything
16
+ that helps us understand the shape of the change.
17
+
18
+ ## Alternatives considered
19
+
20
+ Any other approaches you weighed, and why this one wins.
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: Submit a record
3
+ about: Suggest a new entry for the directory
4
+ title: "[submit] "
5
+ labels: ["submission"]
6
+ assignees: []
7
+ ---
8
+
9
+ Thanks for taking the time to suggest a new entry! Please fill in the
10
+ template below — the more complete it is, the faster it lands.
11
+
12
+ **Important:** this issue tracker is for **suggestions**, not for the
13
+ actual data. Once approved, a maintainer will add the record to
14
+ `data/records/<slug>.yml` (or invite you to open a PR).
15
+
16
+ ## 1. Basics
17
+
18
+ - **Name:**
19
+ - **One-line description:**
20
+ - **Category:** (e.g. Mobile, Web, DevOps, AI/ML)
21
+ - **Primary stack:** (e.g. Flutter, Vue, Go, Python)
22
+ - **Platforms:** (e.g. iOS, Android, Web, Linux, Self-host)
23
+ - **Project type:** (real-app, production, reference, library, tool,
24
+ demo, template, historical)
25
+ - **Difficulty:** (beginner, intermediate, advanced)
26
+
27
+ ## 2. Links
28
+
29
+ - **Repository URL:** (the canonical `https://github.com/owner/repo`)
30
+ - **Website / homepage:**
31
+ - **Docs:**
32
+
33
+ ## 3. Why it deserves a spot
34
+
35
+ A short paragraph — what makes it stand out, what it's good for, who
36
+ should look at it.
37
+
38
+ ## 4. Caveats
39
+
40
+ Anything we should know about: license quirks, abandoned status,
41
+ paid-only features, etc.
42
+
43
+ ## 5. Checkboxes
44
+
45
+ - [ ] The repo is **public** on GitHub / another public forge
46
+ - [ ] It's **open source** under an OSI-approved license
47
+ - [ ] It has been **maintained** in the last 12 months
48
+ - [ ] I am **not** the author (or I'm disclosing that I am)
@@ -0,0 +1,27 @@
1
+ ## What this PR does
2
+
3
+ A short summary of the change. One or two sentences. If it closes an
4
+ issue, write "Closes #123" so it auto-links.
5
+
6
+ ## Why
7
+
8
+ The motivation. Link to any relevant issues or discussions. If this
9
+ is a UI change, attach a before/after screenshot.
10
+
11
+ ## How to verify
12
+
13
+ Steps for a reviewer to follow:
14
+
15
+ 1. `pnpm install`
16
+ 2. `pnpm exec grove validate`
17
+ 3. `pnpm grove:dev` and open `…`
18
+ 4. Confirm that `…`
19
+
20
+ ## Checklist
21
+
22
+ - [ ] `pnpm exec grove validate` passes
23
+ - [ ] `pnpm run build` succeeds locally
24
+ - [ ] For record changes: the `slug` is unique and matches the
25
+ filename (`data/records/<slug>.yml`)
26
+ - [ ] For new categories / stacks / platforms: the field appears
27
+ sensibly in `Browse by category` and `Browse by stack`
@@ -0,0 +1,55 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ build:
10
+ name: grove build
11
+ runs-on: ubuntu-latest
12
+ timeout-minutes: 15
13
+ permissions:
14
+ contents: read
15
+ pages: write
16
+ id-token: write
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: pnpm/action-setup@v4
21
+ with:
22
+ version: 10
23
+
24
+ - uses: actions/setup-node@v4
25
+ with:
26
+ node-version: 20
27
+ cache: pnpm
28
+
29
+ - name: Install dependencies
30
+ run: pnpm install --frozen-lockfile
31
+
32
+ # `build` chains build:data + build:sitemap + build:llms + astro build.
33
+ # Site URL is overridden so sitemap/OG/canonical links resolve to
34
+ # the deployed URL rather than the placeholder in grove.config.ts.
35
+ - name: Build site
36
+ env:
37
+ SITE_URL: ${{ vars.SITE_URL || github.pages.custom_domain || format('https://{0}.github.io/{1}', github.repository_owner, github.event.repository.name) }}
38
+ run: pnpm run build
39
+
40
+ - name: Setup Pages
41
+ uses: actions/configure-pages@v5
42
+
43
+ - name: Upload artifact
44
+ uses: actions/upload-pages-artifact@v3
45
+ with:
46
+ path: ./dist
47
+
48
+ - name: Deploy to GitHub Pages
49
+ id: deployment
50
+ uses: actions/deploy-pages@v4
51
+
52
+ - name: Summary
53
+ if: success()
54
+ run: |
55
+ echo "✅ Deployed to ${{ steps.deployment.outputs.page_url }}"
@@ -0,0 +1,48 @@
1
+ name: Cleanup stale records
2
+
3
+ on:
4
+ schedule:
5
+ # Monthly — first Monday 05:00 UTC. Cheap enough to run daily
6
+ # if you want, but most repos don't change status that often.
7
+ - cron: "0 5 1-7 * 1"
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ cleanup:
12
+ name: grove cleanup stale
13
+ runs-on: ubuntu-latest
14
+ timeout-minutes: 10
15
+ permissions:
16
+ contents: read
17
+ issues: write
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - uses: pnpm/action-setup@v4
22
+ with:
23
+ version: 10
24
+
25
+ - uses: actions/setup-node@v4
26
+ with:
27
+ node-version: 20
28
+ cache: pnpm
29
+
30
+ - name: Install dependencies
31
+ run: pnpm install --frozen-lockfile
32
+
33
+ # `grove cleanup stale` lists records whose health signals say
34
+ # they need human review (archived, no commits in 12+ months,
35
+ # unparseable repo, etc). The report is rendered as a Markdown
36
+ # summary in the workflow run.
37
+ - name: Run cleanup report
38
+ id: report
39
+ run: pnpm exec grove cleanup stale --report > cleanup-report.md
40
+
41
+ - name: Summarise
42
+ run: |
43
+ if [ -s cleanup-report.md ]; then
44
+ echo "## Cleanup candidates" >> $GITHUB_STEP_SUMMARY
45
+ cat cleanup-report.md >> $GITHUB_STEP_SUMMARY
46
+ else
47
+ echo "✅ No records need cleanup." >> $GITHUB_STEP_SUMMARY
48
+ fi
@@ -0,0 +1,53 @@
1
+ name: Daily records refresh
2
+
3
+ on:
4
+ schedule:
5
+ # Daily — 06:00 UTC. Refreshes stars, forks, and the most
6
+ # recent commit date for every record so the home page and
7
+ # /apps filters stay accurate.
8
+ - cron: "0 6 * * *"
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ refresh:
13
+ name: refresh activity
14
+ runs-on: ubuntu-latest
15
+ timeout-minutes: 15
16
+ permissions:
17
+ contents: write
18
+ pull-requests: write
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - uses: pnpm/action-setup@v4
23
+ with:
24
+ version: 10
25
+
26
+ - uses: actions/setup-node@v4
27
+ with:
28
+ node-version: 20
29
+ cache: pnpm
30
+
31
+ - name: Install dependencies
32
+ run: pnpm install --frozen-lockfile
33
+
34
+ - name: Refresh activity
35
+ env:
36
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37
+ # `grove sync github` walks every record, fetches the
38
+ # latest stars/forks/pushed_at, and writes back to the
39
+ # corresponding yml file. Idempotent — no change if the
40
+ # record is already up to date.
41
+ run: pnpm exec grove sync github
42
+
43
+ - name: Open PR if records changed
44
+ uses: peter-evans/create-pull-request@v6
45
+ with:
46
+ commit-message: "chore(data): daily records refresh"
47
+ title: "Daily records refresh"
48
+ body: |
49
+ Automated daily refresh of stars, forks, and last-commit
50
+ timestamps for every record. Generated by the
51
+ `daily-refresh` workflow.
52
+ branch: chore/daily-refresh
53
+ delete-branch: true
@@ -0,0 +1,53 @@
1
+ name: Sync contributors
2
+
3
+ on:
4
+ schedule:
5
+ # Weekly — Sunday 04:00 UTC (after the metadata sync).
6
+ - cron: "0 4 * * 0"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ sync:
11
+ name: sync contributors
12
+ runs-on: ubuntu-latest
13
+ timeout-minutes: 10
14
+ permissions:
15
+ contents: read
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: pnpm/action-setup@v4
20
+ with:
21
+ version: 10
22
+
23
+ - uses: actions/setup-node@v4
24
+ with:
25
+ node-version: 20
26
+ cache: pnpm
27
+
28
+ - name: Install dependencies
29
+ run: pnpm install --frozen-lockfile
30
+
31
+ # Walk the records' repoUrl fields, fetch each repo's
32
+ # /contributors endpoint, and write a single
33
+ # `data/generated/contributors.json` (consumed by the home
34
+ # page and /contributors page). The script lives at the root
35
+ # of the project — it's not a CLI command because contributor
36
+ # fan-in is tightly coupled to this directory's git history
37
+ # and doesn't generalise across forks.
38
+ - name: Sync contributors from GitHub
39
+ env:
40
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41
+ run: node scripts/sync-contributors.mjs
42
+
43
+ - name: Commit contributors.json
44
+ run: |
45
+ git config user.name "github-actions[bot]"
46
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
47
+ if git diff --quiet data/generated/contributors.json; then
48
+ echo "No changes to contributors.json"
49
+ else
50
+ git add data/generated/contributors.json
51
+ git commit -m "chore(data): refresh contributors"
52
+ git push
53
+ fi