@grove-dev/astro 0.1.5 → 0.2.5
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/LICENSE +21 -0
- package/dist/index.d.ts +4 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -22
- package/dist/index.js.map +1 -1
- package/dist/layouts/index.d.ts +25 -0
- package/dist/layouts/index.d.ts.map +1 -0
- package/dist/layouts/index.js +25 -0
- package/dist/layouts/index.js.map +1 -0
- package/dist/lib/display.d.ts +33 -0
- package/dist/lib/display.d.ts.map +1 -0
- package/dist/lib/display.js +104 -0
- package/dist/lib/display.js.map +1 -0
- package/dist/lib/format.d.ts +30 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +73 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/index.d.ts +26 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +26 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/lenses.d.ts +96 -0
- package/dist/lib/lenses.d.ts.map +1 -0
- package/dist/lib/lenses.js +181 -0
- package/dist/lib/lenses.js.map +1 -0
- package/dist/lib/repo.d.ts +30 -0
- package/dist/lib/repo.d.ts.map +1 -0
- package/dist/lib/repo.js +44 -0
- package/dist/lib/repo.js.map +1 -0
- package/dist/lib/scores.d.ts +38 -0
- package/dist/lib/scores.d.ts.map +1 -0
- package/dist/lib/scores.js +83 -0
- package/dist/lib/scores.js.map +1 -0
- package/dist/lib/search.d.ts +199 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +357 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/taxonomy-counts.d.ts +25 -0
- package/dist/lib/taxonomy-counts.d.ts.map +1 -0
- package/dist/lib/taxonomy-counts.js +41 -0
- package/dist/lib/taxonomy-counts.js.map +1 -0
- package/package.json +7 -7
- package/src/components/AppsIndexRow.astro +204 -0
- package/src/components/AppsPagination.astro +126 -0
- package/src/components/CategoryGrid.astro +86 -17
- package/src/components/ContributorsGrid.astro +149 -0
- package/src/components/DecisionRow.astro +89 -0
- package/src/components/ExploreByCategory.astro +67 -0
- package/src/components/ExploreByStack.astro +72 -0
- package/src/components/Hero.astro +246 -0
- package/src/components/Icon.astro +223 -0
- package/src/components/ItemCard.astro +306 -30
- package/src/components/MinimalAbout.astro +82 -0
- package/src/components/OriginalCollection.astro +116 -0
- package/src/components/RecordSection.astro +88 -0
- package/src/components/RefinePanel.astro +197 -0
- package/src/components/ScoreBars.astro +92 -22
- package/src/components/SmartLensTabs.astro +71 -0
- package/src/components/StackGrid.astro +132 -0
- package/src/components/WhyThisExists.astro +116 -0
- package/src/index.ts +61 -14
- package/src/layouts/BaseLayout.astro +227 -15
- package/src/layouts/Container.astro +57 -0
- package/src/layouts/Footer.astro +235 -0
- package/src/layouts/Header.astro +159 -0
- package/src/layouts/SectionHeader.astro +58 -0
- package/{templates/default/src/components/layout → src/layouts}/Seo.astro +62 -38
- package/src/layouts/ThemeToggle.astro +110 -0
- package/src/layouts/astro-shim.d.ts +29 -0
- package/src/layouts/index.ts +24 -0
- package/src/lib/display.ts +118 -0
- package/src/lib/format.ts +65 -0
- package/src/lib/index.ts +26 -0
- package/src/lib/lenses.ts +241 -0
- package/src/lib/repo.ts +44 -0
- package/src/lib/scores.ts +94 -0
- package/src/lib/search.ts +481 -0
- package/src/lib/taxonomy-counts.ts +60 -0
- package/src/styles.css +366 -638
- package/templates/default/astro.config.mjs +8 -6
- package/templates/default/content/pages/about.md +66 -0
- package/templates/default/content/pages/methodology.md +103 -0
- package/templates/default/data/generated/records.full.json +8 -0
- package/templates/default/data/generated/records.index.json +7 -0
- package/templates/default/data/generated/records.json +8 -0
- package/templates/default/data/generated/site-config.json +31 -0
- package/templates/default/data/records/.gitkeep +0 -0
- package/templates/default/grove.config.ts +36 -0
- package/templates/default/package.json +6 -5
- package/templates/default/public/llms-full.txt +14 -0
- package/templates/default/public/llms.txt +11 -0
- package/templates/default/src/components/layout/BaseLayout.astro +10 -57
- package/templates/default/src/components/layout/Footer.astro +16 -134
- package/templates/default/src/components/layout/Header.astro +25 -126
- package/templates/default/src/data/records.ts +193 -0
- package/templates/default/src/lib/markdown.ts +171 -0
- package/templates/default/src/pages/about.astro +95 -429
- package/templates/default/src/pages/index.astro +263 -61
- package/templates/default/src/pages/projects/[slug].astro +480 -0
- package/templates/default/src/pages/projects/index.astro +193 -0
- package/templates/default/src/pages/sitemap.xml.ts +73 -61
- package/templates/default/src/pages/submit.astro +122 -411
- package/templates/default/src/styles/global.css +42 -68
- package/src/components/ActiveFilterChips.astro +0 -20
- package/src/components/DirectoryFilters.astro +0 -100
- package/src/components/DirectoryHero.astro +0 -32
- package/src/components/HealthBadge.astro +0 -12
- package/src/components/LensTabs.astro +0 -26
- package/src/components/MethodologyPanel.astro +0 -20
- package/src/components/Pagination.astro +0 -24
- package/src/components/ProjectDetail.astro +0 -166
- package/src/components/SubmitDraft.astro +0 -137
- package/templates/default/src/components/AppCard.astro +0 -248
- package/templates/default/src/components/AppSection.astro +0 -58
- package/templates/default/src/components/AppsIndexRow.astro +0 -230
- package/templates/default/src/components/AppsPagination.astro +0 -147
- package/templates/default/src/components/CategoryGrid.astro +0 -80
- package/templates/default/src/components/ContributorsGrid.astro +0 -105
- package/templates/default/src/components/DecisionRow.astro +0 -219
- package/templates/default/src/components/ExploreByCategory.astro +0 -74
- package/templates/default/src/components/ExploreByStack.astro +0 -102
- package/templates/default/src/components/Hero.astro +0 -176
- package/templates/default/src/components/MinimalAbout.astro +0 -57
- package/templates/default/src/components/OriginalCollection.astro +0 -144
- package/templates/default/src/components/RefinePanel.astro +0 -272
- package/templates/default/src/components/ScoreBars.astro +0 -72
- package/templates/default/src/components/SmartLensTabs.astro +0 -65
- package/templates/default/src/components/StackGrid.astro +0 -95
- package/templates/default/src/components/WhyThisExists.astro +0 -81
- package/templates/default/src/components/icons/Icon.astro +0 -148
- package/templates/default/src/components/layout/SectionHeader.astro +0 -42
- package/templates/default/src/components/layout/ThemeToggle.astro +0 -97
- package/templates/default/src/data/apps.ts +0 -149
- package/templates/default/src/data/categories.ts +0 -27
- package/templates/default/src/data/config.ts +0 -28
- package/templates/default/src/data/contributors.ts +0 -96
- package/templates/default/src/data/stacks.ts +0 -47
- package/templates/default/src/data/stats.ts +0 -65
- package/templates/default/src/data/types.ts +0 -248
- package/templates/default/src/lib/apps-search.ts +0 -228
- package/templates/default/src/lib/format.ts +0 -36
- package/templates/default/src/lib/lenses.ts +0 -98
- package/templates/default/src/lib/repo.ts +0 -12
- package/templates/default/src/lib/scores.ts +0 -51
- package/templates/default/src/lib/taxonomy-counts.ts +0 -31
- package/templates/default/src/pages/apps/[slug].astro +0 -709
- package/templates/default/src/pages/apps/index.astro +0 -669
- package/templates/default/src/pages/contributors.astro +0 -142
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
import { defineConfig } from 'astro/config';
|
|
4
4
|
import tailwindcss from '@tailwindcss/vite';
|
|
5
|
+
import groveAstro from '@grove-dev/astro';
|
|
5
6
|
|
|
6
7
|
// `site` is the canonical URL the build uses for absolute links
|
|
7
|
-
// (sitemap, OpenGraph, canonical tags, JSON-LD).
|
|
8
|
-
//
|
|
9
|
-
//
|
|
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.
|
|
10
11
|
//
|
|
11
|
-
// The sitemap
|
|
12
|
-
// `
|
|
13
|
-
//
|
|
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).
|
|
14
15
|
export default defineConfig({
|
|
15
16
|
site: process.env.SITE_URL || 'https://example.com',
|
|
16
17
|
trailingSlash: 'ignore',
|
|
18
|
+
integrations: [groveAstro()],
|
|
17
19
|
vite: {
|
|
18
20
|
plugins: [tailwindcss()],
|
|
19
21
|
},
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "About"
|
|
3
|
+
description: "What this directory is, who it's for, and how it works."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# About this directory
|
|
7
|
+
|
|
8
|
+
This site is a small, hand-curated index of useful open-source work
|
|
9
|
+
relevant to a specific community. The framing is deliberately
|
|
10
|
+
narrow: we list *one* project per record, with a hand-written
|
|
11
|
+
"why listed" note for each, and we surface the things that matter
|
|
12
|
+
in practice (recent activity, install friction, license, etc.)
|
|
13
|
+
rather than the things that look impressive on a GitHub profile.
|
|
14
|
+
|
|
15
|
+
## How it works
|
|
16
|
+
|
|
17
|
+
Records live as YAML files in `data/records/`. Each record carries:
|
|
18
|
+
|
|
19
|
+
- A `kind` (`project`, `resource`, or `entity` — picked by the
|
|
20
|
+
blueprint in `grove.config.ts`).
|
|
21
|
+
- A `slug` (URL-safe identifier; becomes the path on
|
|
22
|
+
`/<kind>/<slug>`).
|
|
23
|
+
- A `name` and a one-line `description`.
|
|
24
|
+
- Cross-links (`links.github`, `links.website`, etc.) and free-form
|
|
25
|
+
tags.
|
|
26
|
+
- An optional `curation` block with `labels`, `reviewedAt`,
|
|
27
|
+
`bestFor`, `whyListed`, `caveats`, and `scores`.
|
|
28
|
+
- An optional `github` block with the live repository signals
|
|
29
|
+
(stars, forks, latest release, languages, pushed-at).
|
|
30
|
+
|
|
31
|
+
At build time:
|
|
32
|
+
|
|
33
|
+
1. `grove validate` checks every record against the JSON schema.
|
|
34
|
+
2. `grove generate` writes `data/generated/records.{full,index}.json`
|
|
35
|
+
and `data/generated/site-config.json`.
|
|
36
|
+
3. `grove sitemap` writes `public/sitemap.xml`.
|
|
37
|
+
4. `grove llms` writes `public/llms.txt` and `llms-full.txt`.
|
|
38
|
+
5. `astro build` produces the static output.
|
|
39
|
+
|
|
40
|
+
The whole pipeline is reproducible. The records are the source of
|
|
41
|
+
truth; everything else is derived.
|
|
42
|
+
|
|
43
|
+
## Why a static site
|
|
44
|
+
|
|
45
|
+
The directory is a *reference*, not an *app*. Static HTML is the
|
|
46
|
+
right tool:
|
|
47
|
+
|
|
48
|
+
- Every page is a single round-trip. No client-side data layer.
|
|
49
|
+
- The output is auditable: open the deployed HTML and you can see
|
|
50
|
+
the full markup, no hidden hydration.
|
|
51
|
+
- Hosting is cheap (or free, on GitHub Pages / Cloudflare Pages).
|
|
52
|
+
- AI crawlers can read the full content. The `llms.txt` /
|
|
53
|
+
`llms-full.txt` files give them a single fetch to land on.
|
|
54
|
+
|
|
55
|
+
## Contributing
|
|
56
|
+
|
|
57
|
+
To add a record, open a submission issue. The maintainer will
|
|
58
|
+
review and, if accepted, open a PR that adds the new YAML file.
|
|
59
|
+
See `/submit` for the issue form and a minimal record template.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
The site's source code is MIT. The records are released under CC-BY
|
|
64
|
+
4.0 unless a record's `license` field says otherwise. A record's
|
|
65
|
+
`license` field is the license of the *project it describes*, not
|
|
66
|
+
the license of the directory entry.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Methodology"
|
|
3
|
+
description: "How records are picked, scored, and surfaced in this directory."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Methodology
|
|
7
|
+
|
|
8
|
+
This page describes how entries in the directory are chosen, how the
|
|
9
|
+
curation signals are computed, and what we do (and don't) promise about
|
|
10
|
+
the data. The intent is to make the directory's logic auditable — every
|
|
11
|
+
number on a detail page is reproducible from the record's YAML.
|
|
12
|
+
|
|
13
|
+
## Selection
|
|
14
|
+
|
|
15
|
+
A record is included if it is:
|
|
16
|
+
|
|
17
|
+
1. **Open source.** Source is public under an OSI-approved license
|
|
18
|
+
(or public-domain dedication).
|
|
19
|
+
2. **Actively maintained.** A pushed commit within the last 18 months
|
|
20
|
+
OR a declared maintenance status of `maintained` / `passive`.
|
|
21
|
+
3. **Useful to a curious developer.** A working build, a real user
|
|
22
|
+
base (or a credible path to one), and a clear description of what
|
|
23
|
+
the project does.
|
|
24
|
+
|
|
25
|
+
We exclude: abandoned experiments, vapourware, projects whose entire
|
|
26
|
+
purpose is to sell a hosted plan, and any record that has not been
|
|
27
|
+
hand-checked by a maintainer.
|
|
28
|
+
|
|
29
|
+
## Curation labels
|
|
30
|
+
|
|
31
|
+
The `curation.labels` field is a small, hand-set list. The supported
|
|
32
|
+
labels are:
|
|
33
|
+
|
|
34
|
+
- `hot` — high recent activity or attention (≥ 1 000 stars or a
|
|
35
|
+
commit within the last 30 days).
|
|
36
|
+
- `new` — added to the directory in the last 7 days.
|
|
37
|
+
- `mature` — long-running curated project, pushed > 365 days ago,
|
|
38
|
+
but still maintained.
|
|
39
|
+
- `featured` — editor's pick for the front page.
|
|
40
|
+
- `needs-review` — open submission awaiting a second maintainer
|
|
41
|
+
look.
|
|
42
|
+
|
|
43
|
+
These labels are mutually additive, not exclusive. A `new` record
|
|
44
|
+
can also be `hot`; a `mature` record can also be `featured`.
|
|
45
|
+
|
|
46
|
+
## Scoring
|
|
47
|
+
|
|
48
|
+
The detail page surfaces a five-dimension score block. The five
|
|
49
|
+
dimensions are:
|
|
50
|
+
|
|
51
|
+
- **Documentation** — is the README / docs site enough to onboard
|
|
52
|
+
without reading the source?
|
|
53
|
+
- **Onboarding** — install in < 5 min, first useful result in < 1 h.
|
|
54
|
+
- **Maintenance** — recent commits, issue close rate, release cadence.
|
|
55
|
+
- **Community** — issues answered, discussions active, contributors
|
|
56
|
+
per release.
|
|
57
|
+
- **Production-readiness** — CI, tests, security policy, releases
|
|
58
|
+
with semver.
|
|
59
|
+
|
|
60
|
+
Each dimension is scored 0-5. The overall score on the detail page
|
|
61
|
+
is the mean. Scores are stored on the record, not computed at build
|
|
62
|
+
time, so we can deliberately disagree with the raw signals (a 1-line
|
|
63
|
+
toy that happens to be wildly popular can still score low on
|
|
64
|
+
documentation).
|
|
65
|
+
|
|
66
|
+
## Health signals
|
|
67
|
+
|
|
68
|
+
The `health` block on each record tracks four state machines:
|
|
69
|
+
|
|
70
|
+
- `status` — `healthy` / `slowing` / `stale` / `archived`.
|
|
71
|
+
- `tier` — `curated` / `community` / `experimental`.
|
|
72
|
+
- `issue_close_rate` — moving 90-day average.
|
|
73
|
+
- `last_release` — most recent semver tag.
|
|
74
|
+
|
|
75
|
+
A record's `status` transitions are time-boxed: a project with no
|
|
76
|
+
commits in 365 days flips from `slowing` to `stale`; 730 days flips
|
|
77
|
+
to `archived`. The transition is mechanical; the recovery is
|
|
78
|
+
manual (a maintainer sets `tier` back to `community` after review).
|
|
79
|
+
|
|
80
|
+
## Lenses
|
|
81
|
+
|
|
82
|
+
The directory's home page surfaces three curated lenses:
|
|
83
|
+
|
|
84
|
+
- **Hot** — `curation.labels` includes `hot`, OR `github.stars` ≥
|
|
85
|
+
1 000, OR `pushedAt` within 30 days.
|
|
86
|
+
- **New** — `pushedAt` within 7 days, OR `curation.labels` includes
|
|
87
|
+
`new`.
|
|
88
|
+
- **Mature** — `health.tier === "curated"` AND `pushedAt` > 365 days
|
|
89
|
+
ago.
|
|
90
|
+
|
|
91
|
+
Each lens caps at 6 items on the home page; the full filtered list
|
|
92
|
+
is reachable via the lens tab on `/projects`.
|
|
93
|
+
|
|
94
|
+
## What we don't promise
|
|
95
|
+
|
|
96
|
+
- **Real-time data.** The site is rebuilt on a schedule, not on
|
|
97
|
+
every push. Counts and dates can lag by up to one build cycle.
|
|
98
|
+
- **Verdict-free scores.** A high overall score means "useful to a
|
|
99
|
+
curious developer", not "best in class" — judgement calls are
|
|
100
|
+
documented per record, not baked into the score.
|
|
101
|
+
- **Causal claims.** The "best for" / "why listed" / "caveats"
|
|
102
|
+
blocks are editorial notes, not derived signals. They reflect
|
|
103
|
+
what a maintainer thought at review time.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"blueprint": "project-directory",
|
|
3
|
+
"name": "Grove Directory",
|
|
4
|
+
"tagline": "A curated, health-aware developer directory.",
|
|
5
|
+
"description": "A curated, health-aware developer directory powered by Grove.",
|
|
6
|
+
"siteUrl": "https://example.com",
|
|
7
|
+
"repoUrl": "https://github.com/tortuvshin/grove",
|
|
8
|
+
"nav": [
|
|
9
|
+
{
|
|
10
|
+
"label": "Home",
|
|
11
|
+
"href": "/"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"label": "Browse",
|
|
15
|
+
"href": "/projects"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"label": "About",
|
|
19
|
+
"href": "/about"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"theme": {
|
|
23
|
+
"primaryColor": "#16a34a",
|
|
24
|
+
"radius": "soft",
|
|
25
|
+
"density": "comfortable",
|
|
26
|
+
"containerWidth": "72rem"
|
|
27
|
+
},
|
|
28
|
+
"integrations": {
|
|
29
|
+
"github": false
|
|
30
|
+
}
|
|
31
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineConfig } from "@grove-dev/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default template config — the smallest viable project-directory
|
|
5
|
+
* showcase. Consumers (created via `grove new`) override this
|
|
6
|
+
* with their own branding, taxonomy, and integrations.
|
|
7
|
+
*/
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
blueprint: "project-directory",
|
|
10
|
+
|
|
11
|
+
site: {
|
|
12
|
+
name: "Grove Directory",
|
|
13
|
+
tagline: "A curated, health-aware developer directory.",
|
|
14
|
+
description:
|
|
15
|
+
"A curated, health-aware developer directory powered by Grove.",
|
|
16
|
+
url: "https://example.com",
|
|
17
|
+
repoUrl: "https://github.com/tortuvshin/grove",
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
nav: [
|
|
21
|
+
{ label: "Home", href: "/" },
|
|
22
|
+
{ label: "Browse", href: "/projects" },
|
|
23
|
+
{ label: "About", href: "/about" },
|
|
24
|
+
],
|
|
25
|
+
|
|
26
|
+
facets: ["category", "stacks", "platforms", "tags"],
|
|
27
|
+
|
|
28
|
+
integrations: {},
|
|
29
|
+
|
|
30
|
+
theme: {
|
|
31
|
+
primaryColor: "#16a34a",
|
|
32
|
+
radius: "soft",
|
|
33
|
+
density: "comfortable",
|
|
34
|
+
containerWidth: "72rem",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -11,16 +11,17 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"validate:data": "grove validate",
|
|
14
|
-
"build:data": "grove
|
|
15
|
-
"build:
|
|
16
|
-
"build": "
|
|
14
|
+
"build:data": "grove generate",
|
|
15
|
+
"build:sitemap": "grove sitemap",
|
|
16
|
+
"build:llms": "grove llms",
|
|
17
|
+
"build": "pnpm run build:data && pnpm run build:sitemap && pnpm run build:llms && astro build",
|
|
17
18
|
"dev": "pnpm run build:data && astro dev",
|
|
18
19
|
"start": "astro dev",
|
|
19
20
|
"preview": "astro preview",
|
|
20
21
|
"astro": "astro",
|
|
21
22
|
"check": "astro check",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
23
|
+
"sync:github": "grove sync github",
|
|
24
|
+
"cleanup": "grove cleanup stale"
|
|
24
25
|
},
|
|
25
26
|
"dependencies": {
|
|
26
27
|
"@astrojs/check": "^0.9.9",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Grove Directory — full directory
|
|
2
|
+
|
|
3
|
+
> Generated 2026-06-10T15:03:23.841Z from 0 records.
|
|
4
|
+
> Source: https://example.com/projects · Regenerate with `grove generate`.
|
|
5
|
+
|
|
6
|
+
Each section below mirrors one record detail page.
|
|
7
|
+
|
|
8
|
+
## Index
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Grove Directory
|
|
2
|
+
|
|
3
|
+
A curated, health-aware developer directory powered by Grove.
|
|
4
|
+
|
|
5
|
+
Directory: https://example.com/projects
|
|
6
|
+
Records indexed: 0
|
|
7
|
+
Categories: 0
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
Use /llms-full.txt for record-level details. Prefer detail pages for citations.
|
|
@@ -1,32 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
// SPDX-License-Identifier: MIT
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* BaseLayout — wraps every page. Owns the theme-detection inline script
|
|
6
|
-
* and the global shell (Header, Footer). Per-page SEO (title, description,
|
|
7
|
-
* OG, JSON-LD) is delegated to <Seo /> so each page can declare what it
|
|
8
|
-
* needs without polluting the layout file.
|
|
9
|
-
*/
|
|
10
2
|
import "../../styles/global.css";
|
|
11
3
|
import Header from "./Header.astro";
|
|
12
4
|
import Footer from "./Footer.astro";
|
|
13
|
-
import Seo from "./Seo.astro";
|
|
14
5
|
|
|
15
6
|
interface Props {
|
|
16
7
|
title: string;
|
|
17
8
|
description: string;
|
|
18
|
-
type?: "website" | "article" | "profile";
|
|
19
9
|
noindex?: boolean;
|
|
20
10
|
jsonLd?: Record<string, unknown> | Record<string, unknown>[];
|
|
21
11
|
}
|
|
22
12
|
|
|
23
|
-
const {
|
|
24
|
-
title,
|
|
25
|
-
description,
|
|
26
|
-
type,
|
|
27
|
-
noindex,
|
|
28
|
-
jsonLd,
|
|
29
|
-
} = Astro.props;
|
|
13
|
+
const { title, description, noindex, jsonLd } = Astro.props;
|
|
30
14
|
|
|
31
15
|
const favicon =
|
|
32
16
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%2318181b'/%3E%3C/svg%3E";
|
|
@@ -38,57 +22,26 @@ const favicon =
|
|
|
38
22
|
<meta charset="UTF-8" />
|
|
39
23
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
40
24
|
<meta name="generator" content={Astro.generator} />
|
|
25
|
+
<meta name="description" content={description} />
|
|
41
26
|
<meta name="theme-color" content="#0a0a0c" media="(prefers-color-scheme: dark)" />
|
|
42
27
|
<meta name="theme-color" content="#fafafa" media="(prefers-color-scheme: light)" />
|
|
43
28
|
<link rel="icon" href={favicon} />
|
|
44
29
|
<link rel="sitemap" href="/sitemap.xml" />
|
|
45
30
|
<link rel="alternate" type="text/plain" href="/llms.txt" title="LLM usage guidance" />
|
|
46
|
-
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<slot name="head" />
|
|
56
|
-
<script is:inline>
|
|
57
|
-
(function () {
|
|
58
|
-
var STORAGE_KEY = "open-apps-theme";
|
|
59
|
-
function getMode() {
|
|
60
|
-
var stored = localStorage.getItem(STORAGE_KEY);
|
|
61
|
-
if (stored === "light" || stored === "dark" || stored === "system") return stored;
|
|
62
|
-
return "system";
|
|
63
|
-
}
|
|
64
|
-
function apply(mode) {
|
|
65
|
-
var resolved =
|
|
66
|
-
mode === "system"
|
|
67
|
-
? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light")
|
|
68
|
-
: mode;
|
|
69
|
-
var root = document.documentElement;
|
|
70
|
-
if (resolved === "dark") root.classList.add("dark");
|
|
71
|
-
else root.classList.remove("dark");
|
|
72
|
-
root.dataset.theme = mode;
|
|
73
|
-
root.dataset.resolvedTheme = resolved;
|
|
74
|
-
}
|
|
75
|
-
apply(getMode());
|
|
76
|
-
window.addEventListener("theme:set", function (e) { apply(e.detail); });
|
|
77
|
-
var mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
78
|
-
mq.addEventListener("change", function () {
|
|
79
|
-
if (getMode() === "system") apply("system");
|
|
80
|
-
});
|
|
81
|
-
})();
|
|
82
|
-
</script>
|
|
31
|
+
{noindex && <meta name="robots" content="noindex,nofollow" />}
|
|
32
|
+
<title>{title}</title>
|
|
33
|
+
{jsonLd && (
|
|
34
|
+
<script
|
|
35
|
+
type="application/ld+json"
|
|
36
|
+
set:html={JSON.stringify(jsonLd)}
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
83
39
|
</head>
|
|
84
40
|
<body class="min-h-screen bg-white text-ink-900 dark:bg-ink-950 dark:text-ink-100">
|
|
85
41
|
<Header />
|
|
86
|
-
|
|
87
42
|
<main>
|
|
88
43
|
<slot />
|
|
89
44
|
</main>
|
|
90
|
-
|
|
91
45
|
<Footer />
|
|
92
|
-
<slot name="body-end" />
|
|
93
46
|
</body>
|
|
94
47
|
</html>
|
|
@@ -1,145 +1,27 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
3
|
-
import { stats } from "../../data/stats";
|
|
2
|
+
import siteConfig from "../../data/generated/site-config.json";
|
|
4
3
|
|
|
5
|
-
const githubUrl = stats.originalRepo;
|
|
6
4
|
const year = new Date().getFullYear();
|
|
7
|
-
|
|
8
|
-
// One-line positioning. Should be the same on every page so the
|
|
9
|
-
// project's identity is consistent.
|
|
10
|
-
const positioning =
|
|
11
|
-
"A searchable directory of real open-source applications — organized by stack, category, platform, license, activity, and maturity.";
|
|
12
5
|
---
|
|
13
6
|
|
|
14
7
|
<footer class="mt-16 border-t border-ink-200 bg-white text-ink-500 dark:border-ink-800 dark:bg-ink-950 dark:text-ink-400">
|
|
15
|
-
<div
|
|
16
|
-
class="
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<div
|
|
20
|
-
class="mb-2 inline-flex items-center gap-2 text-[0.95rem] font-semibold text-ink-900 dark:text-ink-100"
|
|
21
|
-
>
|
|
22
|
-
<span
|
|
23
|
-
aria-hidden="true"
|
|
24
|
-
class="inline-block h-3.5 w-3.5 rounded bg-ink-900 dark:bg-ink-100"
|
|
25
|
-
></span>
|
|
26
|
-
<span>{siteConfig.name}</span>
|
|
27
|
-
</div>
|
|
28
|
-
<p class="m-0 max-w-[36ch] text-[0.8125rem] leading-relaxed text-ink-500 dark:text-ink-400">
|
|
29
|
-
{positioning}
|
|
8
|
+
<div class="mx-auto max-w-6xl px-5 py-8 sm:px-7">
|
|
9
|
+
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
|
10
|
+
<p class="m-0 text-sm">
|
|
11
|
+
© {year} {siteConfig.name}.
|
|
30
12
|
</p>
|
|
31
|
-
<p class="
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
13
|
+
<p class="m-0 text-2xs text-ink-500 dark:text-ink-400">
|
|
14
|
+
Built with{" "}
|
|
15
|
+
<a
|
|
16
|
+
href="https://github.com/tortuvshin/grove"
|
|
17
|
+
target="_blank"
|
|
18
|
+
rel="noopener noreferrer"
|
|
19
|
+
class="hover:text-ink-900 dark:hover:text-ink-100"
|
|
20
|
+
>
|
|
21
|
+
Grove
|
|
22
|
+
</a>
|
|
23
|
+
{" "}— an open-source framework for community knowledge sites.
|
|
37
24
|
</p>
|
|
38
25
|
</div>
|
|
39
|
-
|
|
40
|
-
<div>
|
|
41
|
-
<h4
|
|
42
|
-
class="mb-3 text-2xs font-semibold uppercase tracking-wider text-ink-900 dark:text-ink-100"
|
|
43
|
-
>
|
|
44
|
-
Discover
|
|
45
|
-
</h4>
|
|
46
|
-
<ul class="m-0 flex list-none flex-col gap-2 p-0">
|
|
47
|
-
<li><a href="#hot" class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100">Hot apps</a></li>
|
|
48
|
-
<li><a href="#new" class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100">New apps</a></li>
|
|
49
|
-
<li><a href="#mature" class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100">Mature apps</a></li>
|
|
50
|
-
<li><a href="#stacks" class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100">By stack</a></li>
|
|
51
|
-
<li><a href="#categories" class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100">By category</a></li>
|
|
52
|
-
</ul>
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
<div>
|
|
56
|
-
<h4
|
|
57
|
-
class="mb-3 text-2xs font-semibold uppercase tracking-wider text-ink-900 dark:text-ink-100"
|
|
58
|
-
>
|
|
59
|
-
Contribute
|
|
60
|
-
</h4>
|
|
61
|
-
<ul class="m-0 flex list-none flex-col gap-2 p-0">
|
|
62
|
-
<li>
|
|
63
|
-
<a
|
|
64
|
-
href={`${githubUrl}/blob/main/CONTRIBUTING.md`}
|
|
65
|
-
target="_blank"
|
|
66
|
-
rel="noopener noreferrer"
|
|
67
|
-
class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100"
|
|
68
|
-
>Submit via GitHub</a
|
|
69
|
-
>
|
|
70
|
-
</li>
|
|
71
|
-
<li><a href="#contributors" class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100">Contributors</a></li>
|
|
72
|
-
<li>
|
|
73
|
-
<a
|
|
74
|
-
href={`${githubUrl}/issues`}
|
|
75
|
-
target="_blank"
|
|
76
|
-
rel="noopener noreferrer"
|
|
77
|
-
class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100"
|
|
78
|
-
>Report an issue</a
|
|
79
|
-
>
|
|
80
|
-
</li>
|
|
81
|
-
<li>
|
|
82
|
-
<a
|
|
83
|
-
href={`${githubUrl}/blob/main/CONTRIBUTING.md`}
|
|
84
|
-
target="_blank"
|
|
85
|
-
rel="noopener noreferrer"
|
|
86
|
-
class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100"
|
|
87
|
-
>Contributing guide</a
|
|
88
|
-
>
|
|
89
|
-
</li>
|
|
90
|
-
</ul>
|
|
91
|
-
</div>
|
|
92
|
-
|
|
93
|
-
<div>
|
|
94
|
-
<h4
|
|
95
|
-
class="mb-3 text-2xs font-semibold uppercase tracking-wider text-ink-900 dark:text-ink-100"
|
|
96
|
-
>
|
|
97
|
-
Project
|
|
98
|
-
</h4>
|
|
99
|
-
<ul class="m-0 flex list-none flex-col gap-2 p-0">
|
|
100
|
-
<li>
|
|
101
|
-
<a
|
|
102
|
-
href={githubUrl}
|
|
103
|
-
target="_blank"
|
|
104
|
-
rel="noopener noreferrer"
|
|
105
|
-
class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100"
|
|
106
|
-
>Source on GitHub</a
|
|
107
|
-
>
|
|
108
|
-
</li>
|
|
109
|
-
<li><a href="#about" class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100">Why this exists</a></li>
|
|
110
|
-
<li>
|
|
111
|
-
<a
|
|
112
|
-
href={`${githubUrl}/blob/main/README.md`}
|
|
113
|
-
target="_blank"
|
|
114
|
-
rel="noopener noreferrer"
|
|
115
|
-
class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100"
|
|
116
|
-
>README</a
|
|
117
|
-
>
|
|
118
|
-
</li>
|
|
119
|
-
<li>
|
|
120
|
-
<a
|
|
121
|
-
href="/about"
|
|
122
|
-
class="text-sm transition-colors hover:text-ink-900 dark:hover:text-ink-100"
|
|
123
|
-
>About</a
|
|
124
|
-
>
|
|
125
|
-
</li>
|
|
126
|
-
</ul>
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
|
|
130
|
-
<div class="border-t border-ink-200 dark:border-ink-800">
|
|
131
|
-
<div
|
|
132
|
-
class="mx-auto flex max-w-wide flex-wrap items-center gap-3 px-5 py-4 text-2xs text-ink-500 sm:px-7 dark:text-ink-400"
|
|
133
|
-
>
|
|
134
|
-
<span>© {year} {siteConfig.name}. Content under CC BY-SA 4.0.</span>
|
|
135
|
-
<span class="text-ink-300 dark:text-ink-700">·</span>
|
|
136
|
-
<a
|
|
137
|
-
href={githubUrl}
|
|
138
|
-
target="_blank"
|
|
139
|
-
rel="noopener noreferrer"
|
|
140
|
-
class="transition-colors hover:text-ink-900 dark:hover:text-ink-100"
|
|
141
|
-
>View source on GitHub</a
|
|
142
|
-
>
|
|
143
|
-
</div>
|
|
144
26
|
</div>
|
|
145
27
|
</footer>
|