@grove-dev/astro 0.1.4 → 0.2.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 (246) hide show
  1. package/dist/index.d.ts +4 -25
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +56 -22
  4. package/dist/index.js.map +1 -1
  5. package/dist/layouts/index.d.ts +25 -0
  6. package/dist/layouts/index.d.ts.map +1 -0
  7. package/dist/layouts/index.js +25 -0
  8. package/dist/layouts/index.js.map +1 -0
  9. package/dist/lib/display.d.ts +33 -0
  10. package/dist/lib/display.d.ts.map +1 -0
  11. package/dist/lib/display.js +104 -0
  12. package/dist/lib/display.js.map +1 -0
  13. package/dist/lib/format.d.ts +30 -0
  14. package/dist/lib/format.d.ts.map +1 -0
  15. package/dist/lib/format.js +73 -0
  16. package/dist/lib/format.js.map +1 -0
  17. package/dist/lib/index.d.ts +26 -0
  18. package/dist/lib/index.d.ts.map +1 -0
  19. package/dist/lib/index.js +26 -0
  20. package/dist/lib/index.js.map +1 -0
  21. package/dist/lib/lenses.d.ts +96 -0
  22. package/dist/lib/lenses.d.ts.map +1 -0
  23. package/dist/lib/lenses.js +181 -0
  24. package/dist/lib/lenses.js.map +1 -0
  25. package/dist/lib/repo.d.ts +30 -0
  26. package/dist/lib/repo.d.ts.map +1 -0
  27. package/dist/lib/repo.js +44 -0
  28. package/dist/lib/repo.js.map +1 -0
  29. package/dist/lib/scores.d.ts +38 -0
  30. package/dist/lib/scores.d.ts.map +1 -0
  31. package/dist/lib/scores.js +83 -0
  32. package/dist/lib/scores.js.map +1 -0
  33. package/dist/lib/search.d.ts +199 -0
  34. package/dist/lib/search.d.ts.map +1 -0
  35. package/dist/lib/search.js +357 -0
  36. package/dist/lib/search.js.map +1 -0
  37. package/dist/lib/taxonomy-counts.d.ts +25 -0
  38. package/dist/lib/taxonomy-counts.d.ts.map +1 -0
  39. package/dist/lib/taxonomy-counts.js +41 -0
  40. package/dist/lib/taxonomy-counts.js.map +1 -0
  41. package/package.json +7 -7
  42. package/src/components/AppSection.astro +83 -0
  43. package/src/components/AppsIndexRow.astro +204 -0
  44. package/src/components/AppsPagination.astro +126 -0
  45. package/src/components/CategoryGrid.astro +86 -17
  46. package/src/components/ContributorsGrid.astro +149 -0
  47. package/src/components/DecisionRow.astro +89 -0
  48. package/src/components/ExploreByCategory.astro +67 -0
  49. package/src/components/ExploreByStack.astro +72 -0
  50. package/src/components/Hero.astro +246 -0
  51. package/src/components/Icon.astro +223 -0
  52. package/src/components/ItemCard.astro +289 -30
  53. package/src/components/MinimalAbout.astro +82 -0
  54. package/src/components/OriginalCollection.astro +116 -0
  55. package/src/components/RefinePanel.astro +197 -0
  56. package/src/components/ScoreBars.astro +92 -22
  57. package/src/components/SmartLensTabs.astro +71 -0
  58. package/src/components/StackGrid.astro +132 -0
  59. package/src/components/WhyThisExists.astro +116 -0
  60. package/src/index.ts +61 -14
  61. package/src/layouts/BaseLayout.astro +227 -15
  62. package/src/layouts/Container.astro +57 -0
  63. package/src/layouts/Footer.astro +235 -0
  64. package/src/layouts/Header.astro +159 -0
  65. package/src/layouts/SectionHeader.astro +58 -0
  66. package/{templates/default/src/components/layout → src/layouts}/Seo.astro +62 -38
  67. package/src/layouts/ThemeToggle.astro +110 -0
  68. package/src/layouts/astro-shim.d.ts +29 -0
  69. package/src/layouts/index.ts +24 -0
  70. package/src/lib/display.ts +118 -0
  71. package/src/lib/format.ts +65 -0
  72. package/src/lib/index.ts +26 -0
  73. package/src/lib/lenses.ts +241 -0
  74. package/src/lib/repo.ts +44 -0
  75. package/src/lib/scores.ts +94 -0
  76. package/src/lib/search.ts +481 -0
  77. package/src/lib/taxonomy-counts.ts +60 -0
  78. package/src/styles.css +366 -638
  79. package/templates/default/.astro/content.d.ts +155 -0
  80. package/templates/default/.astro/settings.json +5 -0
  81. package/templates/default/.astro/types.d.ts +2 -0
  82. package/templates/default/astro.config.mjs +8 -6
  83. package/templates/default/content/pages/about.md +66 -0
  84. package/templates/default/content/pages/methodology.md +103 -0
  85. package/templates/default/data/generated/records.full.json +8 -0
  86. package/templates/default/data/generated/records.index.json +7 -0
  87. package/templates/default/data/generated/records.json +8 -0
  88. package/templates/default/data/generated/site-config.json +31 -0
  89. package/templates/default/data/records/.gitkeep +0 -0
  90. package/templates/default/dist/_astro/BaseLayout.DfpwR3jc.css +1 -0
  91. package/templates/default/dist/about/index.html +165 -0
  92. package/templates/default/dist/icons/platforms/android.svg +1 -0
  93. package/templates/default/dist/icons/platforms/apple-dark.svg +1 -0
  94. package/templates/default/dist/icons/platforms/apple-light.svg +1 -0
  95. package/templates/default/dist/icons/platforms/chrome.svg +1 -0
  96. package/templates/default/dist/icons/platforms/chromeos.svg +5 -0
  97. package/templates/default/dist/icons/platforms/desktop.svg +4 -0
  98. package/templates/default/dist/icons/platforms/embedded.svg +5 -0
  99. package/templates/default/dist/icons/platforms/ios.svg +1 -0
  100. package/templates/default/dist/icons/platforms/linux.svg +1 -0
  101. package/templates/default/dist/icons/platforms/macos.svg +1 -0
  102. package/templates/default/dist/icons/platforms/ubuntu.svg +1 -0
  103. package/templates/default/dist/icons/platforms/web.svg +5 -0
  104. package/templates/default/dist/icons/platforms/windows.svg +6 -0
  105. package/templates/default/dist/icons/stacks/android.svg +1 -0
  106. package/templates/default/dist/icons/stacks/apple-dark.svg +1 -0
  107. package/templates/default/dist/icons/stacks/apple-light.svg +1 -0
  108. package/templates/default/dist/icons/stacks/capacitor.svg +14 -0
  109. package/templates/default/dist/icons/stacks/dart.svg +1 -0
  110. package/templates/default/dist/icons/stacks/firebase.svg +1 -0
  111. package/templates/default/dist/icons/stacks/flutter.svg +1 -0
  112. package/templates/default/dist/icons/stacks/graphql.svg +1 -0
  113. package/templates/default/dist/icons/stacks/ionic.svg +4 -0
  114. package/templates/default/dist/icons/stacks/java.svg +1 -0
  115. package/templates/default/dist/icons/stacks/javascript.svg +1 -0
  116. package/templates/default/dist/icons/stacks/kotlin.svg +1 -0
  117. package/templates/default/dist/icons/stacks/mongodb.svg +1 -0
  118. package/templates/default/dist/icons/stacks/nodejs.svg +1 -0
  119. package/templates/default/dist/icons/stacks/python.svg +1 -0
  120. package/templates/default/dist/icons/stacks/react-native.svg +1 -0
  121. package/templates/default/dist/icons/stacks/react.svg +1 -0
  122. package/templates/default/dist/icons/stacks/rust.svg +1 -0
  123. package/templates/default/dist/icons/stacks/solidity.svg +1 -0
  124. package/templates/default/dist/icons/stacks/swift.svg +1 -0
  125. package/templates/default/dist/icons/stacks/tensorflow.svg +1 -0
  126. package/templates/default/dist/icons/stacks/typescript.svg +1 -0
  127. package/templates/default/dist/index.html +55 -0
  128. package/templates/default/dist/llms-full.txt +14 -0
  129. package/templates/default/dist/llms.txt +11 -0
  130. package/templates/default/dist/og-image.svg +48 -0
  131. package/templates/default/dist/projects/index.html +61 -0
  132. package/templates/default/dist/robots.txt +53 -0
  133. package/templates/default/dist/sitemap.xml +21 -0
  134. package/templates/default/dist/submit/index.html +69 -0
  135. package/templates/default/grove.config.ts +36 -0
  136. package/templates/default/node_modules/.bin/astro +21 -0
  137. package/templates/default/node_modules/.bin/astro-check +21 -0
  138. package/templates/default/node_modules/.bin/grove +21 -0
  139. package/templates/default/node_modules/.bin/jiti +21 -0
  140. package/templates/default/node_modules/.bin/prettier +21 -0
  141. package/templates/default/node_modules/.bin/rollup +21 -0
  142. package/templates/default/node_modules/.bin/tsc +21 -0
  143. package/templates/default/node_modules/.bin/tsserver +21 -0
  144. package/templates/default/node_modules/.bin/tsx +21 -0
  145. package/templates/default/node_modules/.bin/vite +21 -0
  146. package/templates/default/node_modules/.bin/yaml +21 -0
  147. package/templates/default/node_modules/.vite/deps/_metadata.json +79 -0
  148. package/templates/default/node_modules/.vite/deps/astro-KRVZHBC5.js +433 -0
  149. package/templates/default/node_modules/.vite/deps/astro-KRVZHBC5.js.map +7 -0
  150. package/templates/default/node_modules/.vite/deps/astro___aria-query.js +5 -0
  151. package/templates/default/node_modules/.vite/deps/astro___aria-query.js.map +7 -0
  152. package/templates/default/node_modules/.vite/deps/astro___axobject-query.js +5 -0
  153. package/templates/default/node_modules/.vite/deps/astro___axobject-query.js.map +7 -0
  154. package/templates/default/node_modules/.vite/deps/astro___html-escaper.js +9 -0
  155. package/templates/default/node_modules/.vite/deps/astro___html-escaper.js.map +7 -0
  156. package/templates/default/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +241 -0
  157. package/templates/default/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +7 -0
  158. package/templates/default/node_modules/.vite/deps/audit-GYHQ3ITH.js +1592 -0
  159. package/templates/default/node_modules/.vite/deps/audit-GYHQ3ITH.js.map +7 -0
  160. package/templates/default/node_modules/.vite/deps/chunk-5WRI5ZAA.js +30 -0
  161. package/templates/default/node_modules/.vite/deps/chunk-5WRI5ZAA.js.map +7 -0
  162. package/templates/default/node_modules/.vite/deps/chunk-7P4KIK53.js +186 -0
  163. package/templates/default/node_modules/.vite/deps/chunk-7P4KIK53.js.map +7 -0
  164. package/templates/default/node_modules/.vite/deps/chunk-BQGHFQJH.js +48 -0
  165. package/templates/default/node_modules/.vite/deps/chunk-BQGHFQJH.js.map +7 -0
  166. package/templates/default/node_modules/.vite/deps/chunk-CJCDKWP2.js +6779 -0
  167. package/templates/default/node_modules/.vite/deps/chunk-CJCDKWP2.js.map +7 -0
  168. package/templates/default/node_modules/.vite/deps/chunk-FHJ3XBDE.js +33 -0
  169. package/templates/default/node_modules/.vite/deps/chunk-FHJ3XBDE.js.map +7 -0
  170. package/templates/default/node_modules/.vite/deps/chunk-FQEMNIUQ.js +88 -0
  171. package/templates/default/node_modules/.vite/deps/chunk-FQEMNIUQ.js.map +7 -0
  172. package/templates/default/node_modules/.vite/deps/chunk-HBSVDAQD.js +72 -0
  173. package/templates/default/node_modules/.vite/deps/chunk-HBSVDAQD.js.map +7 -0
  174. package/templates/default/node_modules/.vite/deps/chunk-HDOQ2U3U.js +3757 -0
  175. package/templates/default/node_modules/.vite/deps/chunk-HDOQ2U3U.js.map +7 -0
  176. package/templates/default/node_modules/.vite/deps/chunk-XEBKRCNE.js +54 -0
  177. package/templates/default/node_modules/.vite/deps/chunk-XEBKRCNE.js.map +7 -0
  178. package/templates/default/node_modules/.vite/deps/package.json +3 -0
  179. package/templates/default/node_modules/.vite/deps/settings-C5H4VHXU.js +213 -0
  180. package/templates/default/node_modules/.vite/deps/settings-C5H4VHXU.js.map +7 -0
  181. package/templates/default/node_modules/.vite/deps/toolbar-H5DB6HVP.js +525 -0
  182. package/templates/default/node_modules/.vite/deps/toolbar-H5DB6HVP.js.map +7 -0
  183. package/templates/default/node_modules/.vite/deps/ui-library-JGHU6JE2.js +1020 -0
  184. package/templates/default/node_modules/.vite/deps/ui-library-JGHU6JE2.js.map +7 -0
  185. package/templates/default/node_modules/.vite/deps/xray-EFCQOW4E.js +147 -0
  186. package/templates/default/node_modules/.vite/deps/xray-EFCQOW4E.js.map +7 -0
  187. package/templates/default/package.json +6 -5
  188. package/templates/default/public/llms-full.txt +14 -0
  189. package/templates/default/public/llms.txt +11 -0
  190. package/templates/default/src/components/layout/BaseLayout.astro +10 -57
  191. package/templates/default/src/components/layout/Footer.astro +16 -134
  192. package/templates/default/src/components/layout/Header.astro +25 -126
  193. package/templates/default/src/data/records.ts +161 -0
  194. package/templates/default/src/lib/markdown.ts +171 -0
  195. package/templates/default/src/pages/about.astro +95 -429
  196. package/templates/default/src/pages/index.astro +258 -61
  197. package/templates/default/src/pages/projects/[slug].astro +480 -0
  198. package/templates/default/src/pages/projects/index.astro +193 -0
  199. package/templates/default/src/pages/sitemap.xml.ts +73 -61
  200. package/templates/default/src/pages/submit.astro +122 -411
  201. package/templates/default/src/styles/global.css +42 -68
  202. package/src/components/ActiveFilterChips.astro +0 -20
  203. package/src/components/DirectoryFilters.astro +0 -100
  204. package/src/components/DirectoryHero.astro +0 -32
  205. package/src/components/HealthBadge.astro +0 -12
  206. package/src/components/LensTabs.astro +0 -26
  207. package/src/components/MethodologyPanel.astro +0 -20
  208. package/src/components/Pagination.astro +0 -24
  209. package/src/components/ProjectDetail.astro +0 -166
  210. package/src/components/SubmitDraft.astro +0 -137
  211. package/templates/default/src/components/AppCard.astro +0 -248
  212. package/templates/default/src/components/AppSection.astro +0 -58
  213. package/templates/default/src/components/AppsIndexRow.astro +0 -230
  214. package/templates/default/src/components/AppsPagination.astro +0 -147
  215. package/templates/default/src/components/CategoryGrid.astro +0 -80
  216. package/templates/default/src/components/ContributorsGrid.astro +0 -105
  217. package/templates/default/src/components/DecisionRow.astro +0 -219
  218. package/templates/default/src/components/ExploreByCategory.astro +0 -74
  219. package/templates/default/src/components/ExploreByStack.astro +0 -102
  220. package/templates/default/src/components/Hero.astro +0 -176
  221. package/templates/default/src/components/MinimalAbout.astro +0 -57
  222. package/templates/default/src/components/OriginalCollection.astro +0 -144
  223. package/templates/default/src/components/RefinePanel.astro +0 -272
  224. package/templates/default/src/components/ScoreBars.astro +0 -72
  225. package/templates/default/src/components/SmartLensTabs.astro +0 -65
  226. package/templates/default/src/components/StackGrid.astro +0 -95
  227. package/templates/default/src/components/WhyThisExists.astro +0 -81
  228. package/templates/default/src/components/icons/Icon.astro +0 -148
  229. package/templates/default/src/components/layout/SectionHeader.astro +0 -42
  230. package/templates/default/src/components/layout/ThemeToggle.astro +0 -97
  231. package/templates/default/src/data/apps.ts +0 -149
  232. package/templates/default/src/data/categories.ts +0 -27
  233. package/templates/default/src/data/config.ts +0 -28
  234. package/templates/default/src/data/contributors.ts +0 -96
  235. package/templates/default/src/data/stacks.ts +0 -47
  236. package/templates/default/src/data/stats.ts +0 -65
  237. package/templates/default/src/data/types.ts +0 -248
  238. package/templates/default/src/lib/apps-search.ts +0 -228
  239. package/templates/default/src/lib/format.ts +0 -36
  240. package/templates/default/src/lib/lenses.ts +0 -98
  241. package/templates/default/src/lib/repo.ts +0 -12
  242. package/templates/default/src/lib/scores.ts +0 -51
  243. package/templates/default/src/lib/taxonomy-counts.ts +0 -31
  244. package/templates/default/src/pages/apps/[slug].astro +0 -709
  245. package/templates/default/src/pages/apps/index.astro +0 -669
  246. package/templates/default/src/pages/contributors.astro +0 -142
