@grove-dev/astro 0.3.1 → 0.3.2

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 (161) hide show
  1. package/README.md +9 -75
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +11 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/display.d.ts +1 -26
  6. package/dist/lib/display.d.ts.map +1 -1
  7. package/dist/lib/display.js +1 -103
  8. package/dist/lib/display.js.map +1 -1
  9. package/dist/lib/format.d.ts +1 -28
  10. package/dist/lib/format.d.ts.map +1 -1
  11. package/dist/lib/format.js +1 -71
  12. package/dist/lib/format.js.map +1 -1
  13. package/dist/lib/lenses.d.ts +1 -57
  14. package/dist/lib/lenses.d.ts.map +1 -1
  15. package/dist/lib/lenses.js +1 -198
  16. package/dist/lib/lenses.js.map +1 -1
  17. package/dist/lib/repo.d.ts +1 -19
  18. package/dist/lib/repo.d.ts.map +1 -1
  19. package/dist/lib/repo.js +1 -30
  20. package/dist/lib/repo.js.map +1 -1
  21. package/dist/lib/scores.d.ts +1 -36
  22. package/dist/lib/scores.d.ts.map +1 -1
  23. package/dist/lib/scores.js +1 -75
  24. package/dist/lib/scores.js.map +1 -1
  25. package/dist/lib/search.d.ts +1 -113
  26. package/dist/lib/search.d.ts.map +1 -1
  27. package/dist/lib/search.js +1 -379
  28. package/dist/lib/search.js.map +1 -1
  29. package/dist/lib/taxonomy-counts.d.ts +1 -10
  30. package/dist/lib/taxonomy-counts.d.ts.map +1 -1
  31. package/dist/lib/taxonomy-counts.js +1 -21
  32. package/dist/lib/taxonomy-counts.js.map +1 -1
  33. package/package.json +21 -9
  34. package/src/components/ContributorsGrid.astro +3 -3
  35. package/src/components/CurationGrid.astro +2 -2
  36. package/src/components/DirectoryIndexClient.astro +240 -0
  37. package/src/components/FilterGroupMenu.astro +8 -4
  38. package/src/components/FinalCta.astro +41 -0
  39. package/src/components/Hero.astro +15 -18
  40. package/src/components/Icon.astro +49 -7
  41. package/src/components/RefinePanel.astro +7 -7
  42. package/src/components/SmartLensTabs.astro +5 -4
  43. package/src/components/StackGrid.astro +1 -1
  44. package/src/components/SubmissionClient.astro +133 -0
  45. package/src/index.ts +11 -1
  46. package/src/layouts/BaseLayout.astro +19 -1
  47. package/src/layouts/Footer.astro +25 -56
  48. package/src/layouts/Header.astro +33 -15
  49. package/src/layouts/ThemeToggle.astro +7 -3
  50. package/src/lib/display.ts +1 -111
  51. package/src/lib/format.ts +1 -64
  52. package/src/lib/lenses.ts +1 -220
  53. package/src/lib/repo.ts +1 -32
  54. package/src/lib/scores.ts +1 -90
  55. package/src/lib/search.ts +1 -418
  56. package/src/lib/taxonomy-counts.ts +1 -26
  57. package/{templates/default/src/data/records.ts → src/server/directory.ts} +12 -8
  58. package/src/server/index.ts +2 -0
  59. package/src/server/models.ts +432 -0
  60. package/dist/template-routes.test.d.ts +0 -2
  61. package/dist/template-routes.test.d.ts.map +0 -1
  62. package/dist/template-routes.test.js +0 -63
  63. package/dist/template-routes.test.js.map +0 -1
  64. package/dist/theme.test.d.ts +0 -2
  65. package/dist/theme.test.d.ts.map +0 -1
  66. package/dist/theme.test.js +0 -60
  67. package/dist/theme.test.js.map +0 -1
  68. package/src/template-routes.test.ts +0 -103
  69. package/src/theme.test.ts +0 -76
  70. package/templates/default/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
  71. package/templates/default/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  72. package/templates/default/.github/ISSUE_TEMPLATE/record_submission.md +0 -48
  73. package/templates/default/.github/pull_request_template.md +0 -27
  74. package/templates/default/.github/workflows/build.yml +0 -53
  75. package/templates/default/.github/workflows/cleanup-stale-records.yml +0 -46
  76. package/templates/default/.github/workflows/daily-refresh.yml +0 -51
  77. package/templates/default/.github/workflows/sync-contributors.yml +0 -51
  78. package/templates/default/.github/workflows/sync-github-metadata.yml +0 -56
  79. package/templates/default/.github/workflows/validate-data.yml +0 -33
  80. package/templates/default/astro.config.mjs +0 -25
  81. package/templates/default/content/pages/about.md +0 -66
  82. package/templates/default/content/pages/methodology.md +0 -103
  83. package/templates/default/data/records/.gitkeep +0 -0
  84. package/templates/default/data/records/coolify.yml +0 -46
  85. package/templates/default/data/records/gitea.yml +0 -46
  86. package/templates/default/data/records/hoppscotch.yml +0 -47
  87. package/templates/default/data/records/inventree.yml +0 -47
  88. package/templates/default/data/records/label-studio.yml +0 -46
  89. package/templates/default/data/records/logseq.yml +0 -48
  90. package/templates/default/data/records/private-gpt.yml +0 -47
  91. package/templates/default/data/records/wakapi.yml +0 -44
  92. package/templates/default/data/taxonomy/categories.yml +0 -47
  93. package/templates/default/data/taxonomy/distribution-channels.yml +0 -43
  94. package/templates/default/data/taxonomy/platforms.yml +0 -27
  95. package/templates/default/data/taxonomy/stacks.yml +0 -41
  96. package/templates/default/grove.config.ts +0 -36
  97. package/templates/default/package.json +0 -43
  98. package/templates/default/public/icons/platforms/android.svg +0 -1
  99. package/templates/default/public/icons/platforms/apple-dark.svg +0 -1
  100. package/templates/default/public/icons/platforms/apple-light.svg +0 -1
  101. package/templates/default/public/icons/platforms/chrome.svg +0 -1
  102. package/templates/default/public/icons/platforms/chromeos.svg +0 -5
  103. package/templates/default/public/icons/platforms/desktop.svg +0 -4
  104. package/templates/default/public/icons/platforms/embedded.svg +0 -5
  105. package/templates/default/public/icons/platforms/ios.svg +0 -1
  106. package/templates/default/public/icons/platforms/linux.svg +0 -1
  107. package/templates/default/public/icons/platforms/macos.svg +0 -1
  108. package/templates/default/public/icons/platforms/ubuntu.svg +0 -1
  109. package/templates/default/public/icons/platforms/web.svg +0 -5
  110. package/templates/default/public/icons/platforms/windows.svg +0 -6
  111. package/templates/default/public/icons/stacks/android.svg +0 -1
  112. package/templates/default/public/icons/stacks/apple-dark.svg +0 -1
  113. package/templates/default/public/icons/stacks/apple-light.svg +0 -1
  114. package/templates/default/public/icons/stacks/bun.svg +0 -1
  115. package/templates/default/public/icons/stacks/capacitor.svg +0 -14
  116. package/templates/default/public/icons/stacks/clojure.svg +0 -1
  117. package/templates/default/public/icons/stacks/clojurescript.svg +0 -1
  118. package/templates/default/public/icons/stacks/dart.svg +0 -1
  119. package/templates/default/public/icons/stacks/deno.svg +0 -1
  120. package/templates/default/public/icons/stacks/django.svg +0 -1
  121. package/templates/default/public/icons/stacks/docker.svg +0 -1
  122. package/templates/default/public/icons/stacks/firebase.svg +0 -1
  123. package/templates/default/public/icons/stacks/flutter.svg +0 -1
  124. package/templates/default/public/icons/stacks/go.svg +0 -1
  125. package/templates/default/public/icons/stacks/graphql.svg +0 -1
  126. package/templates/default/public/icons/stacks/ionic.svg +0 -4
  127. package/templates/default/public/icons/stacks/java.svg +0 -1
  128. package/templates/default/public/icons/stacks/javascript.svg +0 -1
  129. package/templates/default/public/icons/stacks/kotlin.svg +0 -1
  130. package/templates/default/public/icons/stacks/llm.svg +0 -1
  131. package/templates/default/public/icons/stacks/mongodb.svg +0 -1
  132. package/templates/default/public/icons/stacks/node.js.svg +0 -1
  133. package/templates/default/public/icons/stacks/nodejs.svg +0 -1
  134. package/templates/default/public/icons/stacks/python.svg +0 -1
  135. package/templates/default/public/icons/stacks/rag.svg +0 -7
  136. package/templates/default/public/icons/stacks/react-native.svg +0 -1
  137. package/templates/default/public/icons/stacks/react.svg +0 -1
  138. package/templates/default/public/icons/stacks/rust.svg +0 -1
  139. package/templates/default/public/icons/stacks/solidity.svg +0 -1
  140. package/templates/default/public/icons/stacks/sveltekit.svg +0 -1
  141. package/templates/default/public/icons/stacks/swift.svg +0 -1
  142. package/templates/default/public/icons/stacks/tensorflow.svg +0 -1
  143. package/templates/default/public/icons/stacks/typescript.svg +0 -1
  144. package/templates/default/public/icons/stacks/vue.svg +0 -1
  145. package/templates/default/public/llms-full.txt +0 -83
  146. package/templates/default/public/llms.txt +0 -11
  147. package/templates/default/public/og-image.svg +0 -48
  148. package/templates/default/public/robots.txt +0 -53
  149. package/templates/default/public/sitemap.xml +0 -63
  150. package/templates/default/src/pages/404.astro +0 -64
  151. package/templates/default/src/pages/[slug]/[recordSlug].astro +0 -691
  152. package/templates/default/src/pages/[slug]/index.astro +0 -482
  153. package/templates/default/src/pages/about.astro +0 -189
  154. package/templates/default/src/pages/apps/[recordSlug].astro +0 -34
  155. package/templates/default/src/pages/contributors.astro +0 -175
  156. package/templates/default/src/pages/index.astro +0 -233
  157. package/templates/default/src/pages/sitemap.xml.ts +0 -89
  158. package/templates/default/src/pages/submit.astro +0 -281
  159. package/templates/default/src/styles/global.css +0 -33
  160. package/templates/default/tsconfig.json +0 -9
  161. package/templates/default/wrangler.jsonc +0 -28
