diff --git a/CLAUDE.md b/CLAUDE.md index bb547db..b11d68b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,6 +43,7 @@ dev server. - fuz_ui (@fuzdev/fuz_ui) - UI components, theming, docs system - fuz_util (@fuzdev/fuz_util) - utility functions - fuz_code (@fuzdev/fuz_code) - syntax highlighting +- fuz_gitops (@fuzdev/fuz_gitops) - multi-repo management and UI components - Gro (@fuzdev/gro) - build system and task runner ## SvelteKit app @@ -53,6 +54,18 @@ Static site at fuz.dev. Uses `@sveltejs/adapter-static` with prerendering. - `/` - Main landing page with vision, description, ProjectLinks - `/about` - About the Fuz ecosystem and fuzdev +- `/tree` - Repo tree view (fuz_gitops), with `/tree/[slug]` per-repo detail +- `/table` - Repo dependency table (fuz_gitops) +- `/modules` - Module explorer (fuz_gitops) +- `/pull_requests` - Pull requests across repos (fuz_gitops) + +### Gitops + +`gitops.config.ts` lists all public fuzdev repos. Data is generated by +`gro gitops_sync` into `src/routes/repos.json`. Each gitops route has its +own layout for code-splitting (duplicated `repos_context` setup pattern, +same as ryanatkn.com). Presentation will be rethought toward tx-style +dashboard layouts. Deploy with `gro deploy` (builds and pushes to deploy branch). @@ -70,4 +83,5 @@ Deploy with `gro deploy` (builds and pushes to deploy branch). - [`fuz_css`](../fuz_css/CLAUDE.md) - CSS framework - [`fuz_ui`](../fuz_ui/CLAUDE.md) - UI components and docs system - [`fuz_util`](../fuz_util/CLAUDE.md) - utility functions +- [`fuz_gitops`](../fuz_gitops/CLAUDE.md) - multi-repo management UI - [`gro`](../gro/CLAUDE.md) - build system and task runner diff --git a/gitops.config.ts b/gitops.config.ts new file mode 100644 index 0000000..67634d8 --- /dev/null +++ b/gitops.config.ts @@ -0,0 +1,27 @@ +import type {CreateGitopsConfig} from '@fuzdev/fuz_gitops/gitops_config.js'; + +const config: CreateGitopsConfig = () => { + return { + repos: [ + 'https://github.com/fuzdev/fuz_util', + 'https://github.com/fuzdev/gro', + 'https://github.com/fuzdev/fuz_css', + 'https://github.com/fuzdev/fuz_ui', + 'https://github.com/fuzdev/fuz_app', + 'https://github.com/fuzdev/fuz_template', + 'https://github.com/fuzdev/fuz_blog', + 'https://github.com/fuzdev/fuz_mastodon', + 'https://github.com/fuzdev/fuz_code', + 'https://github.com/fuzdev/fuz_gitops', + 'https://github.com/fuzdev/zzz', + 'https://github.com/fuzdev/fuz_docs', + 'https://github.com/fuzdev/tsv.dev', + { + repo_url: 'https://github.com/fuzdev/fuz.dev', + branch: 'main', + }, + ], + }; +}; + +export default config; diff --git a/package-lock.json b/package-lock.json index 6f34ab5..a9eb30e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "devDependencies": { "@fuzdev/fuz_code": "^0.45.1", "@fuzdev/fuz_css": "^0.53.0", + "@fuzdev/fuz_gitops": "^0.67.0", "@fuzdev/fuz_ui": "^0.185.1", "@fuzdev/fuz_util": "^0.52.0", "@fuzdev/gro": "^0.195.0", @@ -782,6 +783,28 @@ } } }, + "node_modules/@fuzdev/fuz_gitops": { + "version": "0.67.0", + "resolved": "https://registry.npmjs.org/@fuzdev/fuz_gitops/-/fuz_gitops-0.67.0.tgz", + "integrity": "sha512-wbaBaQsDHzO9zBt6v1m73/qa9KmPUYT22pF+LD4YutqLVy3sr8/0WmRMNE98wop6xXPXWcUZ5OXUYF+XoNoc4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.15" + }, + "funding": { + "url": "https://www.ryanatkn.com/funding" + }, + "peerDependencies": { + "@fuzdev/fuz_css": ">=0.53.0", + "@fuzdev/fuz_ui": ">=0.184.0", + "@fuzdev/fuz_util": ">=0.52.0", + "@fuzdev/gro": ">=0.195.0", + "@sveltejs/kit": "^2", + "svelte": "^5", + "zod": "^4.1.13" + } + }, "node_modules/@fuzdev/fuz_ui": { "version": "0.185.1", "resolved": "https://registry.npmjs.org/@fuzdev/fuz_ui/-/fuz_ui-0.185.1.tgz", diff --git a/package.json b/package.json index c216e8c..1f0e59d 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "devDependencies": { "@fuzdev/fuz_code": "^0.45.1", "@fuzdev/fuz_css": "^0.53.0", + "@fuzdev/fuz_gitops": "^0.67.0", "@fuzdev/fuz_ui": "^0.185.1", "@fuzdev/fuz_util": "^0.52.0", "@fuzdev/gro": "^0.195.0", diff --git a/src/lib/gitops_analyze.task.ts b/src/lib/gitops_analyze.task.ts new file mode 100644 index 0000000..0a7200b --- /dev/null +++ b/src/lib/gitops_analyze.task.ts @@ -0,0 +1 @@ +export * from '@fuzdev/fuz_gitops/gitops_analyze.task.js'; diff --git a/src/lib/gitops_plan.task.ts b/src/lib/gitops_plan.task.ts new file mode 100644 index 0000000..04dd7da --- /dev/null +++ b/src/lib/gitops_plan.task.ts @@ -0,0 +1 @@ +export * from '@fuzdev/fuz_gitops/gitops_plan.task.js'; diff --git a/src/lib/gitops_publish.task.ts b/src/lib/gitops_publish.task.ts new file mode 100644 index 0000000..f016bed --- /dev/null +++ b/src/lib/gitops_publish.task.ts @@ -0,0 +1 @@ +export * from '@fuzdev/fuz_gitops/gitops_publish.task.js'; diff --git a/src/lib/gitops_run.task.ts b/src/lib/gitops_run.task.ts new file mode 100644 index 0000000..29c0428 --- /dev/null +++ b/src/lib/gitops_run.task.ts @@ -0,0 +1 @@ +export * from '@fuzdev/fuz_gitops/gitops_run.task.js'; diff --git a/src/lib/gitops_sync.task.ts b/src/lib/gitops_sync.task.ts new file mode 100644 index 0000000..59a63af --- /dev/null +++ b/src/lib/gitops_sync.task.ts @@ -0,0 +1 @@ +export * from '@fuzdev/fuz_gitops/gitops_sync.task.js'; diff --git a/src/lib/gitops_validate.task.ts b/src/lib/gitops_validate.task.ts new file mode 100644 index 0000000..1ecd757 --- /dev/null +++ b/src/lib/gitops_validate.task.ts @@ -0,0 +1 @@ +export * from '@fuzdev/fuz_gitops/gitops_validate.task.js'; diff --git a/src/routes/fuz.css b/src/routes/fuz.css index 7b27fc5..0fe1955 100644 --- a/src/routes/fuz.css +++ b/src/routes/fuz.css @@ -940,6 +940,30 @@ body { margin-bottom: var(--space_sm); } +:where(table) { + border-collapse: collapse; +} + +:where(thead) { + text-align: left; +} + +:where(th) { + font-weight: bold; +} + +:where(th, td) { + padding: var(--space_xs3) var(--space_sm); +} + +:where(tr) { + border-bottom: 1px solid var(--border_color_10); +} + +:where(tr:hover) { + background-color: var(--fg_10); +} + /* Utility Classes */ .box { @@ -954,6 +978,12 @@ body { flex-direction: row; align-items: center; } +.ellipsis { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} .selectable { --button_fill: color-mix(in hsl, var(--shade_50) 8%, transparent); --button_fill_hover: color-mix(in hsl, var(--shade_50) 16%, transparent); @@ -1116,6 +1146,9 @@ a.chip { color: var(--color_j_50); background-color: var(--color_j_10); } +.font_family_mono { + font-family: var(--font_family_mono); +} .font_size_md { font-size: var(--font_size_md); --font_size: var(--font_size_md); @@ -1219,6 +1252,9 @@ a.chip { .p_sm { padding: var(--space_sm); } +.p_md { + padding: var(--space_md); +} .p_lg { padding: var(--space_lg); } @@ -1268,9 +1304,18 @@ a.chip { .mb_xl3 { margin-bottom: var(--space_xl3); } +.mb_xl5 { + margin-bottom: var(--space_xl5); +} +.mb_xl7 { + margin-bottom: var(--space_xl7); +} .mb_xl9 { margin-bottom: var(--space_xl9); } +.gap_xs2 { + gap: var(--space_xs2); +} .align-items\:center { align-items: center; } @@ -1289,6 +1334,12 @@ a.chip { .height\:100\% { height: 100%; } +.position\:relative { + position: relative; +} +.text-align\:center { + text-align: center; +} .width\:100\% { width: 100%; } diff --git a/src/routes/library.json b/src/routes/library.json index b0e30dc..cfcc107 100644 --- a/src/routes/library.json +++ b/src/routes/library.json @@ -35,6 +35,7 @@ "devDependencies": { "@fuzdev/fuz_code": "^0.45.1", "@fuzdev/fuz_css": "^0.53.0", + "@fuzdev/fuz_gitops": "^0.67.0", "@fuzdev/fuz_ui": "^0.185.1", "@fuzdev/fuz_util": "^0.52.0", "@fuzdev/gro": "^0.195.0", @@ -82,6 +83,44 @@ "source_json": { "name": "fuz.dev", "version": "0.0.1", - "modules": [] + "modules": [ + { + "path": "gitops_analyze.task.ts", + "declarations": [] + }, + { + "path": "gitops_plan.task.ts", + "declarations": [] + }, + { + "path": "gitops_publish.task.ts", + "declarations": [] + }, + { + "path": "gitops_run.task.ts", + "declarations": [ + { + "name": "Args", + "kind": "type", + "source_line": 2, + "type_signature": "ZodObject<{ command: ZodString; config: ZodDefault; concurrency: ZodDefault; format: ZodDefault>; }, $strict>" + }, + { + "name": "task", + "kind": "variable", + "source_line": 2, + "type_signature": "Task<{ command: string; config: string; concurrency: number; format: \"json\" | \"text\"; }, ZodType>, unknown>" + } + ] + }, + { + "path": "gitops_sync.task.ts", + "declarations": [] + }, + { + "path": "gitops_validate.task.ts", + "declarations": [] + } + ] } } diff --git a/src/routes/modules/+layout.svelte b/src/routes/modules/+layout.svelte new file mode 100644 index 0000000..5d33419 --- /dev/null +++ b/src/routes/modules/+layout.svelte @@ -0,0 +1,29 @@ + + +
+ {@render children()} +
diff --git a/src/routes/modules/+page.svelte b/src/routes/modules/+page.svelte new file mode 100644 index 0000000..6a12153 --- /dev/null +++ b/src/routes/modules/+page.svelte @@ -0,0 +1,8 @@ + + + diff --git a/src/routes/pull_requests/+layout.svelte b/src/routes/pull_requests/+layout.svelte new file mode 100644 index 0000000..5d33419 --- /dev/null +++ b/src/routes/pull_requests/+layout.svelte @@ -0,0 +1,29 @@ + + +
+ {@render children()} +
diff --git a/src/routes/pull_requests/+page.svelte b/src/routes/pull_requests/+page.svelte new file mode 100644 index 0000000..b906d2d --- /dev/null +++ b/src/routes/pull_requests/+page.svelte @@ -0,0 +1,13 @@ + + + + pull.user.login === 'ryanatkn'} +/> diff --git a/src/routes/repos.ts b/src/routes/repos.ts new file mode 100644 index 0000000..6afa577 --- /dev/null +++ b/src/routes/repos.ts @@ -0,0 +1,7 @@ +// generated by gitops_sync.task.js - do not edit + +import type {RepoJson} from '@fuzdev/fuz_gitops/repo.svelte.js'; + +import json from './repos.json' with {type: 'json'}; + +export const repos_json: Array = json as unknown as Array; diff --git a/src/routes/table/+layout.svelte b/src/routes/table/+layout.svelte new file mode 100644 index 0000000..5d33419 --- /dev/null +++ b/src/routes/table/+layout.svelte @@ -0,0 +1,29 @@ + + +
+ {@render children()} +
diff --git a/src/routes/table/+page.svelte b/src/routes/table/+page.svelte new file mode 100644 index 0000000..9c65b2c --- /dev/null +++ b/src/routes/table/+page.svelte @@ -0,0 +1,8 @@ + + + diff --git a/src/routes/tree/+layout.svelte b/src/routes/tree/+layout.svelte new file mode 100644 index 0000000..5d33419 --- /dev/null +++ b/src/routes/tree/+layout.svelte @@ -0,0 +1,29 @@ + + +
+ {@render children()} +
diff --git a/src/routes/tree/+page.svelte b/src/routes/tree/+page.svelte new file mode 100644 index 0000000..e1977dc --- /dev/null +++ b/src/routes/tree/+page.svelte @@ -0,0 +1,12 @@ + + + + tree {repo.library.package_json.glyph} {repo.library.repo_name} + + + diff --git a/src/routes/tree/[slug]/+page.svelte b/src/routes/tree/[slug]/+page.svelte new file mode 100644 index 0000000..c0c51d6 --- /dev/null +++ b/src/routes/tree/[slug]/+page.svelte @@ -0,0 +1,16 @@ + + + + {slug} - tree {repo.library.package_json.glyph} {repo.library.package_json.name} + + + diff --git a/src/routes/tree/[slug]/+page.ts b/src/routes/tree/[slug]/+page.ts new file mode 100644 index 0000000..c341a17 --- /dev/null +++ b/src/routes/tree/[slug]/+page.ts @@ -0,0 +1,13 @@ +import type {EntryGenerator} from './$types.js'; +import {Repo, repos_parse} from '@fuzdev/fuz_gitops/repo.svelte.js'; + +import {repos_json} from '$routes/repos.ts'; + +const parsed = repos_parse( + repos_json.map((r) => new Repo(r)), + 'https://www.fuz.dev/', +); + +export const entries: EntryGenerator = () => { + return parsed.repos.map((d) => ({slug: d.library.repo_name})); +};