@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.
- package/README.md +9 -75
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/display.d.ts +1 -26
- package/dist/lib/display.d.ts.map +1 -1
- package/dist/lib/display.js +1 -103
- package/dist/lib/display.js.map +1 -1
- package/dist/lib/format.d.ts +1 -28
- package/dist/lib/format.d.ts.map +1 -1
- package/dist/lib/format.js +1 -71
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/lenses.d.ts +1 -57
- package/dist/lib/lenses.d.ts.map +1 -1
- package/dist/lib/lenses.js +1 -198
- package/dist/lib/lenses.js.map +1 -1
- package/dist/lib/repo.d.ts +1 -19
- package/dist/lib/repo.d.ts.map +1 -1
- package/dist/lib/repo.js +1 -30
- package/dist/lib/repo.js.map +1 -1
- package/dist/lib/scores.d.ts +1 -36
- package/dist/lib/scores.d.ts.map +1 -1
- package/dist/lib/scores.js +1 -75
- package/dist/lib/scores.js.map +1 -1
- package/dist/lib/search.d.ts +1 -113
- package/dist/lib/search.d.ts.map +1 -1
- package/dist/lib/search.js +1 -379
- package/dist/lib/search.js.map +1 -1
- package/dist/lib/taxonomy-counts.d.ts +1 -10
- package/dist/lib/taxonomy-counts.d.ts.map +1 -1
- package/dist/lib/taxonomy-counts.js +1 -21
- package/dist/lib/taxonomy-counts.js.map +1 -1
- package/package.json +21 -9
- package/src/components/ContributorsGrid.astro +3 -3
- package/src/components/CurationGrid.astro +2 -2
- package/src/components/DirectoryIndexClient.astro +240 -0
- package/src/components/FilterGroupMenu.astro +8 -4
- package/src/components/FinalCta.astro +41 -0
- package/src/components/Hero.astro +15 -18
- package/src/components/Icon.astro +49 -7
- package/src/components/RefinePanel.astro +7 -7
- package/src/components/SmartLensTabs.astro +5 -4
- package/src/components/StackGrid.astro +1 -1
- package/src/components/SubmissionClient.astro +133 -0
- package/src/index.ts +11 -1
- package/src/layouts/BaseLayout.astro +19 -1
- package/src/layouts/Footer.astro +25 -56
- package/src/layouts/Header.astro +33 -15
- package/src/layouts/ThemeToggle.astro +7 -3
- package/src/lib/display.ts +1 -111
- package/src/lib/format.ts +1 -64
- package/src/lib/lenses.ts +1 -220
- package/src/lib/repo.ts +1 -32
- package/src/lib/scores.ts +1 -90
- package/src/lib/search.ts +1 -418
- package/src/lib/taxonomy-counts.ts +1 -26
- package/{templates/default/src/data/records.ts → src/server/directory.ts} +12 -8
- package/src/server/index.ts +2 -0
- package/src/server/models.ts +432 -0
- package/dist/template-routes.test.d.ts +0 -2
- package/dist/template-routes.test.d.ts.map +0 -1
- package/dist/template-routes.test.js +0 -63
- package/dist/template-routes.test.js.map +0 -1
- package/dist/theme.test.d.ts +0 -2
- package/dist/theme.test.d.ts.map +0 -1
- package/dist/theme.test.js +0 -60
- package/dist/theme.test.js.map +0 -1
- package/src/template-routes.test.ts +0 -103
- package/src/theme.test.ts +0 -76
- package/templates/default/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
- package/templates/default/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/templates/default/.github/ISSUE_TEMPLATE/record_submission.md +0 -48
- package/templates/default/.github/pull_request_template.md +0 -27
- package/templates/default/.github/workflows/build.yml +0 -53
- package/templates/default/.github/workflows/cleanup-stale-records.yml +0 -46
- package/templates/default/.github/workflows/daily-refresh.yml +0 -51
- package/templates/default/.github/workflows/sync-contributors.yml +0 -51
- package/templates/default/.github/workflows/sync-github-metadata.yml +0 -56
- package/templates/default/.github/workflows/validate-data.yml +0 -33
- package/templates/default/astro.config.mjs +0 -25
- package/templates/default/content/pages/about.md +0 -66
- package/templates/default/content/pages/methodology.md +0 -103
- package/templates/default/data/records/.gitkeep +0 -0
- package/templates/default/data/records/coolify.yml +0 -46
- package/templates/default/data/records/gitea.yml +0 -46
- package/templates/default/data/records/hoppscotch.yml +0 -47
- package/templates/default/data/records/inventree.yml +0 -47
- package/templates/default/data/records/label-studio.yml +0 -46
- package/templates/default/data/records/logseq.yml +0 -48
- package/templates/default/data/records/private-gpt.yml +0 -47
- package/templates/default/data/records/wakapi.yml +0 -44
- package/templates/default/data/taxonomy/categories.yml +0 -47
- package/templates/default/data/taxonomy/distribution-channels.yml +0 -43
- package/templates/default/data/taxonomy/platforms.yml +0 -27
- package/templates/default/data/taxonomy/stacks.yml +0 -41
- package/templates/default/grove.config.ts +0 -36
- package/templates/default/package.json +0 -43
- package/templates/default/public/icons/platforms/android.svg +0 -1
- package/templates/default/public/icons/platforms/apple-dark.svg +0 -1
- package/templates/default/public/icons/platforms/apple-light.svg +0 -1
- package/templates/default/public/icons/platforms/chrome.svg +0 -1
- package/templates/default/public/icons/platforms/chromeos.svg +0 -5
- package/templates/default/public/icons/platforms/desktop.svg +0 -4
- package/templates/default/public/icons/platforms/embedded.svg +0 -5
- package/templates/default/public/icons/platforms/ios.svg +0 -1
- package/templates/default/public/icons/platforms/linux.svg +0 -1
- package/templates/default/public/icons/platforms/macos.svg +0 -1
- package/templates/default/public/icons/platforms/ubuntu.svg +0 -1
- package/templates/default/public/icons/platforms/web.svg +0 -5
- package/templates/default/public/icons/platforms/windows.svg +0 -6
- package/templates/default/public/icons/stacks/android.svg +0 -1
- package/templates/default/public/icons/stacks/apple-dark.svg +0 -1
- package/templates/default/public/icons/stacks/apple-light.svg +0 -1
- package/templates/default/public/icons/stacks/bun.svg +0 -1
- package/templates/default/public/icons/stacks/capacitor.svg +0 -14
- package/templates/default/public/icons/stacks/clojure.svg +0 -1
- package/templates/default/public/icons/stacks/clojurescript.svg +0 -1
- package/templates/default/public/icons/stacks/dart.svg +0 -1
- package/templates/default/public/icons/stacks/deno.svg +0 -1
- package/templates/default/public/icons/stacks/django.svg +0 -1
- package/templates/default/public/icons/stacks/docker.svg +0 -1
- package/templates/default/public/icons/stacks/firebase.svg +0 -1
- package/templates/default/public/icons/stacks/flutter.svg +0 -1
- package/templates/default/public/icons/stacks/go.svg +0 -1
- package/templates/default/public/icons/stacks/graphql.svg +0 -1
- package/templates/default/public/icons/stacks/ionic.svg +0 -4
- package/templates/default/public/icons/stacks/java.svg +0 -1
- package/templates/default/public/icons/stacks/javascript.svg +0 -1
- package/templates/default/public/icons/stacks/kotlin.svg +0 -1
- package/templates/default/public/icons/stacks/llm.svg +0 -1
- package/templates/default/public/icons/stacks/mongodb.svg +0 -1
- package/templates/default/public/icons/stacks/node.js.svg +0 -1
- package/templates/default/public/icons/stacks/nodejs.svg +0 -1
- package/templates/default/public/icons/stacks/python.svg +0 -1
- package/templates/default/public/icons/stacks/rag.svg +0 -7
- package/templates/default/public/icons/stacks/react-native.svg +0 -1
- package/templates/default/public/icons/stacks/react.svg +0 -1
- package/templates/default/public/icons/stacks/rust.svg +0 -1
- package/templates/default/public/icons/stacks/solidity.svg +0 -1
- package/templates/default/public/icons/stacks/sveltekit.svg +0 -1
- package/templates/default/public/icons/stacks/swift.svg +0 -1
- package/templates/default/public/icons/stacks/tensorflow.svg +0 -1
- package/templates/default/public/icons/stacks/typescript.svg +0 -1
- package/templates/default/public/icons/stacks/vue.svg +0 -1
- package/templates/default/public/llms-full.txt +0 -83
- package/templates/default/public/llms.txt +0 -11
- package/templates/default/public/og-image.svg +0 -48
- package/templates/default/public/robots.txt +0 -53
- package/templates/default/public/sitemap.xml +0 -63
- package/templates/default/src/pages/404.astro +0 -64
- package/templates/default/src/pages/[slug]/[recordSlug].astro +0 -691
- package/templates/default/src/pages/[slug]/index.astro +0 -482
- package/templates/default/src/pages/about.astro +0 -189
- package/templates/default/src/pages/apps/[recordSlug].astro +0 -34
- package/templates/default/src/pages/contributors.astro +0 -175
- package/templates/default/src/pages/index.astro +0 -233
- package/templates/default/src/pages/sitemap.xml.ts +0 -89
- package/templates/default/src/pages/submit.astro +0 -281
- package/templates/default/src/styles/global.css +0 -33
- package/templates/default/tsconfig.json +0 -9
- 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
|
-
});
|