@@ -1,103 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { readFile, stat } from "node:fs/promises";
3
- import { resolve } from "node:path";
4
-
5
- const pagesDir = resolve(import.meta.dirname, "../templates/default/src/pages");
6
-
7
- describe("default Astro route configuration", () => {
8
- it("ships TypeScript settings that resolve package exports and Node built-ins", async () => {
9
- const templateRoot = resolve(pagesDir, "../..");
10
- const tsconfig = JSON.parse(
11
- await readFile(resolve(templateRoot, "tsconfig.json"), "utf8"),
12
- ) as {
13
- extends?: string;
14
- compilerOptions?: {
15
- moduleResolution?: string;
16
- types?: string[];
17
- };
18
- };
19
- const manifest = JSON.parse(
20
- await readFile(resolve(templateRoot, "package.json"), "utf8"),
21
- ) as { devDependencies?: Record<string, string> };
22
-
23
- expect(tsconfig.extends).toBe("astro/tsconfigs/base");
24
- expect(tsconfig.compilerOptions?.moduleResolution).toBe("Bundler");
25
- expect(tsconfig.compilerOptions?.types).toContain("node");
26
- expect(manifest.devDependencies?.["@types/node"]).toMatch(/^\^/);
27
- });
28
-
29
- it("treats generated JSON as an untyped boundary before applying payload types", async () => {
30
- const recordsModule = await readFile(
31
- resolve(pagesDir, "../data/records.ts"),
32
- "utf8",
33
- );
34
-
35
- expect(recordsModule).toContain(
36
- "fullPayload as unknown as FullPayload",
37
- );
38
- });
39
-
40
- it("derives the directory route from generated site config", async () => {
41
- const listPage = await readFile(resolve(pagesDir, "[slug]/index.astro"), "utf8");
42
-
43
- expect(listPage).toContain("siteConfig.blueprintConfig?.routeSlug");
44
- });
45
-
46
- it("does not generate the legacy apps alias when apps is canonical", async () => {
47
- const aliasPage = await readFile(resolve(pagesDir, "apps/[recordSlug].astro"), "utf8");
48
-
49
- expect(aliasPage).toContain('if (indexSlug() === "apps")');
50
- expect(aliasPage).toContain("return []");
51
- });
52
-
53
- it("renders consumer-authored about Markdown through the default page", async () => {
54
- const aboutPage = await readFile(resolve(pagesDir, "about.astro"), "utf8");
55
-
56
- expect(aboutPage).toContain('getPageContentHtml("about")');
57
- });
58
-
59
- it("generates submission drafts accepted by the Grove record schema", async () => {
60
- const submitPage = await readFile(resolve(pagesDir, "submit.astro"), "utf8");
61
-
62
- expect(submitPage).toContain('" type: manual"');
63
- expect(submitPage).not.toContain('" type: github"');
64
- });
65
-
66
- it("keeps generic maintenance behavior in Grove instead of consumer scripts", async () => {
67
- const templateRoot = resolve(pagesDir, "../..");
68
- const manifest = JSON.parse(
69
- await readFile(resolve(templateRoot, "package.json"), "utf8"),
70
- ) as { scripts?: Record<string, string> };
71
- const scriptsDirExists = await stat(resolve(templateRoot, "scripts"))
72
- .then(() => true)
73
- .catch(() => false);
74
-
75
- expect(manifest.scripts?.["build:llms"]).toBe("grove llms");
76
- expect(manifest.scripts?.["sync:contributors"]).toBe(
77
- "grove sync contributors",
78
- );
79
- expect(scriptsDirExists).toBe(false);
80
- });
81
-
82
- it("hydrates static list pages with URL-driven search and pagination", async () => {
83
- const listPage = await readFile(resolve(pagesDir, "[slug]/index.astro"), "utf8");
84
-
85
- expect(listPage).toContain('id="grove-index-data"');
86
- expect(listPage).toContain("function applyClientFilters()");
87
- expect(listPage).toContain("const PAGE_SIZE = 20");
88
- });
89
-
90
- it("uses generated taxonomy names as display labels", async () => {
91
- const recordsModule = await readFile(
92
- resolve(pagesDir, "../data/records.ts"),
93
- "utf8",
94
- );
95
- const homePage = await readFile(resolve(pagesDir, "index.astro"), "utf8");
96
- const listPage = await readFile(resolve(pagesDir, "[slug]/index.astro"), "utf8");
97
-
98
- expect(recordsModule).toContain("export function taxonomyLabel");
99
- expect(recordsModule).toContain("?? prettySlug(id)");
100
- expect(homePage).toContain('taxonomyLabel("categories"');
101
- expect(listPage).toContain("labelFacetsWithTaxonomy");
102
- });
103
- });
package/src/theme.test.ts DELETED
@@ -1,76 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
3
- import { describe, expect, it } from "vitest";
4
-
5
- const astroTheme = readFileSync(resolve(import.meta.dirname, "styles.css"), "utf8");
6
- const scaffoldTheme = readFileSync(
7
- resolve(import.meta.dirname, "../templates/default/src/styles/global.css"),
8
- "utf8",
9
- );
10
- const tailwindMarkup = [
11
- "components/ItemCard.astro",
12
- "layouts/Header.astro",
13
- "../templates/default/src/pages/submit.astro",
14
- ].map((file) => readFileSync(resolve(import.meta.dirname, file), "utf8")).join("\n");
15
- const iconMarkup = readFileSync(
16
- resolve(import.meta.dirname, "components/Icon.astro"),
17
- "utf8",
18
- );
19
-
20
- describe("Astro theme contract", () => {
21
- it("keeps Starlight's light and dark foundation values", () => {
22
- expect(astroTheme).toContain("--grove-background: oklch(100% 0 0)");
23
- expect(astroTheme).toContain("--grove-foreground: var(--color-ink-950)");
24
- expect(astroTheme).toContain("--grove-background: var(--color-ink-950)");
25
- expect(astroTheme).toContain("--grove-foreground: var(--color-ink-50)");
26
- expect(astroTheme).toContain("--color-ink-50: oklch(98.5% 0 0)");
27
- expect(astroTheme).toContain("--color-ink-950: oklch(14.5% 0 0)");
28
- });
29
-
30
- it("exposes runtime semantic colors to Tailwind", () => {
31
- for (const token of [
32
- "background",
33
- "foreground",
34
- "primary",
35
- "secondary",
36
- "muted",
37
- "accent",
38
- "border",
39
- "card",
40
- "popover",
41
- ]) {
42
- expect(astroTheme).toContain(`--color-${token}: var(--grove-${token})`);
43
- }
44
- });
45
-
46
- it("uses the same system and mono font stacks as the docs", () => {
47
- expect(astroTheme).toContain(
48
- '--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,',
49
- );
50
- expect(astroTheme).toContain(
51
- "--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,",
52
- );
53
- expect(astroTheme).toContain("font-family: var(--font-sans)");
54
- });
55
-
56
- it("does not duplicate package-owned foundation tokens in the scaffold", () => {
57
- expect(scaffoldTheme).not.toContain("--color-ink-");
58
- expect(scaffoldTheme).not.toContain("font-family:");
59
- expect(scaffoldTheme).not.toContain("color-scheme:");
60
- });
61
-
62
- it("styles components in HTML with Starlight-aligned Tailwind utilities", () => {
63
- expect(tailwindMarkup).toContain("rounded-[calc(var(--radius)+0.25rem)]");
64
- expect(tailwindMarkup).toContain("rounded-full");
65
- expect(tailwindMarkup).toContain("min-h-5");
66
- expect(tailwindMarkup).toContain("h-8");
67
- expect(tailwindMarkup).toContain("focus-visible:ring-3");
68
- expect(astroTheme).not.toContain(".grove-card");
69
- expect(astroTheme).not.toContain(".grove-btn");
70
- });
71
-
72
- it("falls back to initials when a consumer has no matching icon asset", () => {
73
- expect(iconMarkup).toContain("data-grove-icon-fallback-initials");
74
- expect(iconMarkup).toContain("onerror=");
75
- });
76
- });
@@ -1,33 +0,0 @@
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):
@@ -1,20 +0,0 @@
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.
@@ -1,48 +0,0 @@
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)
@@ -1,27 +0,0 @@
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`
@@ -1,53 +0,0 @@
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
-
22
- - uses: actions/setup-node@v4
23
- with:
24
- node-version: "24"
25
- cache: pnpm
26
-
27
- - name: Install dependencies
28
- run: pnpm install --frozen-lockfile
29
-
30
- # `build` chains build:data + build:sitemap + build:llms + astro build.
31
- # Site URL is overridden so sitemap/OG/canonical links resolve to
32
- # the deployed URL rather than the placeholder in grove.config.ts.
33
- - name: Build site
34
- env:
35
- SITE_URL: ${{ vars.SITE_URL || github.pages.custom_domain || format('https://{0}.github.io/{1}', github.repository_owner, github.event.repository.name) }}
36
- run: pnpm run build
37
-
38
- - name: Setup Pages
39
- uses: actions/configure-pages@v5
40
-
41
- - name: Upload artifact
42
- uses: actions/upload-pages-artifact@v3
43
- with:
44
- path: ./dist
45
-
46
- - name: Deploy to GitHub Pages
47
- id: deployment
48
- uses: actions/deploy-pages@v4
49
-
50
- - name: Summary
51
- if: success()
52
- run: |
53
- echo "✅ Deployed to ${{ steps.deployment.outputs.page_url }}"
@@ -1,46 +0,0 @@
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
-
23
- - uses: actions/setup-node@v4
24
- with:
25
- node-version: "24"
26
- cache: pnpm
27
-
28
- - name: Install dependencies
29
- run: pnpm install --frozen-lockfile
30
-
31
- # `grove cleanup stale` lists records whose health signals say
32
- # they need human review (archived, no commits in 12+ months,
33
- # unparseable repo, etc). The report is rendered as a Markdown
34
- # summary in the workflow run.
35
- - name: Run cleanup report
36
- id: report
37
- run: pnpm exec grove cleanup stale --report > cleanup-report.md
38
-
39
- - name: Summarise
40
- run: |
41
- if [ -s cleanup-report.md ]; then
42
- echo "## Cleanup candidates" >> $GITHUB_STEP_SUMMARY
43
- cat cleanup-report.md >> $GITHUB_STEP_SUMMARY
44
- else
45
- echo "✅ No records need cleanup." >> $GITHUB_STEP_SUMMARY
46
- fi
@@ -1,51 +0,0 @@
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
-
24
- - uses: actions/setup-node@v4
25
- with:
26
- node-version: "24"
27
- cache: pnpm
28
-
29
- - name: Install dependencies
30
- run: pnpm install --frozen-lockfile
31
-
32
- - name: Refresh activity
33
- env:
34
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35
- # `grove sync github` walks every record, fetches the
36
- # latest stars/forks/pushed_at, and writes back to the
37
- # corresponding yml file. Idempotent — no change if the
38
- # record is already up to date.
39
- run: pnpm exec grove sync github
40
-
41
- - name: Open PR if records changed
42
- uses: peter-evans/create-pull-request@v6
43
- with:
44
- commit-message: "chore(data): daily records refresh"
45
- title: "Daily records refresh"
46
- body: |
47
- Automated daily refresh of stars, forks, and last-commit
48
- timestamps for every record. Generated by the
49
- `daily-refresh` workflow.
50
- branch: chore/daily-refresh
51
- delete-branch: true
@@ -1,51 +0,0 @@
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
-
21
- - uses: actions/setup-node@v4
22
- with:
23
- node-version: "24"
24
- cache: pnpm
25
-
26
- - name: Install dependencies
27
- run: pnpm install --frozen-lockfile
28
-
29
- # Walk the records' repoUrl fields, fetch each repo's
30
- # /contributors endpoint, and write a single
31
- # `data/generated/contributors.json` (consumed by the home
32
- # page and /contributors page). The script lives at the root
33
- # of the project — it's not a CLI command because contributor
34
- # fan-in is tightly coupled to this directory's git history
35
- # and doesn't generalise across forks.
36
- - name: Sync contributors from GitHub
37
- env:
38
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39
- run: pnpm exec grove sync contributors
40
-
41
- - name: Commit contributors.json
42
- run: |
43
- git config user.name "github-actions[bot]"
44
- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
45
- if git diff --quiet data/generated/contributors.json; then
46
- echo "No changes to contributors.json"
47
- else
48
- git add data/generated/contributors.json
49
- git commit -m "chore(data): refresh contributors"
50
- git push
51
- fi
@@ -1,56 +0,0 @@
1
- name: Sync GitHub metadata
2
-
3
- on:
4
- schedule:
5
- # Weekly — Sunday 03:00 UTC. Off-hours so PR validation has the
6
- # freshest metadata by Monday morning.
7
- - cron: "0 3 * * 0"
8
- workflow_dispatch:
9
- # Run on push to data/records/** so curators see fresh stars/forks
10
- # without waiting for the weekly cron.
11
- push:
12
- branches: [main]
13
- paths:
14
- - "data/records/**"
15
-
16
- jobs:
17
- sync:
18
- name: grove sync github
19
- runs-on: ubuntu-latest
20
- timeout-minutes: 20
21
- permissions:
22
- contents: write
23
- pull-requests: write
24
- steps:
25
- - uses: actions/checkout@v4
26
-
27
- - uses: pnpm/action-setup@v4
28
-
29
- - uses: actions/setup-node@v4
30
- with:
31
- node-version: "24"
32
- cache: pnpm
33
-
34
- - name: Install dependencies
35
- run: pnpm install --frozen-lockfile
36
-
37
- - name: Sync GitHub metadata
38
- env:
39
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40
- # `grove sync github` walks every record, fetches stars/forks/
41
- # activity from the GitHub API, and writes a `github` block
42
- # back into each record's YAML. Falls back to HTML scraping
43
- # when the API rate-limits.
44
- run: pnpm exec grove sync github
45
-
46
- - name: Open PR if records changed
47
- uses: peter-evans/create-pull-request@v6
48
- with:
49
- commit-message: "chore(data): sync GitHub metadata"
50
- title: "Weekly GitHub metadata sync"
51
- body: |
52
- Automated weekly sync of stars, forks, activity, and topics
53
- for every record. Generated by the `sync-github-metadata`
54
- workflow.
55
- branch: chore/sync-github-metadata
56
- delete-branch: true
@@ -1,33 +0,0 @@
1
- name: Validate data
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- pull_request:
7
- branches: [main]
8
-
9
- jobs:
10
- validate:
11
- name: grove validate
12
- runs-on: ubuntu-latest
13
- timeout-minutes: 5
14
- steps:
15
- - uses: actions/checkout@v4
16
-
17
- - uses: pnpm/action-setup@v4
18
-
19
- - uses: actions/setup-node@v4
20
- with:
21
- node-version: "24"
22
- cache: pnpm
23
-
24
- - name: Install dependencies
25
- run: pnpm install --frozen-lockfile
26
-
27
- - name: Validate records
28
- # `grove validate` checks every records/*.yml against the
29
- # blueprint schema, plus decisions.yml, taxonomy, and the
30
- # health block. --strict fails on warnings, used on the
31
- # main branch but not on PRs (where external contributors
32
- # may have minor warnings we'd rather flag than block).
33
- run: pnpm exec grove validate
@@ -1,25 +0,0 @@
1
- // @ts-check
2
- // SPDX-License-Identifier: MIT
3
- import { defineConfig } from 'astro/config';
4
- import tailwindcss from '@tailwindcss/vite';
5
- import groveAstro from '@grove-dev/astro';
6
-
7
- // `site` is the canonical URL the build uses for absolute links
8
- // (sitemap, OpenGraph, canonical tags, JSON-LD). The CLI injects
9
- // `grove.config.ts` → `site.url` at scaffold time, but it can also
10
- // be overridden per-build via the `SITE_URL` env var.
11
- //
12
- // The sitemap is generated by the CLI's `grove sitemap` command
13
- // into `public/sitemap.xml`; the public URL is exactly `/sitemap.xml`
14
- // (no `-index.xml` suffix).
15
- export default defineConfig({
16
- site: process.env.SITE_URL || 'https://example.com',
17
- trailingSlash: 'ignore',
18
- integrations: [groveAstro()],
19
- vite: {
20
- plugins: [tailwindcss()],
21
- },
22
- build: {
23
- format: 'directory',
24
- },
25
- });