@@ -1,149 +0,0 @@
1
- import generatedJson from "../../data/generated/apps.json";
2
- import type { OpenSourceApp, AppLabel } from "./types";
3
-
4
- // ──────────────────────────────────────────────────────────────────────
5
- // Source of truth: data/generated/apps.json, produced at build time
6
- // from data/apps/*.yml by scripts/build-apps-json.mjs. The yml files
7
- // are the human-edited source; this file is just a typed re-export
8
- // that fills in safe defaults so consumers don't have to guard every
9
- // optional field.
10
- //
11
- // When adding a new app: write a yml in data/apps/, run
12
- // `pnpm run build:data`, and it will appear here.
13
- // ──────────────────────────────────────────────────────────────────────
14
-
15
- const generated = generatedJson as { apps: unknown[] };
16
-
17
- type GeneratedApp = Partial<OpenSourceApp> & {
18
- slug: string;
19
- name: string;
20
- repoUrl: string;
21
- description?: string;
22
- stack: string;
23
- platforms: string[];
24
- category: string;
25
- activity?: {
26
- stars?: number;
27
- forks?: number;
28
- lastCommitAt?: string | null;
29
- contributors?: number;
30
- updatedAt?: string;
31
- };
32
- };
33
-
34
- /**
35
- * Auto-compute labels for an app from its activity block. Used as a
36
- * fallback when a curator hasn't hand-set `labels:` in the yml. Drives
37
- * the homepage "new / hot / mature" sections.
38
- *
39
- * mature — stars ≥ 500, OR very high stars (popular, established)
40
- * hot — last commit within the last 6 months (currently active)
41
- * new — emerging: not mature, not in the last commit window, or
42
- * no commit signal at all
43
- *
44
- * Multiple labels can apply (a popular active project is both mature
45
- * and hot).
46
- */
47
- function computeLabels(g: GeneratedApp): AppLabel[] {
48
- const labels: AppLabel[] = [];
49
- // After the schemaVersion 1 migration, stars + lastCommitAt live at
50
- // the top level of the generated record (the v1 normalizer in
51
- // `app-schema.mjs` flattens `github.repository.stargazers_count`
52
- // and `github.repository.pushed_at` to top-level). The old
53
- // `g.activity.stars` shape still works for legacy records, so we
54
- // fall back to it for mixed input.
55
- const stars =
56
- typeof g.stars === "number"
57
- ? g.stars
58
- : typeof g.activity?.stars === "number"
59
- ? g.activity.stars
60
- : 0;
61
- const lastCommit = g.lastCommitAt ?? g.activity?.lastCommitAt;
62
-
63
- if (stars >= 500) labels.push("mature");
64
- if (stars >= 100 && stars < 500) labels.push("hot");
65
- if (stars < 100) labels.push("new");
66
-
67
- // Hot: recent commit and not already tagged as such
68
- if (lastCommit) {
69
- const sixMonthsAgo = new Date();
70
- sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
71
- if (new Date(lastCommit) >= sixMonthsAgo && !labels.includes("hot")) {
72
- labels.push("hot");
73
- }
74
- }
75
- return labels;
76
- }
77
-
78
- /**
79
- * Map a generated yml-shaped record to the OpenSourceApp shape that
80
- * pages expect. Fills defaults, flattens `activity.stars` → `stars`,
81
- * and tolerates missing curation fields.
82
- */
83
- function normalize(g: GeneratedApp): OpenSourceApp {
84
- const a = g.activity ?? {};
85
- return {
86
- slug: g.slug,
87
- name: g.name,
88
- description: g.description ?? "",
89
- repoUrl: g.repoUrl,
90
- homepageUrl: g.homepageUrl,
91
- stack: g.stack,
92
- stacks: g.stacks,
93
- platforms: g.platforms ?? [],
94
- distribution: g.distribution,
95
- category: g.category,
96
- tags: g.tags,
97
- logoUrl: g.logoUrl,
98
- stars: typeof a.stars === "number" ? a.stars : g.stars,
99
- license: g.license,
100
- status: g.status,
101
- addedAt: g.addedAt,
102
- lastCommitAt: a.lastCommitAt ?? g.lastCommitAt,
103
- labels: g.labels && g.labels.length > 0 ? g.labels : computeLabels(g),
104
- // Curation (optional)
105
- projectType: g.projectType,
106
- stateManagement: g.stateManagement,
107
- backend: g.backend,
108
- architecture: g.architecture,
109
- difficulty: g.difficulty,
110
- codebaseSize: g.codebaseSize,
111
- bestFor: g.bestFor,
112
- whyListed: g.whyListed,
113
- caveats: g.caveats,
114
- goodFirstIssues: g.goodFirstIssues,
115
- contributionGuide: g.contributionGuide,
116
- launchedBy: g.launchedBy,
117
- launchAsk: g.launchAsk,
118
- lenses: g.lenses,
119
- scores: g.scores,
120
- curation: g.curation,
121
- github: g.github,
122
- health: g.health,
123
- tier: g.tier,
124
- };
125
- }
126
-
127
- const generatedApps = generated.apps as GeneratedApp[];
128
-
129
- export const apps: OpenSourceApp[] = generatedApps.map(normalize);
130
-
131
- // ── Convenience filters ──────────────────────────────────────────────
132
-
133
- export function newApps(): OpenSourceApp[] {
134
- return apps.filter((a) => a.labels?.includes("new"));
135
- }
136
- export function hotApps(): OpenSourceApp[] {
137
- return apps.filter((a) => a.labels?.includes("hot"));
138
- }
139
- export function matureApps(): OpenSourceApp[] {
140
- return apps.filter((a) => a.labels?.includes("mature"));
141
- }
142
-
143
- // ── Lookups ──────────────────────────────────────────────────────────
144
-
145
- const bySlug = new Map(apps.map((a) => [a.slug, a]));
146
-
147
- export function appBySlug(slug: string): OpenSourceApp | undefined {
148
- return bySlug.get(slug);
149
- }
@@ -1,27 +0,0 @@
1
- export type Category = {
2
- slug: string;
3
- name: string;
4
- blurb: string;
5
- };
6
-
7
- // Static taxonomy. Counts are NOT stored here — they are computed at
8
- // build time from data/generated/apps.json via src/lib/category-counts.ts
9
- // so the numbers always match what's actually rendered.
10
- export const categories: Category[] = [
11
- { slug: "productivity", name: "Productivity", blurb: "Tasks, notes, calendars, knowledge bases." },
12
- { slug: "finance", name: "Finance", blurb: "Budgeting, wallets, expense tracking." },
13
- { slug: "education", name: "Education", blurb: "Flashcards, learning, reference apps." },
14
- { slug: "tools", name: "Tools", blurb: "Browsers, utilities, dev helpers, file tools." },
15
- { slug: "communication", name: "Communication", blurb: "Chat, messaging, social, team tools." },
16
- { slug: "health-and-fitness", name: "Health and Fitness", blurb: "Workouts, nutrition, wellness tracking." },
17
- { slug: "business", name: "Business", blurb: "Invoicing, jobs, marketplace, ops tools." },
18
- { slug: "games", name: "Games", blurb: "Open-source games and engines." },
19
- { slug: "media", name: "Media", blurb: "Music, movies, photos, audio and video." },
20
- { slug: "entertainment", name: "Entertainment", blurb: "TV, movies, books, anime, ebooks." },
21
- { slug: "social-network", name: "Social Network", blurb: "Decentralized social clients and readers." },
22
- { slug: "shopping", name: "Shopping", blurb: "E-commerce, delivery, food, retail." },
23
- { slug: "news", name: "News and Magazine", blurb: "Hacker News clients, RSS, magazines." },
24
- { slug: "travel", name: "Travel", blurb: "Flights, tourism, cab sharing, guides." },
25
- { slug: "lifestyle", name: "Lifestyle", blurb: "Habits, journaling, daily life tools." },
26
- { slug: "personalization", name: "Personalization", blurb: "Launchers, themes, customization." },
27
- ];
@@ -1,28 +0,0 @@
1
- /**
2
- * Site config exposed to Astro pages.
3
- *
4
- * This file is the typed view of `curated.config.ts`. The CLI builds it
5
- * from the project-root config at `grove build-data` time. Astro
6
- * pages and components import it directly for branding strings.
7
- *
8
- * Do not edit by hand. Re-run `grove build-data` after changing
9
- * `curated.config.ts`.
10
- */
11
-
12
- export type SiteConfig = {
13
- name: string;
14
- tagline: string;
15
- description: string;
16
- siteUrl: string;
17
- repoUrl: string;
18
- itemLabel: string;
19
- };
20
-
21
- export const siteConfig: SiteConfig = {
22
- name: "Grove",
23
- tagline: "A living, health-aware developer directory.",
24
- description: "A searchable directory of open-source projects — organized by stack, category, platform, license, activity, and maturity.",
25
- siteUrl: "https://example.com",
26
- repoUrl: "https://github.com/tortuvshin/grove",
27
- itemLabel: "project",
28
- };
@@ -1,96 +0,0 @@
1
- export type Contributor = {
2
- username: string;
3
- name?: string;
4
- avatarUrl: string;
5
- profileUrl: string;
6
- contributions?: number;
7
- };
8
-
9
- // AUTO-GENERATED by scripts/sync-contributors.mjs — do not edit by hand.
10
- // Re-run the script (or wait for the weekly workflow) to refresh from GitHub.
11
- // Source: GET /repos/tortuvshin/open-apps/contributors (82 named contributors).
12
- // Anonymous contributors are excluded — the homepage grid renders <a> avatars with no anonymous target.
13
- export const contributors: Contributor[] = [
14
- { username: "tortuvshin", avatarUrl: "https://avatars.githubusercontent.com/u/9257227?v=4", profileUrl: "https://github.com/tortuvshin", contributions: 140 },
15
- { username: "j-j-gajjar", avatarUrl: "https://avatars.githubusercontent.com/u/57590688?v=4", profileUrl: "https://github.com/j-j-gajjar", contributions: 5 },
16
- { username: "ArizArmeidi", avatarUrl: "https://avatars.githubusercontent.com/u/60814961?v=4", profileUrl: "https://github.com/ArizArmeidi", contributions: 3 },
17
- { username: "vellt", avatarUrl: "https://avatars.githubusercontent.com/u/61885011?v=4", profileUrl: "https://github.com/vellt", contributions: 3 },
18
- { username: "tejasbadone", avatarUrl: "https://avatars.githubusercontent.com/u/81501235?v=4", profileUrl: "https://github.com/tejasbadone", contributions: 3 },
19
- { username: "ErfanRht", avatarUrl: "https://avatars.githubusercontent.com/u/68302442?v=4", profileUrl: "https://github.com/ErfanRht", contributions: 2 },
20
- { username: "monolidth", avatarUrl: "https://avatars.githubusercontent.com/u/71930307?v=4", profileUrl: "https://github.com/monolidth", contributions: 2 },
21
- { username: "proninyaroslav", avatarUrl: "https://avatars.githubusercontent.com/u/7840559?v=4", profileUrl: "https://github.com/proninyaroslav", contributions: 2 },
22
- { username: "Tarikul711", avatarUrl: "https://avatars.githubusercontent.com/u/9304805?v=4", profileUrl: "https://github.com/Tarikul711", contributions: 2 },
23
- { username: "lucalves", avatarUrl: "https://avatars.githubusercontent.com/u/17712401?v=4", profileUrl: "https://github.com/lucalves", contributions: 2 },
24
- { username: "1hanzla100", avatarUrl: "https://avatars.githubusercontent.com/u/59178380?v=4", profileUrl: "https://github.com/1hanzla100", contributions: 2 },
25
- { username: "jerichoi224", avatarUrl: "https://avatars.githubusercontent.com/u/4184001?v=4", profileUrl: "https://github.com/jerichoi224", contributions: 2 },
26
- { username: "tsvillain", avatarUrl: "https://avatars.githubusercontent.com/u/42140007?v=4", profileUrl: "https://github.com/tsvillain", contributions: 1 },
27
- { username: "TNT-Likely", avatarUrl: "https://avatars.githubusercontent.com/u/9278923?v=4", profileUrl: "https://github.com/TNT-Likely", contributions: 1 },
28
- { username: "sumittiware", avatarUrl: "https://avatars.githubusercontent.com/u/64718675?v=4", profileUrl: "https://github.com/sumittiware", contributions: 1 },
29
- { username: "simonbengtsson", avatarUrl: "https://avatars.githubusercontent.com/u/3586691?v=4", profileUrl: "https://github.com/simonbengtsson", contributions: 1 },
30
- { username: "shaxxx", avatarUrl: "https://avatars.githubusercontent.com/u/1778875?v=4", profileUrl: "https://github.com/shaxxx", contributions: 1 },
31
- { username: "88srzh", avatarUrl: "https://avatars.githubusercontent.com/u/61797666?v=4", profileUrl: "https://github.com/88srzh", contributions: 1 },
32
- { username: "SatyamX64", avatarUrl: "https://avatars.githubusercontent.com/u/62766656?v=4", profileUrl: "https://github.com/SatyamX64", contributions: 1 },
33
- { username: "sarvesh4396", avatarUrl: "https://avatars.githubusercontent.com/u/68162479?v=4", profileUrl: "https://github.com/sarvesh4396", contributions: 1 },
34
- { username: "illussna", avatarUrl: "https://avatars.githubusercontent.com/u/20238269?v=4", profileUrl: "https://github.com/illussna", contributions: 1 },
35
- { username: "SAHILDUDHAL21", avatarUrl: "https://avatars.githubusercontent.com/u/129080375?v=4", profileUrl: "https://github.com/SAHILDUDHAL21", contributions: 1 },
36
- { username: "SaadAAkash", avatarUrl: "https://avatars.githubusercontent.com/u/16515550?v=4", profileUrl: "https://github.com/SaadAAkash", contributions: 1 },
37
- { username: "Rohithgilla12", avatarUrl: "https://avatars.githubusercontent.com/u/19389850?v=4", profileUrl: "https://github.com/Rohithgilla12", contributions: 1 },
38
- { username: "teolemon", avatarUrl: "https://avatars.githubusercontent.com/u/1689815?v=4", profileUrl: "https://github.com/teolemon", contributions: 1 },
39
- { username: "Re4ch-Jay", avatarUrl: "https://avatars.githubusercontent.com/u/111555521?v=4", profileUrl: "https://github.com/Re4ch-Jay", contributions: 1 },
40
- { username: "pauek", avatarUrl: "https://avatars.githubusercontent.com/u/4069?v=4", profileUrl: "https://github.com/pauek", contributions: 1 },
41
- { username: "DaNnyKg07", avatarUrl: "https://avatars.githubusercontent.com/u/78636435?v=4", profileUrl: "https://github.com/DaNnyKg07", contributions: 1 },
42
- { username: "omar-h-omar", avatarUrl: "https://avatars.githubusercontent.com/u/58376513?v=4", profileUrl: "https://github.com/omar-h-omar", contributions: 1 },
43
- { username: "FatoomRe", avatarUrl: "https://avatars.githubusercontent.com/u/112693194?v=4", profileUrl: "https://github.com/FatoomRe", contributions: 1 },
44
- { username: "yon30c", avatarUrl: "https://avatars.githubusercontent.com/u/83658386?v=4", profileUrl: "https://github.com/yon30c", contributions: 1 },
45
- { username: "y-pakorn", avatarUrl: "https://avatars.githubusercontent.com/u/48324733?v=4", profileUrl: "https://github.com/y-pakorn", contributions: 1 },
46
- { username: "virlow-voice", avatarUrl: "https://avatars.githubusercontent.com/u/102702984?v=4", profileUrl: "https://github.com/virlow-voice", contributions: 1 },
47
- { username: "trizin", avatarUrl: "https://avatars.githubusercontent.com/u/25263018?v=4", profileUrl: "https://github.com/trizin", contributions: 1 },
48
- { username: "sparkleMing", avatarUrl: "https://avatars.githubusercontent.com/u/38350996?v=4", profileUrl: "https://github.com/sparkleMing", contributions: 1 },
49
- { username: "softjapan", avatarUrl: "https://avatars.githubusercontent.com/u/11269856?v=4", profileUrl: "https://github.com/softjapan", contributions: 1 },
50
- { username: "moda20", avatarUrl: "https://avatars.githubusercontent.com/u/23613485?v=4", profileUrl: "https://github.com/moda20", contributions: 1 },
51
- { username: "mihalycsaba", avatarUrl: "https://avatars.githubusercontent.com/u/50019470?v=4", profileUrl: "https://github.com/mihalycsaba", contributions: 1 },
52
- { username: "ivirtex", avatarUrl: "https://avatars.githubusercontent.com/u/57679865?v=4", profileUrl: "https://github.com/ivirtex", contributions: 1 },
53
- { username: "comerc", avatarUrl: "https://avatars.githubusercontent.com/u/1025241?v=4", profileUrl: "https://github.com/comerc", contributions: 1 },
54
- { username: "albemala", avatarUrl: "https://avatars.githubusercontent.com/u/2332860?v=4", profileUrl: "https://github.com/albemala", contributions: 1 },
55
- { username: "xal", avatarUrl: "https://avatars.githubusercontent.com/u/1388084?v=4", profileUrl: "https://github.com/xal", contributions: 1 },
56
- { username: "yash1200", avatarUrl: "https://avatars.githubusercontent.com/u/38391570?v=4", profileUrl: "https://github.com/yash1200", contributions: 1 },
57
- { username: "wad3g", avatarUrl: "https://avatars.githubusercontent.com/u/2086896?v=4", profileUrl: "https://github.com/wad3g", contributions: 1 },
58
- { username: "VarunS2002", avatarUrl: "https://avatars.githubusercontent.com/u/30069380?v=4", profileUrl: "https://github.com/VarunS2002", contributions: 1 },
59
- { username: "friebetill", avatarUrl: "https://avatars.githubusercontent.com/u/10923085?v=4", profileUrl: "https://github.com/friebetill", contributions: 1 },
60
- { username: "theachoem", avatarUrl: "https://avatars.githubusercontent.com/u/29684683?v=4", profileUrl: "https://github.com/theachoem", contributions: 1 },
61
- { username: "Enhancifire", avatarUrl: "https://avatars.githubusercontent.com/u/81345756?v=4", profileUrl: "https://github.com/Enhancifire", contributions: 1 },
62
- { username: "Ehtiram-Ullah", avatarUrl: "https://avatars.githubusercontent.com/u/157794767?v=4", profileUrl: "https://github.com/Ehtiram-Ullah", contributions: 1 },
63
- { username: "Deepanshu-Rohilla", avatarUrl: "https://avatars.githubusercontent.com/u/52520071?v=4", profileUrl: "https://github.com/Deepanshu-Rohilla", contributions: 1 },
64
- { username: "DattatreyaReddy", avatarUrl: "https://avatars.githubusercontent.com/u/58727124?v=4", profileUrl: "https://github.com/DattatreyaReddy", contributions: 1 },
65
- { username: "shurygindv", avatarUrl: "https://avatars.githubusercontent.com/u/38868386?v=4", profileUrl: "https://github.com/shurygindv", contributions: 1 },
66
- { username: "csuka1219", avatarUrl: "https://avatars.githubusercontent.com/u/70962953?v=4", profileUrl: "https://github.com/csuka1219", contributions: 1 },
67
- { username: "ChangJoo-Park", avatarUrl: "https://avatars.githubusercontent.com/u/1451365?v=4", profileUrl: "https://github.com/ChangJoo-Park", contributions: 1 },
68
- { username: "KyleKun", avatarUrl: "https://avatars.githubusercontent.com/u/36611739?v=4", profileUrl: "https://github.com/KyleKun", contributions: 1 },
69
- { username: "bipinct", avatarUrl: "https://avatars.githubusercontent.com/u/1249142?v=4", profileUrl: "https://github.com/bipinct", contributions: 1 },
70
- { username: "Spyy004", avatarUrl: "https://avatars.githubusercontent.com/u/54628130?v=4", profileUrl: "https://github.com/Spyy004", contributions: 1 },
71
- { username: "AyanDas-99", avatarUrl: "https://avatars.githubusercontent.com/u/86493736?v=4", profileUrl: "https://github.com/AyanDas-99", contributions: 1 },
72
- { username: "aryamangodara", avatarUrl: "https://avatars.githubusercontent.com/u/77824849?v=4", profileUrl: "https://github.com/aryamangodara", contributions: 1 },
73
- { username: "agordn52", avatarUrl: "https://avatars.githubusercontent.com/u/17294994?v=4", profileUrl: "https://github.com/agordn52", contributions: 1 },
74
- { username: "akmadan", avatarUrl: "https://avatars.githubusercontent.com/u/56507451?v=4", profileUrl: "https://github.com/akmadan", contributions: 1 },
75
- { username: "akashlilhare", avatarUrl: "https://avatars.githubusercontent.com/u/39927872?v=4", profileUrl: "https://github.com/akashlilhare", contributions: 1 },
76
- { username: "aditya-njr", avatarUrl: "https://avatars.githubusercontent.com/u/169588760?v=4", profileUrl: "https://github.com/aditya-njr", contributions: 1 },
77
- { username: "abhith", avatarUrl: "https://avatars.githubusercontent.com/u/7039457?v=4", profileUrl: "https://github.com/abhith", contributions: 1 },
78
- { username: "NaserElziadna", avatarUrl: "https://avatars.githubusercontent.com/u/24838963?v=4", profileUrl: "https://github.com/NaserElziadna", contributions: 1 },
79
- { username: "brownboycodes", avatarUrl: "https://avatars.githubusercontent.com/u/64550304?v=4", profileUrl: "https://github.com/brownboycodes", contributions: 1 },
80
- { username: "mzsdev1", avatarUrl: "https://avatars.githubusercontent.com/u/34914546?v=4", profileUrl: "https://github.com/mzsdev1", contributions: 1 },
81
- { username: "mllrr96", avatarUrl: "https://avatars.githubusercontent.com/u/28247455?v=4", profileUrl: "https://github.com/mllrr96", contributions: 1 },
82
- { username: "hadiuzzaman524", avatarUrl: "https://avatars.githubusercontent.com/u/52348628?v=4", profileUrl: "https://github.com/hadiuzzaman524", contributions: 1 },
83
- { username: "deandreamatias", avatarUrl: "https://avatars.githubusercontent.com/u/21011641?v=4", profileUrl: "https://github.com/deandreamatias", contributions: 1 },
84
- { username: "mateusz-bak", avatarUrl: "https://avatars.githubusercontent.com/u/32651935?v=4", profileUrl: "https://github.com/mateusz-bak", contributions: 1 },
85
- { username: "maksymilian-majer", avatarUrl: "https://avatars.githubusercontent.com/u/1215868?v=4", profileUrl: "https://github.com/maksymilian-majer", contributions: 1 },
86
- { username: "musfique113", avatarUrl: "https://avatars.githubusercontent.com/u/53111065?v=4", profileUrl: "https://github.com/musfique113", contributions: 1 },
87
- { username: "Mufaddal5253110", avatarUrl: "https://avatars.githubusercontent.com/u/60619133?v=4", profileUrl: "https://github.com/Mufaddal5253110", contributions: 1 },
88
- { username: "Kessir", avatarUrl: "https://avatars.githubusercontent.com/u/2332730?v=4", profileUrl: "https://github.com/Kessir", contributions: 1 },
89
- { username: "kaiwalyakoparkar", avatarUrl: "https://avatars.githubusercontent.com/u/53310847?v=4", profileUrl: "https://github.com/kaiwalyakoparkar", contributions: 1 },
90
- { username: "Livinglist", avatarUrl: "https://avatars.githubusercontent.com/u/7277662?v=4", profileUrl: "https://github.com/Livinglist", contributions: 1 },
91
- { username: "jerald-jacob", avatarUrl: "https://avatars.githubusercontent.com/u/25875900?v=4", profileUrl: "https://github.com/jerald-jacob", contributions: 1 },
92
- { username: "jaysavsani07", avatarUrl: "https://avatars.githubusercontent.com/u/43170852?v=4", profileUrl: "https://github.com/jaysavsani07", contributions: 1 },
93
- { username: "javipacheco", avatarUrl: "https://avatars.githubusercontent.com/u/456025?v=4", profileUrl: "https://github.com/javipacheco", contributions: 1 },
94
- { username: "7flash", avatarUrl: "https://avatars.githubusercontent.com/u/4569866?v=4", profileUrl: "https://github.com/7flash", contributions: 1 },
95
- { username: "floranguyen0", avatarUrl: "https://avatars.githubusercontent.com/u/72301141?v=4", profileUrl: "https://github.com/floranguyen0", contributions: 1 },
96
- ];
@@ -1,47 +0,0 @@
1
- export type Stack = {
2
- slug: string;
3
- name: string;
4
- blurb: string;
5
- status: "live" | "expanding" | "planned";
6
- };
7
-
8
- // Static taxonomy. Counts are NOT stored here — they are computed at
9
- // build time from data/generated/apps.json. See src/lib/stack-counts.ts.
10
- export const stacks: Stack[] = [
11
- {
12
- slug: "flutter",
13
- name: "Flutter",
14
- blurb: "Dart-based, cross-platform mobile apps.",
15
- status: "live",
16
- },
17
- {
18
- slug: "react-native",
19
- name: "React Native",
20
- blurb: "JavaScript / TypeScript mobile apps using React.",
21
- status: "expanding",
22
- },
23
- {
24
- slug: "ios",
25
- name: "iOS",
26
- blurb: "Native Swift apps from the App Store and the open-source community.",
27
- status: "expanding",
28
- },
29
- {
30
- slug: "android",
31
- name: "Android",
32
- blurb: "Native Kotlin / Java apps with a long, mature history.",
33
- status: "expanding",
34
- },
35
- {
36
- slug: "kmp",
37
- name: "Kotlin Multiplatform",
38
- blurb: "Shared Kotlin codebases targeting iOS and Android.",
39
- status: "planned",
40
- },
41
- {
42
- slug: "capacitor",
43
- name: "Capacitor",
44
- blurb: "Hybrid mobile apps built on web standards.",
45
- status: "planned",
46
- },
47
- ];
@@ -1,65 +0,0 @@
1
- // Site stats, derived from generated JSON files at build time.
2
- //
3
- // This file imports the same JSON the rest of the app uses, so the numbers
4
- // here always match what's actually rendered. No hand-tuned magic numbers.
5
- //
6
- // Numbers in the rendered UI (hero, header, OriginalCollection) come from
7
- // this module. If a number looks wrong, refresh the source data:
8
- // - pnpm run sync:repo-stats → data/generated/repo-stats.json (open-apps repo)
9
- // - pnpm run sync:contributors → src/data/contributors.ts
10
- // - pnpm run refresh:activity → data/apps/*.yml (per-app activity, then build:data)
11
- import generatedJson from "../../data/generated/apps.json";
12
- import repoStats from "../../data/generated/repo-stats.json";
13
- import { categories } from "./categories";
14
- import { contributors } from "./contributors";
15
-
16
- type GeneratedApp = {
17
- stack?: string;
18
- platforms?: string[];
19
- };
20
-
21
- type RepoStats = {
22
- stars: number;
23
- forks: number;
24
- watchers?: number;
25
- openIssues?: number;
26
- defaultBranch?: string;
27
- pushedAt?: string;
28
- syncedAt?: string;
29
- };
30
-
31
- const raw = generatedJson as { apps?: GeneratedApp[] };
32
- const apps: GeneratedApp[] = raw.apps ?? [];
33
- const repo = repoStats as RepoStats;
34
-
35
- const platforms = new Set<string>();
36
- for (const a of apps) {
37
- for (const p of a.platforms ?? []) platforms.add(p);
38
- }
39
-
40
- export type SiteStats = {
41
- apps: number;
42
- contributors: number;
43
- stars: number;
44
- forks: number;
45
- categories: number;
46
- stacks: number;
47
- platforms: number;
48
- originalRepo: string;
49
- };
50
-
51
- export const stats: SiteStats = {
52
- apps: apps.length,
53
- contributors: contributors.length,
54
- // Stars/forks are the open-apps repo's own — sourced from
55
- // data/generated/repo-stats.json, refreshed weekly by the
56
- // sync-repo-stats workflow. Previously these were summed across
57
- // every app in the directory, which produced 6-figure numbers
58
- // for a 4k-star repo.
59
- stars: repo.stars,
60
- forks: repo.forks,
61
- categories: categories.length,
62
- stacks: new Set(apps.map((a) => a.stack).filter(Boolean)).size,
63
- platforms: platforms.size,
64
- originalRepo: "https://github.com/tortuvshin/open-apps",
65
- };