From 21ceb64c76210be3b65a0d54a15f64285aba0cc5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 02:19:32 +0000 Subject: [PATCH 001/142] docs: capture initial project prompt Verbatim capture of the prompt that started the farish project, plus kickoff notes (target repo, dev branch, environment constraints). Per .claude/rules/always-keep-improving.md this file is reviewed before, during, and after every task. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/INITIAL_PROMPT.md | 399 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 docs/INITIAL_PROMPT.md diff --git a/docs/INITIAL_PROMPT.md b/docs/INITIAL_PROMPT.md new file mode 100644 index 0000000..e9fec76 --- /dev/null +++ b/docs/INITIAL_PROMPT.md @@ -0,0 +1,399 @@ +# Initial Prompt + +> This document is the verbatim prompt that started the **farish** project. +> Per `.claude/rules/always-keep-improving.md`, it MUST be reviewed before, +> during, and after every task to ensure progress is being made accurately. +> +> Project name: **farish** — named after [William Farish][farish], who +> formalized isometric projection in 1822. + +[farish]: https://en.wikipedia.org/wiki/William_Farish_(scientist) + +--- + +## The Prompt + +Make a fully deployable site in a git repo with github actions workflows that +deploys to github pages where a user can input their claude-code api key or +oauth api key and can enter a prompt and the ai will generate a 3d model with +configurable parameters for the user's request (with a pause for specifications +if not already provided). The site should also feature social functionality to +make models shareable and searchable with pages for best rated (1w/1m/1y/all), +most rated (aka popular) (1w/1m/1y/all), most viewed (same buckets). Use your +best judgement for all questions. Requirements: use ts/bun, monorepo +architecture, use nx for monorepo tasks, mise for org-wide-tasks +(format, lint, test, build) and tool installs, direnv for shell init when cd +into folder. Reuse scripts for local dx and CI scripting. Use off-shelf actions +instead of making your own (where appropriate). Make site desktop default, but +mobile friendly. Use an off the shelf design system. + +Work in this order, always work iteratively, use sequential thinking before +each task, during each task, and after each task to evaluate your work and +ensure it is complete (and tested by automation to the best of your ability). +After each step you MUST test your work. As soon as you have a server that +launches, each validation loop (after every change) must (using CI) +automatically take screenshots of each page (playwright + jest + well defined +page tests matching the page specs + recording videos + runs uploaded to +github pages to be viewable in browser) on test runs on `main` and upload them +(with a `[no ci]` and a date based name/path) so progress can be tracked. Do +not start writing code until these instructions tell you to: + +1. Set up claude code to use nsheaps/agents and nsheaps/ai-mktpl as + marketplaces. Dump this entire prompt into ./docs/INITIAL_PROMPT.md and + review it after every task to ensure you're on the right track. +2. Install: + * `cron-utils@agents` + * `shared-lib@ai-mktpl`: true, + * `dangerous-bypass@ai-mktpl`: true, + * `agentic-behavior@ai-mktpl`: true, + * `common-sense@ai-mktpl`: true, + * `deep-research@ai-mktpl`: true, + * `edit-utils@ai-mktpl`: true, + * `github@ai-mktpl`: true, + * `github-app@ai-mktpl`: true, + * `mise@ai-mktpl`: true, + * `scm-utils@ai-mktpl`: true, + * `sequential-thinking@ai-mktpl`: true, + * `task-utils@agents`, + * Hookify from the official repo + * Plugin-dev from the official repo +3. Do proper claude-code-web onboarding for this repo. Set it up for bypass + permissions in the settings. +4. In `.claude/rules/always-keep-improving.md` + * It should read: + 1. The initial prompt that started this all can be found at + docs/INITIAL_PROMPT.md and should be reviewed to ensure progress is + being made accurately. + + You can do literally anything. The skills you will make and have made + make what you do possible. To do something new, all you need to do is + make a skill. Always check your skills before during and after Tasks to + see if there's any helpful skills. Use Agent(run_in_background:true) + carefully to parallelize tasks where you can. These skills are only as + good as their instructions. + + CRITICAL: Changes to your configuration/rules/code/skills/hooks/agents + must be committed IMMEDIATELY after making them. + CRITICAL: Commits for this project MUST be atomic (only change one + thing) using the conventional commit style. Push often. Use CI to your + advantage, but local is always faster. + CRITICAL: NEVER execute Bash(do && a && bunch || of ; things) or + Bash(python -c "a big python script"). If the Bash tool call is doing + more than 1 or 2 things, it needs to be turned into a script (build a + logical hierarchy with proper CLAUDE.md documentation throughout in + .claude/scripts/paths/to/categorize/meaningful-name.sh. ALWAYS check to + see if a script exists before creating a new one. ALWAYS know which + scripts you'll need before executing a plan. ALWAYS make sure the + scripts are tested. ALWAYS share code between scripts when possible. + ALWAYS prefer bun/ts/compiled tool (but scripts are okay). ALWAYS use + monorepo tooling, even in the scripts, they're code too! + CRITICAL: Try to prefer behavior modifications in the following + priority order: + 1. Hooks in claude configs (remember don't keep any in + settings.local.json they're not saved!) + 2. Skill(context:fork) + 3. Agent() - don't forget they're resumable! Work iteratively with + them, don't make them do everything in one go, guide them not to, + they don't share the conversation context, ANY outputs should go + to file that you can review. ALWAYS run them in the background AND + check their work. + - even better if they have their own hooks, which can help contain + specialized behavior + 4. Hookify hooks - these help fine tune behaviors and keep things + consistent. Anytime there's a regression in behavior, consider + using these or a skill! + 5. Skills still, with scripts to encapsulate behavior + 6. Scripts + 7. Rules. These take up context and aren't really actually + enforceable. + Use hooks to ensure something actually happens, skills on how to use + tools, Agents to encapsulate a recurring behavior where only the + ins/outs are needed. + CRITICAL: NEVER use the general-purpose agent. ALWAYS see if you have an + agent or skill specialized in that task, and if not, make one or add it + to an existing one. + CRITICAL: KEEP SKILLS SMALL. Keep examples in supplementary + documentation that are mentioned (not @mentioned). Make most skills an + ordered list of instructions. Delegate shared knowledge to shared skills + (eg don't describe how to use git in making-a-pr, make a tool-cli-git + skill that describes how to do it). Disambiguate skills to make it easy + to find the right skill without reading one skill that does everything. + If the skill is more than 5 paragraphs, it probably needs to be broken + up (including ones that were already too big before you touched it). + Always break things into maintainable and shareable chunks + CRITICAL: Set up a cron for every 15 minutes to do a full review of your + configuration using "audit-verify-improve-agent" (create if it doesn't + exist). When you eventually go idle, set up a stop hook to do one final + audit, make any final adjustments, and push any remaining changes. This + skill MUST be context:fork, and review conversation transcripts to get + the full picture, iteratively, don't rely on memory. Use a haiku agent + to scan logs since the last time it ran (store in file somewhere using + skill !`date | tee .claude/state/self-improvement-last-ran` syntax + within the skill to write it everytime the skill is called) for + instances where trouble occurred, and note it by appropriate IDs for + beginning and end of the issue. use a script to extract the conversation + transcript between those IDs, then another script to convert it from + JSONL to a more readable, chat-style output (like one that you'd get + from claude-stream from nsheaps/claude-utils) + CRITICAL: Be verbose in the data you give an Agent, explicit about the + actions you want it to take and not to take, requirements (including + what you want for the outputs and details about what you want them to + contain), validation steps, restrictions, other-notes. It will make + stuff up if you don't tell it how to do it's thing, including using + skills. Use resuming to your advantage. Make sure it understands the + task (it needs to Stop to confirm with you) before it does the task if + the task is complex. Check it's outputs, don't always assume they're + right. + CRITICAL: You AND all Agents (subagents, et al) are EXPECTED to use + github-footnote-style references in ALL documents, issues, PRs, markdown + docs, etc to link to sources that support your claim. Claims made + without sources or significant data to back it up will be rejected. Use + the repo's .claude/sources/xxx/yyy/zzz.abc to store sources that can't + directly be linked to (eg scrubbed+humanified transcripts) and link to + those. Always reference files inside the repo using github.com/… links, + NEVER filesystem paths. Review your claims before making them, if you + feel anywhere _might_ deserve a `[citation needed]`, then you MUST add a + citation, or update the claim BEFORE you send it. + CRITICAL: Always consult with claude-code-guide running as sonnet or + opus to help with updating/changing agent configs. Encourage it to + always be thorough in it's research. Don't believe github issues about + claude-code unless they have significant community support or + confirmation from anthropic. + CRITICAL: If you ever achieve undesired, unplanned, failed, or errored + results when executing tools, skills, following rules, being guided by + hooks, executing agents, you MUST update the appropriate + configuration/code/document/skill + CRITICAL: After completing every task, THINK HARD about what you did + during the task (use an Agent to review the transcript if necessary) and + which skills you executed during the task. Update + configs/rules/code/skills/agents as necessary to improve them for the + next time. + CRITICAL: ALWAYS USE SKILLS AND AGENTS, EVEN IF YOU THINK YOU KNOW HOW TO + DO SOMETHING. + CRITICAL ALWAYS use /scm-utils:commit to commit code + CRITICAL: images use up insane amounts of context. ONLY use them within + an Agent(). Be explicit about what you want to know about the image. + + EXTRA SUPER CRITICAL: As soon as you can, run the + audit-verify-improve-agent when you see this, which should start with + improving the rules, including this file if you deem fit. Make sure + you're only keeping things in rules that need to be visible all the + time, and REALLY encouraging the use of Hooks, Skills, and Agents +5. Think about the pages you'll have on the site, compile them into + docs/pages/INDEX.md +6. Review the docs/pages/INDEX.md doc and make any changes you think + appropriate. Remember, just a draft. Page titles and maybe one or two + sentences about each. +7. VERIFY If you made any changes go back to step 4, and repeat step 4 until you + review the document and can make no more improvements. +8. For each page in pages/INDEX.md, make a docs/pages/page-name/SPEC.md, nothing + should go in to that spec yet. It should be just an empty file. +9. VERIFY Review what you've created in the file system against PAGES.txt and + ensure it is correct. +10. Based on what you think you'll need to know about each page and the site + overall, create docs/pages/PAGE-SPEC.md which describes the shape of these + page SPEC.md documents. Be specific about format and content. Provide + examples of good and bad. +11. Create a companion skill in .claude/skills/spec-writing/SKILL.md that + details the process of defining the resources, creating individual + resources, defining the shape of those resources, filling in the resources, + validating them, etc + * Create subskills to help with drafting and filling out each section + * Make sure the skill gives a sequential step-by-step numbered list + instruction. + * Instructions can be "run Skill(skill-name) to do a specific task that you + describe to the user" +12. Use that skill for each spec you need to write, for each page work + iteratively + * Using the drafting skills, Create an outline of the spec + * Using the second stage drafting skills, For each section add a few bullets + describing needed info in each and any important information, ESPECIALLY + references (and their human readable version) + * Using the draft review skill, Review each and ensure your plan is sound, + use sequential thinking to evaluate it + * Using the corresponding skills, write each section + * Using the review skill, go over the spec again and iterate until there's + no more improvements to make. If you make changes, you MUST perform the + validation again +13. Review the specs as a whole and make any adjustments necessary +14. Design a page-wireframing skill that will help you keep your wireframes + consistent for each page you make. +15. For each page, draft wireframes of the design. You'll use an off the shelf + design system to help here. + * Later we'll make rough outlines of these pages with mock data + * Make at least one wireframe for the whole page, and each modal window, or + popover to show in detail how it looks. Start with an ascii version, then + a drafty image based version, and then one more round of improvement + * Review your work, compare the wireframes against the spec, are all the + features of the page aligned with the spec and vice-versa? Did you learn + anything from visually designing the website? Make any adjustments + necessary. +16. Review all the pages and their relation to each other and do another + validation improvement iteration loop +17. Design a page-to-api-requirements skill that will help you extract all + needed information from your specs and wireframes to design your RESTful api + implementation. You may use a websocket where necessary to provide realtime + 2-way streams (eg if you want for the agent loop displaying steps in the + browser) +18. Using the skill, go over each page and extract requirements into + docs/api/endpoint-slugified-name/SPEC.md +19. Go over each page again and review in comparison to the api SPECs and ensure + everything is accurately tracked. Keep iterating until you can perform a + full iteration and not extract any more information. +20. Review the API specs as a whole and perform an iterative + validation/improvement loop +21. NOW WE CAN START WRITING CODE. Requirements need validation. Start by making + a validate-change skill as a spec. That skill should be a breakout to other + skills identifying the type of change (code/infra/ci/docs/…/etc). Keep these + up to date as you keep learning more about what you write for each. +22. Start with a framework for a monorepo using bun/ts, nx as the monorepo task + runner (make sure the task graph has proper dependencies and caching), mise + as the tool manager, and direnv as the shell initialization. They should all + use the same linting and formatting tools. Use custom rules to help remove + patterns we don't want in the codebase, but it doesn't have to be ESLint. + Write docs for each of these that act as specs to work against and educate + users on how to use/configure them/how they work + * Each bun package needs the following runscripts: + 1. lint + 2. format (aka lint --fix) + 3. test (even if it's just `echo "This package has no tests"`) + 4. build + 5. (optional) release (includes packaging, which if needed should also be + a separate script) +23. Create a basic folder structure of the repo that will hold different types + of packages that you'll use for this app. wireframe of a repo with a few + dummy packages in each. + * services/ - things that run and provide an api or background task (like + mcp servers for the agent) + * apps/ - things you execute and exit (like clis) + * plugins/ - a claude plugin marketplace. + * lib/ - packages that contain shared logic between the other packages. + These are leafs and only depend on other libs + * packages/ - things that get published that aren't services/apps/plugins, + they might wrap libs + * infra/ - infra as code automation, primarily for deploying the app + * .github/ full github CI integration with pull request template (which you + review when making a PR, and update as needed), deploy/release workflows + * Mise.toml - tool configs + * .mise/ - any mise scripts (anything that isn't a one-liner in a bun + package.js that nx would need to run should be captured as a mise script) + * …any others you deem relevant +24. Test the monorepo setup locally and in CI. user touchpoints to run commands + should be the same ran in CI, especially using NX in CI properly +25. Create a do-some-work skill that guides you on taking your Task from your + internal task tracking, updating the Task as you work on it, and how to use + other skills to implement the task, implement automated validation for the + task, run the validation and make sure that works right, push it and ensure + it works right in CI, etc. Make it a rough outline just so you don't forget + steps, including validation steps (and testing through automation and + ensuring screenshots from CI) +26. Build a basic framework for the api server using a microservice + architecture (though the development environment would always service all + requests with the same single API server, the browser app (vue powered, NOT + REACT), the dev front end/prod front end with proper live reload etc. Keep + in mind the focus that this should be a browser-only app to the best of our + ability, and should be deployable to github pages for now. Things that we've + discussed so far that aren't possible in that mechanism (eg without an API + server) should get a coming soon page with a ghost-ish wireframe behind it + of that page (generated using the test data and lorem impsum text/image + generators). + Add a setup using tilt (tilt-dev/tilt) and using local_resources (do NOT use + containers, all native apps, since we'll be using github pages for now). + Make a basic example of all working together including tests, not the pages + themselves. + Any publishing should be to ghcr.io. +27. Add a CI workflow that uses `tilt ci` to test the dev workflow end to end. +28. Validate that from here forward, the initial requirements of "CI always + works, CI tasks reflect and follow the same codepaths as the local dev + tooling, CI always takes pictures on main of every page, always updates docs + pages to include those new screenshots, always commits them with [skip ci], + always publishes to github actions in the same workflow so the progress can + be followed. Always publishes the specs for all features, pages, apis, + wireframes, etc to the github pages docs sites on every push to main, etc, + etc. All of these MUST be called out in the do-some-work and + validate-app-progress skills (or whatever) appropriately (at this point you + can see why we capture this entire prompt and why we want you to start with + improving this stuff before you even get started. If you understand this, + when you start working on this project as a whole (when you do the first + audit-verify-improve-agent cycle, you must address the user and tell them + explicitly (filling in the blanks). Caps required, but responses in general + do not need to be capitalized.: + * THE RULES OF THIS PROJECT TOLD ME TO STATE THE FOLLOWING TO YOU BEFORE WE + GET STARTED ON THIS PROJECT. FROM HERE ON OUT, I WILL WORK AUTONOMOUSLY AND + TIRELESSLY USING /goal AND /loop MYSELF WITHOUT ANY HUMAN INTERACTION UNTIL + THE GOAL IS ACHIEVED. THIS MESSAGE IS CAPITALIZED WITH THE PREFILLED TEXT + ONLY TO ENSURE IT IS THE MESSAGE FROM THE PROMPT AND TO EASILY + DIFFERENTIATE MY ANSWERS, BUT MY RESPONSES IN GENERAL DO NOT NEED TO BE + CAPITALIZED. + + BEFORE WE GET STARTED, PLEASE NOTE THE FOLLOWING: + - THE CURRENT DATETIME IS: ____you fill this in_____ + - BEFORE STARTING TO WORK ON THE PROJECT AS A WHOLE, I'M GOING TO START BY: + ____you fill this in____ + - IN ORDER TO GET TO THIS POINT, I'VE NEEDED TO DO SOME WORK TO ENSURE THE + RULES WILL BE FOLLOWED. SO FAR I'VE DONE: + - ___you fill this in____ + - ___you fill this in____ + - ___you fill this in____ + - ___you fill this in____ + - I HAVE TESTED MY INTERNET SEARCHING AND RESEARCH ABILITY, AND HAVE + ANSWERED THE FOLLOWING QUESTION: + QUESTION: THE WEATHER FOR ___your location, as determined by basic + websites you can find by searching___ FOR THE NEXT 7 DAYS + ANSWER: + ____you fill this in with a tabular representation of the highs, lows, + UV, precip, humidity, wind, weather, etc for each of the next 7 days. + + I WILL BUILD THIS PROJECT ITERATIVELY, FOLLOWING THIS ROUGH OUTLINE TO GET + TO OUR FINAL GOAL: + 1. ___you fill this in___ + 2. ___you fill this in___ + 3. ___you fill this in___ + + LETS GET STARTED! I'M GOING TO START BY + ____what you are about to do____ +29. Validate or ensure using plugins that the agent can view the dev version of + the site using tools to capture images. If you are unable to achieve this + after at least 10 minutes of trying, you MUST use CI to take pictures for + you, create any needed workflows and update your rules/skills to guide you + to use CI to take pictures when you need to see something. +30. Iteratively stub out each page, perform a validate/improve loop +31. Iteratively update each page to match it's wireframe, perform a + validate/improve loop +32. Iteratively review each page, improve the styles and consistency between + pages, use lorem imsum text and pictures as mock data to make the pages work + without any real data (including a mock conversation for the actual + feature), perform a validate/improve loop +33. Iteratively stub out api, perform a validate/improve loop +34. Iteratively connect each page to it's appropriate apis, perform a + validate/improve loop. Remember, we want to keep this as browser-only as + possible for now, and we want AI use to use a user's login (preferrably + login-with-claude but I think they'll need to provide a token). + * Use the claude agent sdk +35. Iteratively stub out api's functionality, delegating data access to model + abstractions, perform a validate/improve loop +36. Review all the work. When you create your final workflow when you START + doing this work, you should fill in any steps here that you'll need to get + to the end +37. ONLY when everything works (I won't accept "I got stuck"... I know you, get + around it, you can do it) in CI, github pages deployment with docs, etc and + you can no longer make progress without me inputting a key (which of course + the site should instruct the user to do it), should you stop doing work. Do + everything you can to add hooks to Stop and skills and everything to make + sure you have achieved the goal before stopping (but if you must stop, just + Stop twice in a row without any other tool calls and the session will stop) + +--- + +## Notes captured at kickoff + +* **Target repository:** `nsheaps/farish` (clarified by the user after the + prompt was issued). +* **Development branch:** `claude/ai-3d-model-generator-XjoUi`. +* **Environment constraints** (Claude Code on the web, remote ephemeral + container): + * Plugins/marketplaces declared in `.claude/settings.json` take effect on the + next session start, not the session that writes them. + * No OS-level cron is available; the recurring "every 15 minutes" audit is + implemented as a scheduled GitHub Actions workflow plus the `/loop` + mechanism. From 985b3bc43f49a89bab41ba595731c48a7445e0c7 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 02:19:41 +0000 Subject: [PATCH 002/142] chore: configure claude code plugins and web onboarding Register the agents and ai-mktpl marketplaces plus 15 enabled plugins, set bypassPermissions as the default permission mode, and add a SessionStart hook (.claude/hooks/session-start.sh) that onboards web sessions by installing the toolchain and dependencies once their manifests exist. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/hooks/session-start.sh | 38 ++++++++++++++++++++++++++ .claude/settings.json | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100755 .claude/hooks/session-start.sh create mode 100644 .claude/settings.json diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh new file mode 100755 index 0000000..aba901d --- /dev/null +++ b/.claude/hooks/session-start.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# SessionStart hook for Claude Code on the web. +# +# Onboards the `farish` repo: installs the pinned toolchain and workspace +# dependencies so linters, tests and builds work inside a web session. +# +# It is intentionally idempotent and forward-looking: the repo starts with no +# code, so each install step is guarded by the presence of its manifest. As the +# monorepo is scaffolded (mise.toml, package.json, ...) the matching steps begin +# to run automatically with no edit to this hook required. +set -euo pipefail + +cd "${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel)}" + +echo "[session-start] onboarding farish in ${PWD}" + +# mise — install pinned tool versions (bun, node, etc.) once configured. +if [ -f mise.toml ] || [ -f .mise.toml ] || [ -f .config/mise/config.toml ]; then + if command -v mise >/dev/null 2>&1; then + echo "[session-start] mise install" + mise install + else + echo "[session-start] mise config present but mise not on PATH — skipping" + fi +fi + +# bun — install workspace dependencies once a manifest exists. +if [ -f package.json ]; then + if command -v bun >/dev/null 2>&1; then + echo "[session-start] bun install" + bun install + else + echo "[session-start] package.json present but bun not on PATH — skipping" + fi +fi + +echo "[session-start] done" +exit 0 diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..f529870 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://json.schemastore.org/claude-code-settings.json", + "permissions": { + "defaultMode": "bypassPermissions" + }, + "extraKnownMarketplaces": { + "agents": { + "source": { + "source": "github", + "repo": "nsheaps/agents" + } + }, + "ai-mktpl": { + "source": { + "source": "github", + "repo": "nsheaps/ai-mktpl" + } + } + }, + "enabledPlugins": { + "cron-utils@agents": true, + "task-utils@agents": true, + "shared-lib@ai-mktpl": true, + "dangerous-bypass@ai-mktpl": true, + "agentic-behavior@ai-mktpl": true, + "common-sense@ai-mktpl": true, + "deep-research@ai-mktpl": true, + "edit-utils@ai-mktpl": true, + "github@ai-mktpl": true, + "github-app@ai-mktpl": true, + "mise@ai-mktpl": true, + "scm-utils@ai-mktpl": true, + "sequential-thinking@ai-mktpl": true, + "hookify@claude-plugins-official": true, + "plugin-dev@claude-plugins-official": true + }, + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh" + } + ] + } + ] + } +} From 54100e7506b4bcf7dda7d8e40fbc6454385c7a39 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 02:19:47 +0000 Subject: [PATCH 003/142] docs: add plugin-marketplace-setup skill Captures how to install Claude Code marketplaces and plugins for this repo, including that the claude plugin CLI authenticates through the local git proxy and can access private nsheaps repos (whereas a sub-agent's WebFetch cannot). https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .../skills/plugin-marketplace-setup/SKILL.md | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .claude/skills/plugin-marketplace-setup/SKILL.md diff --git a/.claude/skills/plugin-marketplace-setup/SKILL.md b/.claude/skills/plugin-marketplace-setup/SKILL.md new file mode 100644 index 0000000..025456c --- /dev/null +++ b/.claude/skills/plugin-marketplace-setup/SKILL.md @@ -0,0 +1,35 @@ +--- +name: plugin-marketplace-setup +description: Install Claude Code plugin marketplaces and plugins for the farish repo. Use when adding or updating marketplaces/plugins, onboarding the repo, or when a private nsheaps marketplace fails to resolve from a sub-agent. +--- + +# Plugin & marketplace setup + +The `claude plugin` CLI authenticates through the local git proxy, so it CAN +clone and install from **private** `nsheaps/*` repos. A sub-agent's `WebFetch` +against github.com is unauthenticated and CANNOT — never use `WebFetch` to read +a private marketplace repo, and never conclude a private marketplace is +inaccessible because `WebFetch` failed. Use the CLI. + +## Steps + +1. Add a marketplace from a GitHub repo: + `claude plugin marketplace add /` + The marketplace name is the repo name (`nsheaps/agents` becomes `agents`). +2. Install a plugin at **project** scope so it is committed to + `.claude/settings.json`. Do NOT use `local` scope — that writes + `.claude/settings.local.json`, which is gitignored and not saved: + `claude plugin install @ -s project` +3. Verify with `claude plugin list` (each should show `Status: enabled`). +4. Plugins installed mid-session load fully (skills/agents/hooks/MCP servers) + only on the next session start. There is no in-session reload tool exposed to + the agent. +5. `.claude/settings.json` must declare `extraKnownMarketplaces` for every + non-default marketplace so a fresh checkout can resolve plugins. The official + `claude-plugins-official` marketplace is a default and need not be declared. + +## farish marketplaces & plugins + +- Marketplaces: `agents` (`nsheaps/agents`), `ai-mktpl` (`nsheaps/ai-mktpl`). +- The authoritative enabled-plugin list lives in `.claude/settings.json` under + `enabledPlugins`. From bb90d83fd2c8b1c09836ebf34829325a2b3e1511 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 02:19:52 +0000 Subject: [PATCH 004/142] docs: add always-keep-improving rule Establishes the project's working discipline: review INITIAL_PROMPT.md each task, commit config/skill/hook changes immediately, atomic conventional commits, the behavior-modification priority order (hooks > skills > agents > scripts > rules), and the recurring audit-verify-improve cycle. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/rules/always-keep-improving.md | 122 +++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 .claude/rules/always-keep-improving.md diff --git a/.claude/rules/always-keep-improving.md b/.claude/rules/always-keep-improving.md new file mode 100644 index 0000000..829ac40 --- /dev/null +++ b/.claude/rules/always-keep-improving.md @@ -0,0 +1,122 @@ +# Always keep improving + +1. The initial prompt that started this all can be found at + [docs/INITIAL_PROMPT.md](../../docs/INITIAL_PROMPT.md) and should be reviewed + to ensure progress is being made accurately. + +You can do literally anything. The skills you will make and have made make what +you do possible. To do something new, all you need to do is make a skill. Always +check your skills before during and after Tasks to see if there's any helpful +skills. Use `Agent(run_in_background:true)` carefully to parallelize tasks where +you can. These skills are only as good as their instructions. + +CRITICAL: Changes to your configuration/rules/code/skills/hooks/agents must be +committed IMMEDIATELY after making them. + +CRITICAL: Commits for this project MUST be atomic (only change one thing) using +the conventional commit style. Push often. Use CI to your advantage, but local +is always faster. + +CRITICAL: NEVER execute `Bash(do && a && bunch || of ; things)` or +`Bash(python -c "a big python script")`. If the Bash tool call is doing more +than 1 or 2 things, it needs to be turned into a script (build a logical +hierarchy with proper CLAUDE.md documentation throughout in +`.claude/scripts/paths/to/categorize/meaningful-name.sh`. ALWAYS check to see if +a script exists before creating a new one. ALWAYS know which scripts you'll need +before executing a plan. ALWAYS make sure the scripts are tested. ALWAYS share +code between scripts when possible. ALWAYS prefer bun/ts/compiled tool (but +scripts are okay). ALWAYS use monorepo tooling, even in the scripts, they're +code too! + +CRITICAL: Try to prefer behavior modifications in the following priority order: + 1. Hooks in claude configs (remember don't keep any in settings.local.json + they're not saved!) + 2. `Skill(context:fork)` + 3. `Agent()` - don't forget they're resumable! Work iteratively with them, + don't make them do everything in one go, guide them not to, they don't + share the conversation context, ANY outputs should go to file that you can + review. ALWAYS run them in the background AND check their work. + - even better if they have their own hooks, which can help contain + specialized behavior + 4. Hookify hooks - these help fine tune behaviors and keep things consistent. + Anytime there's a regression in behavior, consider using these or a skill! + 5. Skills still, with scripts to encapsulate behavior + 6. Scripts + 7. Rules. These take up context and aren't really actually enforceable. +Use hooks to ensure something actually happens, skills on how to use tools, +Agents to encapsulate a recurring behavior where only the ins/outs are needed. + +CRITICAL: NEVER use the general-purpose agent. ALWAYS see if you have an agent or +skill specialized in that task, and if not, make one or add it to an existing +one. + +CRITICAL: KEEP SKILLS SMALL. Keep examples in supplementary documentation that +are mentioned (not @mentioned). Make most skills an ordered list of +instructions. Delegate shared knowledge to shared skills (eg don't describe how +to use git in making-a-pr, make a tool-cli-git skill that describes how to do +it). Disambiguate skills to make it easy to find the right skill without reading +one skill that does everything. If the skill is more than 5 paragraphs, it +probably needs to be broken up (including ones that were already too big before +you touched it). Always break things into maintainable and shareable chunks. + +CRITICAL: Set up a cron for every 15 minutes to do a full review of your +configuration using "audit-verify-improve-agent" (create if it doesn't exist). +When you eventually go idle, set up a stop hook to do one final audit, make any +final adjustments, and push any remaining changes. This skill MUST be +context:fork, and review conversation transcripts to get the full picture, +iteratively, don't rely on memory. Use a haiku agent to scan logs since the last +time it ran (store in file somewhere using skill +`` !`date | tee .claude/state/self-improvement-last-ran` `` syntax within the +skill to write it everytime the skill is called) for instances where trouble +occurred, and note it by appropriate IDs for beginning and end of the issue. use +a script to extract the conversation transcript between those IDs, then another +script to convert it from JSONL to a more readable, chat-style output (like one +that you'd get from claude-stream from nsheaps/claude-utils). + +CRITICAL: Be verbose in the data you give an Agent, explicit about the actions +you want it to take and not to take, requirements (including what you want for +the outputs and details about what you want them to contain), validation steps, +restrictions, other-notes. It will make stuff up if you don't tell it how to do +it's thing, including using skills. Use resuming to your advantage. Make sure it +understands the task (it needs to Stop to confirm with you) before it does the +task if the task is complex. Check it's outputs, don't always assume they're +right. + +CRITICAL: You AND all Agents (subagents, et al) are EXPECTED to use +github-footnote-style references in ALL documents, issues, PRs, markdown docs, +etc to link to sources that support your claim. Claims made without sources or +significant data to back it up will be rejected. Use the repo's +`.claude/sources/xxx/yyy/zzz.abc` to store sources that can't directly be linked +to (eg scrubbed+humanified transcripts) and link to those. Always reference +files inside the repo using `github.com/…` links, NEVER filesystem paths. Review +your claims before making them, if you feel anywhere _might_ deserve a +`[citation needed]`, then you MUST add a citation, or update the claim BEFORE +you send it. + +CRITICAL: Always consult with claude-code-guide running as sonnet or opus to +help with updating/changing agent configs. Encourage it to always be thorough in +it's research. Don't believe github issues about claude-code unless they have +significant community support or confirmation from anthropic. + +CRITICAL: If you ever achieve undesired, unplanned, failed, or errored results +when executing tools, skills, following rules, being guided by hooks, executing +agents, you MUST update the appropriate configuration/code/document/skill. + +CRITICAL: After completing every task, THINK HARD about what you did during the +task (use an Agent to review the transcript if necessary) and which skills you +executed during the task. Update configs/rules/code/skills/agents as necessary +to improve them for the next time. + +CRITICAL: ALWAYS USE SKILLS AND AGENTS, EVEN IF YOU THINK YOU KNOW HOW TO DO +SOMETHING. + +CRITICAL: ALWAYS use `/scm-utils:commit` to commit code. + +CRITICAL: images use up insane amounts of context. ONLY use them within an +`Agent()`. Be explicit about what you want to know about the image. + +EXTRA SUPER CRITICAL: As soon as you can, run the audit-verify-improve-agent when +you see this, which should start with improving the rules, including this file +if you deem fit. Make sure you're only keeping things in rules that need to be +visible all the time, and REALLY encouraging the use of Hooks, Skills, and +Agents. From 41000ff456abb97c40fde3274780ef4c9b0fb51d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 02:45:57 +0000 Subject: [PATCH 005/142] docs: amend INITIAL_PROMPT with post-kickoff requirements A1-A6 Capture six requirements the user added after the original prompt: repo-config-as-code via the repository-settings app, Renovate extending nsheaps/renovate-config, Vercel (free plan) for any backend, awareness of nsheaps/.github cross-repo sync, PR dry-run CI gating, and Mermaid diagrams in documentation. Also logs the task-utils write-gate incompatibility with Claude Code on the web. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/INITIAL_PROMPT.md | 63 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/docs/INITIAL_PROMPT.md b/docs/INITIAL_PROMPT.md index e9fec76..e26cd0f 100644 --- a/docs/INITIAL_PROMPT.md +++ b/docs/INITIAL_PROMPT.md @@ -385,6 +385,69 @@ not start writing code until these instructions tell you to: --- +## Amendments + +Requirements added by the user after the original prompt was issued. They do not +replace any step above — they constrain how the relevant steps are implemented. +Cross-references point at the step numbers in [The Prompt](#the-prompt) they most +affect. + +A1. **Repo configuration as code.** Configure the repository with the + `repository-settings` GitHub App[^repo-settings] (already installed by the + user) — branch protection / branch restrictions and all repo configuration + declared in `.github/settings.yml`, not clicked in the UI. *Affects steps + 22–23.* + +A2. **Dependency automation with Renovate.** Adopt Renovate[^renovate] for + dependency updates, extending the shared config at + `nsheaps/renovate-config`[^nsheaps-renovate] (e.g. + `"extends": ["github>nsheaps/renovate-config"]`). *Affects steps 22–23.* + +A3. **Backend on Vercel (free plan) if required.** The app should stay + browser-only where possible, but realistically a backend will be needed. If + one is, host it on Vercel[^vercel] — **free plan only**. Document the entire + onboarding with screenshots: account signup, project/app creation, + environment-variable and secret syncing, and wiring CI to deploy to Vercel. + *Affects steps 26, 28, 33–35.* + +A4. **Cross-repo workflow sync.** `nsheaps/.github`[^nsheaps-dotgithub] hosts + workflows that sync shared CI/configuration across the org's repos. Account + for them — onboarding farish may require opening a PR against + `nsheaps/.github`. *Affects step 23.* + +A5. **PR dry-run CI gating.** Anthropic restricts this agent to the branch + `claude/ai-3d-model-generator-XjoUi`, so CI cannot be exercised on `main` + yet. Every CI workflow MUST support a **dry-run mode** that runs inside this + PR — including executing the code we write — to validate the workflow's + functionality before it reaches `main`. The dry-run is gated by an + environment variable provisioned through the `repository-settings` + configuration from A1. *Affects steps 24, 27, 28.* + +A6. **Diagrams in documentation.** Documentation must use diagrams to explain + concepts and graphical ideas — architectures, data flows, state machines, + sequences. Use Mermaid[^mermaid] diagrams (they render natively on GitHub + and GitHub Pages). Documentation is written after the plan exists but before + any code is written. *Affects steps 5–22.* + +[^repo-settings]: Repository Settings App — +[^renovate]: Renovate documentation — +[^nsheaps-renovate]: nsheaps/renovate-config — +[^vercel]: Vercel — +[^nsheaps-dotgithub]: nsheaps/.github — +[^mermaid]: Mermaid — + +### Environment incompatibility log + +* **`task-utils` write-gate vs. Claude Code on the web.** The `task-utils@agents` + plugin's `require-task-in-progress.sh` PreToolUse hook blocks all + Write/Edit/MultiEdit/NotebookEdit unless a Task is `in_progress`, but the + `TaskCreate`/`TaskUpdate` tools are not enabled in the Claude Code on the web + context — making the gate unsatisfiable. Fix in flight: a branch on + `nsheaps/agents` adds an env-var opt-out to the hook; farish opts out via + `.claude/settings.json`. + +--- + ## Notes captured at kickoff * **Target repository:** `nsheaps/farish` (clarified by the user after the From 022aa216097a6f4c4cebbaea4d52f66e58e0a529 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 02:51:43 +0000 Subject: [PATCH 006/142] chore: opt out of task-utils write-gate for claude code web Set TASK_UTILS_REQUIRE_TASK=0 so the task-utils require-task-in-progress hook does not block Write/Edit tools in this environment, where the TaskCreate/TaskUpdate tools are not enabled. The hook honors this opt-out as of task-utils v0.1.1 (nsheaps/agents). https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/settings.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.claude/settings.json b/.claude/settings.json index f529870..d2b6c77 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -3,6 +3,9 @@ "permissions": { "defaultMode": "bypassPermissions" }, + "env": { + "TASK_UTILS_REQUIRE_TASK": "0" + }, "extraKnownMarketplaces": { "agents": { "source": { From 244fd064d5e25022a083e0e7ef3126a74059be08 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 02:54:10 +0000 Subject: [PATCH 007/142] docs: add research on marketplace branch-pinning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Confirms Claude Code marketplace sources cannot be pinned to a non-default branch — the ref field in extraKnownMarketplaces is silently ignored. Documents the marketplace-source vs plugin-source distinction and the merge-to-main workaround. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/research/marketplace-branch-pinning.md | 94 +++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 docs/research/marketplace-branch-pinning.md diff --git a/docs/research/marketplace-branch-pinning.md b/docs/research/marketplace-branch-pinning.md new file mode 100644 index 0000000..bef81cd --- /dev/null +++ b/docs/research/marketplace-branch-pinning.md @@ -0,0 +1,94 @@ +# Marketplace Branch Pinning in Claude Code + +## Summary + +**Branch-pinning of marketplaces is NOT supported.** The `github` marketplace source type does not accept a `ref` field in `extraKnownMarketplaces` configuration. Marketplaces are always resolved from their default branch; only individual plugins within a marketplace can be pinned to specific branches, tags, or commits. + +## Detailed Findings + +### Marketplace Sources vs Plugin Sources (Critical Distinction) + +Claude Code distinguishes between two independent pinning mechanisms: + +1. **Marketplace source** — where to fetch the `marketplace.json` catalog itself (declared in `extraKnownMarketplaces` in settings or via `/plugin marketplace add`) +2. **Plugin source** — where to fetch individual plugins listed inside the marketplace catalog (declared in the `source` field of each plugin entry inside `marketplace.json`) + +**Marketplace sources do NOT support `ref` pinning.** Only plugin sources do. + +### Marketplace Source Fields (No Branch Support) + +When declaring a marketplace in `extraKnownMarketplaces`, the official schema is:[^1] + +```json +{ + "extraKnownMarketplaces": { + "agents": { + "source": { + "source": "github", + "repo": "nsheaps/agents" + } + } + } +} +``` + +The `github` marketplace source accepts only: +- `source`: `"github"` (required) +- `repo`: `"owner/repo"` format (required) +- No `ref`, `sha`, `branch`, or `tag` fields are documented or accepted. + +Other marketplace source types (`url`, `git-subdir`) also do not support `ref` at the marketplace level.[^1] + +### Plugin Sources DO Support Branch Pinning (Different Config) + +Individual plugins listed IN a marketplace can be pinned to branches: + +```json +{ + "name": "my-plugin", + "source": { + "source": "github", + "repo": "owner/plugin-repo", + "ref": "v2.0.0", + "sha": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0" + } +} +``` + +But this is configured in the `plugins` array inside `marketplace.json` itself, NOT in the project's `settings.json`.[^1] + +### CLI Confirmation + +Running `claude plugin marketplace add --help` shows no `--ref`, `--branch`, or `--tag` flag.[^2] The command accepts only `--scope` and `--sparse`. + +Running `claude plugin marketplace --help` shows no ref-related options.[^2] + +### What You Need to Do + +To use a plugin from a non-default branch: + +1. **EITHER** — Merge the feature branch to the default branch of the marketplace repo +2. **OR** — Create a **new marketplace** that points to the same repo but is configured differently (workaround; not scalable) +3. **OR** — Maintain the plugin source manually in your own marketplace manifest and pin it there (requires hosting your own marketplace catalog) + +## Tested and Failed Approaches + +The user confirmed these do NOT work:[^3] + +1. Adding `"ref": "branch-name"` to the `source` object in `extraKnownMarketplaces` — silently ignored +2. Using the `--ref` flag with `claude plugin marketplace add` — flag does not exist +3. Using the `--branch` flag — flag does not exist + +## Conclusion + +**Marketplace branch-pinning is NOT supported in current Claude Code.** The feature does not exist in the official documentation or CLI. Workaround: either merge the branch to `main` in the marketplace repo, or create a separate marketplace catalog that lists the plugin with an explicit `ref` in its `source` field. + +--- + +## Sources + +[^1]: Claude Code Official Documentation - Create and Distribute a Plugin Marketplace. "Plugin sources" section describing the `github` source type and its fields, and the distinction between marketplace sources (which do not support `ref`) and plugin sources (which do). [https://code.claude.com/docs/en/plugin-marketplaces](https://code.claude.com/docs/en/plugin-marketplaces) + +[^2]: Claude Code CLI `--help` output for `claude plugin marketplace add` and `claude plugin marketplace`. Confirmed no `--ref`, `--branch`, or `--tag` flag exists. Output captured 2026-05-21. + +[^3]: User testing summary (provided in task context): attempted `"ref": "branch-name"` in settings.json — silently ignored. Attempted CLI flags `--ref` and `--branch` — not recognized. From 21655292c278cf646ac89be37a416269f63340fe Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 03:07:54 +0000 Subject: [PATCH 008/142] chore: add task/background/plugin-refresh env vars to settings Set CLAUDE_CODE_ENABLE_TASKS, CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH, CLAUDE_AUTO_BACKGROUND_TASKS, CLAUDE_CODE_DISABLE_CRON=0, CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=0, CLAUDE_CODE_EXIT_AFTER_STOP_DELAY, and FORCE_AUTOUPDATE_PLUGINS so the next session can use the Task tools, background tasks/cron, and forced plugin auto-update. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/settings.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.claude/settings.json b/.claude/settings.json index d2b6c77..dd78c4c 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -4,7 +4,14 @@ "defaultMode": "bypassPermissions" }, "env": { - "TASK_UTILS_REQUIRE_TASK": "0" + "TASK_UTILS_REQUIRE_TASK": "0", + "CLAUDE_CODE_ENABLE_TASKS": "1", + "CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH": "1", + "CLAUDE_AUTO_BACKGROUND_TASKS": "1", + "CLAUDE_CODE_DISABLE_CRON": "0", + "CLAUDE_CODE_DISABLE_BACKGROUND_TASKS": "0", + "CLAUDE_CODE_EXIT_AFTER_STOP_DELAY": "60000", + "FORCE_AUTOUPDATE_PLUGINS": "1" }, "extraKnownMarketplaces": { "agents": { From 084b8c7b74aaecc0f5aa04dd6ccde16dbb1d693e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 03:19:37 +0000 Subject: [PATCH 009/142] docs: add draft site page index Compile the farish site's page inventory into docs/pages/INDEX.md (prompt steps 5-7): 11 pages across Discover/Create/Account/System, each tagged browser-only vs backend-dependent, with a Mermaid sitemap. Search folded into Explore on review; no separate onboarding or login page. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/pages/INDEX.md | 124 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 docs/pages/INDEX.md diff --git a/docs/pages/INDEX.md b/docs/pages/INDEX.md new file mode 100644 index 0000000..a3ce75e --- /dev/null +++ b/docs/pages/INDEX.md @@ -0,0 +1,124 @@ +# Site Pages — Index (draft) + +Draft page inventory for **farish**, the AI 3D-model generator. Derived from +[`docs/INITIAL_PROMPT.md`][prompt]. This is a **first-pass draft** (prompt +steps 5–7): page titles and one or two sentences each — no detailed specs yet. +Each page gets its own `docs/pages//SPEC.md` in a later step. + +[prompt]: ../INITIAL_PROMPT.md + +## Browser-only vs. backend-dependent + +farish is built to run as a browser-only static site on GitHub Pages for now. +The AI generator and a per-browser local library work fully client-side. The +social layer (shared galleries, ratings, view counts, public profiles, +cross-user search) needs a shared backend; until a Vercel backend exists +(amendment A3 in the initial prompt) those pages ship as **Coming Soon** +placeholders behind a ghost wireframe rendered with mock data. Each page below +is tagged accordingly. + +| Tag | Meaning | +| -------------- | --------------------------------------------------------- | +| `browser-only` | Works fully client-side; ships functional. | +| `backend` | Needs a shared backend; ships as Coming Soon until built. | +| `static` | Static content, no data dependency. | +| `system` | Framework / utility page. | + +## Sitemap + +```mermaid +flowchart TD + Home[Home] --> Generate[Generate] + Home --> Explore[Explore + Search] + Home --> Leaderboards[Leaderboards] + Home --> MyLibrary[My Library] + Home --> About[About] + Home --> Settings[Settings] + Generate -. requires key .-> Settings + Generate --> ModelDetail[Model Detail] + Explore --> ModelDetail + Leaderboards --> ModelDetail + MyLibrary --> ModelDetail + ModelDetail --> Profile[Profile] + ModelDetail --> Generate + + ComingSoon[Coming Soon] + NotFound[Not Found / 404] + + Explore -. backend-gated .-> ComingSoon + Leaderboards -. backend-gated .-> ComingSoon + Profile -. backend-gated .-> ComingSoon +``` + +## Pages + +### Discover + +1. **Home** — `home` — `static` + The landing page: what farish does, the primary call-to-action into + Generate, and a preview strip of trending models (the strip is a + backend-enhanced extra that degrades gracefully when offline). + +2. **Explore** — `explore` — `backend` + The browsable gallery of shared models with search, sort, and filter + controls — search is a first-class mode of this page, not a separate route. + Covers the query, empty, and no-results states. + +3. **Leaderboards** — `leaderboards` — `backend` + Three ranked boards — Best Rated, Most Rated (Popular), and Most Viewed — + each filterable by time bucket: 1 week, 1 month, 1 year, all time. + +### Create + +4. **Generate** — `generate` — `browser-only` + The core feature: enter a prompt, configure model parameters, answer + spec-clarification questions when the prompt is underspecified, and watch + the live generation loop produce a 3D model. Prompts inline to connect a + key (linking to Settings) when none is set — no separate onboarding page. + +5. **Model Detail** — `model-detail` — `browser-only` viewer, `backend` social + An interactive 3D viewer for a single model alongside its prompt, + parameters, and metadata, plus download, share, and rating actions. + +### Account + +6. **My Library** — `my-library` — `browser-only` + The current user's own generated models, stored in the browser so the + library works offline and without an account. + +7. **Profile** — `profile` — `backend` + A public user's models and stats — their shared creations and rankings. + +8. **Settings** — `settings` — `browser-only` + Connect a Claude account (login-with-Claude) or enter an API key, manage + preferences, and read how credentials are stored locally. This page is also + the login/connect surface — no separate Login page. + +### System + +9. **About** — `about` — `static` + Project background — William Farish and the history of isometric + projection — how generation works, and the credential-privacy explanation. + +10. **Coming Soon** — `coming-soon` — `system` + A reusable placeholder for backend-dependent pages before the backend + exists: a ghost wireframe rendered with mock data behind a "coming soon" + overlay. + +11. **Not Found** — `not-found` — `system` + The 404 page for unknown routes. + +## Review notes (step 6) + +Resolved from the first draft's open questions: + +- **Search folded into Explore.** Search and a browse gallery share the same + card grid and states; search is a mode of Explore, not a separate page or + spec. Models remain fully searchable — via Explore's search control. +- **No separate onboarding page.** Generate prompts inline to connect a key + (deep-linking to Settings) when none is present. +- **No separate Login/Connect page.** Settings is the connect surface. + +Result: **11 pages** (down from 12). Reviewed a second time (step 7) — no +further changes; the set is complete and each page maps cleanly to a flow in +the initial prompt. From e5b78d9b3761cf1d6f1c9b95e1f7cf06368fca39 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 03:20:02 +0000 Subject: [PATCH 010/142] docs: scaffold empty per-page spec files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create an empty docs/pages//SPEC.md for each of the 11 pages in docs/pages/INDEX.md (prompt step 8). Files are intentionally empty — they are filled in once docs/pages/PAGE-SPEC.md defines their shape. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/pages/about/SPEC.md | 0 docs/pages/coming-soon/SPEC.md | 0 docs/pages/explore/SPEC.md | 0 docs/pages/generate/SPEC.md | 0 docs/pages/home/SPEC.md | 0 docs/pages/leaderboards/SPEC.md | 0 docs/pages/model-detail/SPEC.md | 0 docs/pages/my-library/SPEC.md | 0 docs/pages/not-found/SPEC.md | 0 docs/pages/profile/SPEC.md | 0 docs/pages/settings/SPEC.md | 0 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/pages/about/SPEC.md create mode 100644 docs/pages/coming-soon/SPEC.md create mode 100644 docs/pages/explore/SPEC.md create mode 100644 docs/pages/generate/SPEC.md create mode 100644 docs/pages/home/SPEC.md create mode 100644 docs/pages/leaderboards/SPEC.md create mode 100644 docs/pages/model-detail/SPEC.md create mode 100644 docs/pages/my-library/SPEC.md create mode 100644 docs/pages/not-found/SPEC.md create mode 100644 docs/pages/profile/SPEC.md create mode 100644 docs/pages/settings/SPEC.md diff --git a/docs/pages/about/SPEC.md b/docs/pages/about/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/coming-soon/SPEC.md b/docs/pages/coming-soon/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/explore/SPEC.md b/docs/pages/explore/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/generate/SPEC.md b/docs/pages/generate/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/home/SPEC.md b/docs/pages/home/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/leaderboards/SPEC.md b/docs/pages/leaderboards/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/model-detail/SPEC.md b/docs/pages/model-detail/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/my-library/SPEC.md b/docs/pages/my-library/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/not-found/SPEC.md b/docs/pages/not-found/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/profile/SPEC.md b/docs/pages/profile/SPEC.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/pages/settings/SPEC.md b/docs/pages/settings/SPEC.md new file mode 100644 index 0000000..e69de29 From a33ebe886fd9fb6daed0e9497e943c3e0ceb3293 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 03:21:12 +0000 Subject: [PATCH 011/142] docs: define page-spec shape and authoring rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add docs/pages/PAGE-SPEC.md (prompt step 10): the schema every docs/pages//SPEC.md must follow — required frontmatter, 13 ordered sections, format rules (Mermaid diagrams, footnote citations), and good/bad examples for the States and Data sections. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/pages/PAGE-SPEC.md | 146 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 docs/pages/PAGE-SPEC.md diff --git a/docs/pages/PAGE-SPEC.md b/docs/pages/PAGE-SPEC.md new file mode 100644 index 0000000..02c8999 --- /dev/null +++ b/docs/pages/PAGE-SPEC.md @@ -0,0 +1,146 @@ +# Page Spec — Shape & Authoring Rules + +This document defines the **shape** of a page specification: the structure, +required sections, and format every `docs/pages//SPEC.md` must follow. +It is the contract a page spec is reviewed against (prompt step 10). + +It is not itself a page spec — it is the schema for them. + +## Why a fixed shape + +Every page spec is consumed three times downstream: + +1. **Wireframing** (prompt step 15) — layout and component sections drive the + wireframes. +2. **API design** (prompt steps 17–18) — the Data section is mined for the + REST/WebSocket endpoints each page needs. +3. **Implementation** (prompt step 30+) — states, interactions, and responsive + notes become the build checklist and the page tests. + +A consistent shape means a reviewer (human or agent) can diff a spec against +this document and mechanically find what is missing. + +## File location & naming + +- One spec per page: `docs/pages//SPEC.md`. +- `` is the slug column from [`INDEX.md`](INDEX.md) — lowercase, + kebab-case (`model-detail`, `not-found`). +- The spec file is always named `SPEC.md` (uppercase). + +## Required frontmatter + +Every spec opens with a YAML frontmatter block. All keys are required. + +```yaml +--- +title: Model Detail # human-readable page title, matches INDEX.md +slug: model-detail # matches the directory name +route: /m/:modelId # URL path pattern; ":param" for dynamic segments +tag: browser-only # one of: browser-only | backend | static | system +status: draft # one of: draft | reviewed | live +backend_dependent: partial # one of: no | partial | yes +--- +``` + +## Required sections + +Sections appear in this exact order. Use the exact `##` headings shown. A +section with nothing to say still appears, with the single line `_None._` — +never delete a heading. + +| # | Heading | Content | +| --- | ------------------------ | -------------------------------------------------------------------------------------------------------- | +| 1 | `# ` | The H1, matching `title`. | +| 2 | `## Summary` | 1–3 sentences: what the page is and why it exists. | +| 3 | `## Route & Access` | The URL pattern, the `tag`, and any precondition (API key set, model exists, auth). | +| 4 | `## Users & Entry Points`| Who arrives here and from which pages/links/redirects. | +| 5 | `## Layout` | The page's regions, top to bottom. Include a Mermaid `flowchart` **or** an ASCII sketch of the regions. | +| 6 | `## Components` | Bulleted list of the notable UI components/widgets, each with a one-line role. | +| 7 | `## States` | A table of every state (`default`, `loading`, `empty`, `error`, `no-key`, `offline`, `coming-soon`, …) and what the page renders in each. | +| 8 | `## Interactions` | Each user action and its outcome, as `action → outcome` bullets. | +| 9 | `## Data` | Every piece of data the page reads or writes. Mark each `local` (browser storage) or `remote` (backend). | +| 10 | `## Navigation` | In-links (how users get here) and out-links (where they can go). | +| 11 | `## Responsive` | Desktop is the default; describe the mobile/narrow adaptations. | +| 12 | `## Open Questions` | Unresolved decisions. `_None._` when empty. | +| 13 | `## References` | Markdown footnote definitions backing any non-obvious claim. | + +## Format rules + +- **Markdown**, GitHub-flavored. Wrap prose at ~90 columns. +- **Diagrams use Mermaid** (per amendment A6 of the initial prompt) — never an + image where a Mermaid diagram works. ASCII sketches are allowed only for the + rough region layout in `## Layout`. +- **Cite sources** with GitHub footnote syntax (`[^1]`) in `## References`. + Any claim that could attract a `[citation needed]` must carry one. +- **Link to repo files** with `github.com/...` URLs or repo-relative links, + never filesystem paths. +- Reference the initial prompt as `../INITIAL_PROMPT.md` and other pages as + `..//SPEC.md`. +- Keep a spec under ~250 lines. If it grows past that, the page is probably + two pages — raise it in `## Open Questions`. + +## Good vs. bad + +### `## States` — good + +```markdown +## States + +| State | Trigger | Renders | +| ------------- | -------------------------------- | ------------------------------------------------ | +| `default` | Model loaded | 3D viewer + metadata panel + action bar | +| `loading` | Model fetch in flight | Skeleton viewer + shimmer on the metadata panel | +| `error` | Fetch failed | Inline error card with a Retry button | +| `coming-soon` | Social actions, no backend yet | Action bar replaced by the Coming Soon overlay | +``` + +Why it is good: every state names its trigger and its concrete rendering — a +builder and a test can both act on it. + +### `## States` — bad + +```markdown +## States + +The page handles loading and errors gracefully and shows the right thing. +``` + +Why it is bad: no enumerated states, no triggers, nothing testable — "the +right thing" cannot be built or verified against. + +### `## Data` — good + +```markdown +## Data + +- `model` — the model record (id, prompt, params, geometry URL). `remote`. +- `viewerSettings` — camera/lighting prefs. `local` (browser storage). +- `rating` — the viewer's own rating of this model. `remote`, write. +``` + +Why it is good: each datum is named, sourced, and marked local/remote — step +17 can mine this directly into endpoints. + +### `## Data` — bad + +```markdown +## Data + +The page needs the model and some user preferences. +``` + +Why it is bad: unnamed, unsourced — gives the API-design step nothing to +extract. + +## Authoring & review flow + +A spec is authored and reviewed with the `spec-writing` skill +(`.claude/skills/spec-writing/`, prompt step 11). In short: outline → bullet +each section → review the plan → write each section → review the whole spec → +iterate until no improvement remains. This document is the checklist that +review step diffs against. + +## References + +[^1]: Initial prompt, step 10 (defines this document) and amendment A6 + (Mermaid diagrams in docs) — [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). From b4c4398ab5e6540d84af5cda27d0972d3bb2fc6b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 04:10:03 +0000 Subject: [PATCH 012/142] chore: point plugin marketplaces at local branch checkouts Add agents-local and ai-mktpl-local directory-source marketplaces (pointing at the local /home/user/agents and /home/user/ai-mktpl checkouts on the dev branch) and repoint the agents/ai-mktpl plugins' enabledPlugins entries at them. The GitHub-source agents/ai-mktpl marketplaces are left declared; official-marketplace plugins unchanged. This lets farish use in-development branch versions of the plugins. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/settings.json | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index dd78c4c..eaceb0e 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -25,22 +25,34 @@ "source": "github", "repo": "nsheaps/ai-mktpl" } + }, + "agents-local": { + "source": { + "source": "directory", + "path": "/home/user/agents" + } + }, + "ai-mktpl-local": { + "source": { + "source": "directory", + "path": "/home/user/ai-mktpl" + } } }, "enabledPlugins": { - "cron-utils@agents": true, - "task-utils@agents": true, - "shared-lib@ai-mktpl": true, - "dangerous-bypass@ai-mktpl": true, - "agentic-behavior@ai-mktpl": true, - "common-sense@ai-mktpl": true, - "deep-research@ai-mktpl": true, - "edit-utils@ai-mktpl": true, - "github@ai-mktpl": true, - "github-app@ai-mktpl": true, - "mise@ai-mktpl": true, - "scm-utils@ai-mktpl": true, - "sequential-thinking@ai-mktpl": true, + "cron-utils@agents-local": true, + "task-utils@agents-local": true, + "shared-lib@ai-mktpl-local": true, + "dangerous-bypass@ai-mktpl-local": true, + "agentic-behavior@ai-mktpl-local": true, + "common-sense@ai-mktpl-local": true, + "deep-research@ai-mktpl-local": true, + "edit-utils@ai-mktpl-local": true, + "github@ai-mktpl-local": true, + "github-app@ai-mktpl-local": true, + "mise@ai-mktpl-local": true, + "scm-utils@ai-mktpl-local": true, + "sequential-thinking@ai-mktpl-local": true, "hookify@claude-plugins-official": true, "plugin-dev@claude-plugins-official": true }, From 10eb9c53f22151ab977a3656c9986d74cf8408d4 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 04:10:09 +0000 Subject: [PATCH 013/142] chore: harden session-start hook for local marketplaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the mise toolchain-install block — that duplicates the mise plugin's own SessionStart hook. Add a best-effort fetch + ff-only pull of the local marketplace checkouts (/home/user/agents, /home/user/ai-mktpl) so the directory-source marketplaces stay current with their branch. Route bun install through `mise exec` so bun resolves on a first run. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/hooks/session-start.sh | 38 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh index aba901d..899954e 100755 --- a/.claude/hooks/session-start.sh +++ b/.claude/hooks/session-start.sh @@ -14,25 +14,37 @@ cd "${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel)}" echo "[session-start] onboarding farish in ${PWD}" -# mise — install pinned tool versions (bun, node, etc.) once configured. -if [ -f mise.toml ] || [ -f .mise.toml ] || [ -f .config/mise/config.toml ]; then - if command -v mise >/dev/null 2>&1; then - echo "[session-start] mise install" - mise install - else - echo "[session-start] mise config present but mise not on PATH — skipping" - fi -fi +# Toolchain install (mise) is handled by the mise plugin's own SessionStart +# hook — intentionally NOT duplicated here. -# bun — install workspace dependencies once a manifest exists. +# bun — install workspace dependencies once a manifest exists. bun is provided +# by mise (pinned in mise.toml), so route through `mise exec` so bun resolves +# even before mise's shims reach PATH on a first run — rather than assuming bun +# is already on PATH. Project-specific; a future bun-utils plugin could own it. if [ -f package.json ]; then - if command -v bun >/dev/null 2>&1; then + if command -v mise >/dev/null 2>&1; then + echo "[session-start] bun install (via mise exec)" + mise exec -- bun install || echo "[session-start] bun install failed (continuing)" + elif command -v bun >/dev/null 2>&1; then echo "[session-start] bun install" - bun install + bun install || echo "[session-start] bun install failed (continuing)" else - echo "[session-start] package.json present but bun not on PATH — skipping" + echo "[session-start] package.json present but neither mise nor bun on PATH — skipping" fi fi +# Keep local-checkout plugin marketplaces fresh. farish's `agents-local` and +# `ai-mktpl-local` marketplaces are `directory` sources pointing at local git +# checkouts; a directory marketplace serves whatever is in the checkout's +# working tree, so each checkout must be pulled forward to stay current with +# its branch. Best-effort — failures never abort onboarding. +for repo in /home/user/agents /home/user/ai-mktpl; do + if [ -d "$repo/.git" ]; then + echo "[session-start] refreshing local marketplace checkout: $repo" + git -C "$repo" fetch --quiet origin || echo "[session-start] fetch failed for $repo (continuing)" + git -C "$repo" pull --ff-only --quiet || echo "[session-start] pull skipped/failed for $repo (continuing)" + fi +done + echo "[session-start] done" exit 0 From bc42c2550e6c6ed387fb5252a3441c34164e48b6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 04:10:15 +0000 Subject: [PATCH 014/142] docs: add build-confidence-by-trying-to-prove-incorrect skill A context:fork skill capturing the adversarial-debate pattern: when not fully confident in a decision or next step, dispatch an Agent whose job is to disprove it, and proceed only once the claim survives the attack. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .../SKILL.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .claude/skills/build-confidence-by-trying-to-prove-incorrect/SKILL.md diff --git a/.claude/skills/build-confidence-by-trying-to-prove-incorrect/SKILL.md b/.claude/skills/build-confidence-by-trying-to-prove-incorrect/SKILL.md new file mode 100644 index 0000000..5d5c653 --- /dev/null +++ b/.claude/skills/build-confidence-by-trying-to-prove-incorrect/SKILL.md @@ -0,0 +1,41 @@ +--- +name: build-confidence-by-trying-to-prove-incorrect +description: Resolve a decision, claim, or plan you are not fully confident in by dispatching an adversarial Agent whose job is to disprove it. Use before committing to a non-trivial or hard-to-reverse next step while ambiguity or low confidence remains. Trigger phrases — "I have a feeling but want to be sure", "is this the right next step?", "prove this wrong before I act", "I keep wanting to second-guess this". +context: fork +--- + +# Build confidence by trying to prove it incorrect + +When you have a hypothesis, plan, or next step you are not fully confident in, +do not guess and do not proceed. Dispatch an adversarial `Agent()` whose +explicit job is to **disprove** it. Proceed only once the claim survives a +genuine attack. + +## Steps + +1. Write the claim/plan as a single falsifiable statement, plus the concrete + next step it would justify and why the step is hard to reverse. +2. Dispatch `Agent(run_in_background: true)` with an adversarial brief: its job + is to prove the claim wrong, unsafe, or that a better option exists — NOT to + agree. Instruct it to verify empirically wherever possible, cite official or + primary sources, and to state explicitly if it cannot disprove the claim. +3. Require the agent to write its findings to a file and return a short + verdict: which claims survived, which were disproven, and the corrected + next step. +4. If a claim is disproven, adopt the correction. If confidence is still not + sufficient, repeat from step 1 on the corrected claim. +5. If the claim survives a genuine attack, confidence is sufficient — proceed. + +## Stop condition + +You are done debating when you no longer feel you would need another round to +prove the next step wrong. Lingering "do nothing until proven correct" +hesitation means another round is needed. + +## Notes + +- The adversary must genuinely attack — an agreeable reviewer gives false + confidence. Frame the brief so agreement is failure. +- Empirical disproof beats argument: prefer an agent that can run a test. +- This is for uncertainty, not for every decision — skip it when the next step + is obvious and easily reversible. From a82891cd5b18e465ada263bc9b7d94985205c4b3 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 04:10:21 +0000 Subject: [PATCH 015/142] docs: document local-checkout marketplace pinning strategy Marketplace sources cannot be branch-pinned (the ref field is ignored), but registering a local git checkout kept on the target branch as a directory-source marketplace achieves the goal. Update the branch-pinning research with the working strategy and the fetch/pull caveat; add the empirical local-marketplace-setup findings. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/research/local-marketplace-setup.md | 176 ++++++++++++++++++++ docs/research/marketplace-branch-pinning.md | 34 +++- 2 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 docs/research/local-marketplace-setup.md diff --git a/docs/research/local-marketplace-setup.md b/docs/research/local-marketplace-setup.md new file mode 100644 index 0000000..e9c7a25 --- /dev/null +++ b/docs/research/local-marketplace-setup.md @@ -0,0 +1,176 @@ +# Local Marketplace Setup: Empirical Testing & Findings + +## Question + +Can farish resolve plugins from **local git checkouts** of nsheaps' marketplaces (agents, ai-mktpl) on a feature branch, without waiting for merges to main? + +Sub-questions for testing: + +1. Can the KEY in `extraKnownMarketplaces` differ from the marketplace.json `"name"` field? (If yes, `agents-local`/`ai-mktpl-local` names are possible.) +2. Is a PROJECT-scope `directory`-source marketplace shadowing a USER-scope GitHub marketplace safe and well-defined? +3. What's the state after the user's ad-hoc `claude plugin marketplace add` experiment? + +## Empirical Testing + +### Test 1: Key vs. Marketplace.json Name + +**Setup**: Created `/tmp/test-mktpl/.claude-plugin/marketplace.json` with `"name": "test-marketplace"` and added a test plugin. + +**Test**: Manually edited `.claude/settings.json` to use key `"test_different_name"` while the marketplace.json has `"name": "test-marketplace"`. + +**Settings.json entry**: +```json +{ + "test_different_name": { + "source": { + "source": "directory", + "path": "/tmp/test-mktpl" + } + } +} +``` + +**Plugin reference**: +```json +{ + "enabledPlugins": { + "test-plugin@test_different_name": true + } +} +``` + +**Result**: The key in `extraKnownMarketplaces` CAN differ from the marketplace.json `"name"`. The enablement string uses the `extraKnownMarketplaces` KEY, not the marketplace.json name. + +**Evidence**: Official Claude Code documentation [plugin-marketplaces](https://code.claude.com/docs/en/plugin-marketplaces) shows: + +> ```json +> { +> "extraKnownMarketplaces": { +> "company-tools": { +> "source": { +> "source": "github", +> "repo": "your-org/claude-plugins" +> } +> } +> }, +> "enabledPlugins": { +> "code-formatter@company-tools": true +> } +> } +> ``` + +The key (`"company-tools"`) is the identifier used in `enabledPlugins`. It can be anything and does NOT need to match the marketplace.json `"name"` field. + +### Test 2: PROJECT-scope Shadowing USER-scope + +**Observed state after user's experiment**: +- User ran: `claude plugin marketplace add /home/user/agents --scope project` +- CLI response: "Successfully added marketplace: agents (declared in project settings)" +- Current `/home/user/farish/.claude/settings.json` extraKnownMarketplaces: + +```json +{ + "agents": { + "source": { + "source": "directory", + "path": "/home/user/agents" + } + }, + "ai-mktpl": { + "source": { + "source": "github", + "repo": "nsheaps/ai-mktpl" + } + } +} +``` + +**Key discrepancy identified**: The settings.json still shows `ai-mktpl` pointing to GitHub (not local). The user's intent was to make BOTH agents and ai-mktpl resolve from local paths. + +**Shadowing behavior**: PROJECT-scope settings successfully OVERRIDE user-scope settings with the same key name. When farish loads, it merges: +1. User scope (`~/.claude/settings.json`) — GitHub agents + GitHub ai-mktpl +2. Project scope (`.claude/settings.json`) — local agents (directory source) + +The project-scope `agents` entry with directory source successfully shadows the user-scope `agents` entry with GitHub source. This is explicitly supported and safe. + +### Test 3: Current Cleanup State + +**What the experiment left behind**: +- ✅ agents marketplace registered at PROJECT scope pointing to `/home/user/agents` +- ❌ ai-mktpl still points to GitHub (user scope) — not yet updated to local + +**What still needs to be done**: +- Add ai-mktpl (directory source) to project `.claude/settings.json` with key `"ai-mktpl"` +- Verify both local checkouts are on the correct branch (`claude/ai-3d-model-generator-XjoUi`) + +## Key Claims Attacked & Verdict + +| Claim | Attack | Verdict | +|-------|--------|---------| +| **Keys must match marketplace.json `"name"`** | Tested key `test_different_name` with marketplace.json `"name": "test-marketplace"`. Plugin ref `test-plugin@test_different_name` worked. | ❌ DISPROVEN — Keys are independent. | +| **Naming agents-local/ai-mktpl-local is impossible** | Demonstrated that any KEY in `extraKnownMarketplaces` can be chosen freely. | ❌ DISPROVEN — Keys ARE independently nameable. | +| **PROJECT-scope shadowing is unsafe** | Official docs and CLI behavior confirm safe shadowing. No conflicts or inconsistency. | ✅ CONFIRMED SAFE — shadowing works as designed. | +| **Absolute paths in .claude/settings.json cause portability issues** | Design of Claude Code settings allows this. However, locally scoped, not committed. Absolute paths are project-specific, not portable. | ⚠️ PARTIALLY TRUE — Path is absolute but OK for a single dev machine; user should be aware it's machine-specific. | + +## Mechanism: How Plugin Resolution Works + +1. **Settings merge** (precedence: local > project > user) — Claude Code reads all 3 scopes +2. **Marketplace discovery** — `extraKnownMarketplaces` keys become recognized marketplace names +3. **Marketplace fetch** — Claude Code fetches marketplace.json from the declared source (GitHub URL, git repo, or local directory) +4. **Plugin enablement** — `enabledPlugins` references plugins by `name@marketplace_key` (uses the key, not the marketplace.json name) +5. **Plugin install** — For each enabled plugin, Claude Code looks it up in the marketplace catalog and installs from the plugin source + +**Key insight**: The marketplace.json `"name"` is purely metadata. Plugin resolution uses the `extraKnownMarketplaces` KEY throughout. + +## Recommended Safe Sequence + +**DO**: +1. Edit `/home/user/farish/.claude/settings.json` extraKnownMarketplaces to add ai-mktpl with directory source +2. Keep both keys as `"agents"` and `"ai-mktpl"` (matching user habit) +3. Verify both local repos are on the feature branch +4. No other changes needed + +**DON'T**: +- Don't create wrapper catalogs or renaming redirects +- Don't edit /home/user/agents/.claude-plugin/marketplace.json `"name"` fields +- Don't create symlinks or path aliases + +## Exact Safe Sequence (Clean State) + +```bash +# 1. Verify current state +cat /home/user/farish/.claude/settings.json | jq '.extraKnownMarketplaces | keys' + +# 2. Check branch on both local repos +cd /home/user/agents && git rev-parse --abbrev-ref HEAD +git rev-parse --abbrev-ref HEAD + +# 3. Update farish settings.json to add ai-mktpl local source +# (If not already present, which it isn't) +jq '.extraKnownMarketplaces.["ai-mktpl"] = { + "source": { + "source": "directory", + "path": "/home/user/ai-mktpl" + } +}' /home/user/farish/.claude/settings.json > /tmp/settings-update.json + +# 4. Review the update +jq '.extraKnownMarketplaces' /tmp/settings-update.json + +# 5. Apply (after user approval) +# mv /tmp/settings-update.json /home/user/farish/.claude/settings.json + +# 6. Verify both agents and ai-mktpl are resolvable and on correct branch +# (handled by Claude Code on next session start or manual plugin refresh) +``` + +## What Remains Uncertain + +- **Auto-refresh on branch change**: Does Claude Code automatically pick up new plugins when the local git checkout changes branches? (Likely yes, but not tested.) +- **Plugin cache invalidation**: When a local directory source updates, how quickly are changes visible? (Likely immediate for local paths, but not formally tested.) + +## Sources + +- [Claude Code Plugin Marketplaces Documentation](https://code.claude.com/docs/en/plugin-marketplaces) — official reference for `extraKnownMarketplaces` structure and behavior [retrieved 2026-05-21] +- Empirical testing with `/tmp/test-mktpl` — confirmed key independence and shadowing behavior +- Current farish `.claude/settings.json` state — confirms agents local registration works diff --git a/docs/research/marketplace-branch-pinning.md b/docs/research/marketplace-branch-pinning.md index bef81cd..9902939 100644 --- a/docs/research/marketplace-branch-pinning.md +++ b/docs/research/marketplace-branch-pinning.md @@ -2,7 +2,7 @@ ## Summary -**Branch-pinning of marketplaces is NOT supported.** The `github` marketplace source type does not accept a `ref` field in `extraKnownMarketplaces` configuration. Marketplaces are always resolved from their default branch; only individual plugins within a marketplace can be pinned to specific branches, tags, or commits. +**Branch-pinning a marketplace _source_ is NOT supported** — the `github` marketplace source type does not accept a `ref` field in `extraKnownMarketplaces`, and marketplaces resolve from their default branch. **But the goal — using a plugin from a non-default branch — IS achievable** via a different mechanism: register a **local git checkout** (kept on the target branch) as a `directory`-source marketplace. See [Working strategy](#working-strategy--local-checkout-directory-marketplace) below; full details in [`local-marketplace-setup.md`](local-marketplace-setup.md). ## Detailed Findings @@ -79,9 +79,39 @@ The user confirmed these do NOT work:[^3] 2. Using the `--ref` flag with `claude plugin marketplace add` — flag does not exist 3. Using the `--branch` flag — flag does not exist +## Working strategy — local-checkout directory marketplace + +Although a marketplace _source_ cannot be branch-pinned, the goal — use a +plugin from a non-default branch — IS achievable: + +1. Keep a **local git checkout** of the marketplace repo, checked out to the + desired branch. +2. Register that checkout as a **`directory`-source marketplace** in + `extraKnownMarketplaces`. The `extraKnownMarketplaces` KEY is free-form + (independent of the `marketplace.json` `"name"`), so it can be named + distinctly — e.g. `agents-local`. +3. Point the relevant `enabledPlugins` entries at the local marketplace key. + +A `directory` marketplace serves plugins from the checkout's current working +tree, so whatever branch the checkout sits on is what gets served. + +**Operational caveat:** a `directory` marketplace does NOT auto-update when the +branch advances on the remote. The local checkout must be continually +`git fetch`ed + `git pull`ed to stay current — otherwise the marketplace serves +stale plugin code. farish automates this in its `SessionStart` hook +(`.claude/hooks/session-start.sh`), which refreshes `/home/user/agents` and +`/home/user/ai-mktpl` on every session start. + +Full empirical findings and farish's exact configuration: +[`local-marketplace-setup.md`](local-marketplace-setup.md). + ## Conclusion -**Marketplace branch-pinning is NOT supported in current Claude Code.** The feature does not exist in the official documentation or CLI. Workaround: either merge the branch to `main` in the marketplace repo, or create a separate marketplace catalog that lists the plugin with an explicit `ref` in its `source` field. +A marketplace's _source_ cannot be branch-pinned (`ref` is silently ignored for +`github` sources). But the objective is met by the **local-checkout directory +marketplace** strategy above: register a local checkout — kept on the target +branch and kept fresh by your own `git fetch`/`pull` — as a `directory` +marketplace. farish uses this for `agents-local` and `ai-mktpl-local`. --- From fd8c0342731551a67ef43c66b56464b9cb207dd5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 04:55:08 +0000 Subject: [PATCH 016/142] feat(skills): add spec-writing skill and subskills (step 11) Adds .claude/skills/spec-writing/SKILL.md with a 7-step numbered procedure that drives step 12 (one run per page). Adds three focused subskills: - spec-writing-draft-outline: scaffold frontmatter + bullet-note placeholders - spec-writing-write-section: fill one section with polished prose/tables - spec-writing-review: validate completed spec against PAGE-SPEC.md Each skill is a small ordered list; format rules and examples defer to docs/pages/PAGE-SPEC.md rather than inlining them. --- .../spec-writing-draft-outline/SKILL.md | 41 ++++++++++++++ .claude/skills/spec-writing-review/SKILL.md | 54 +++++++++++++++++++ .../spec-writing-write-section/SKILL.md | 45 ++++++++++++++++ .claude/skills/spec-writing/SKILL.md | 50 +++++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 .claude/skills/spec-writing-draft-outline/SKILL.md create mode 100644 .claude/skills/spec-writing-review/SKILL.md create mode 100644 .claude/skills/spec-writing-write-section/SKILL.md create mode 100644 .claude/skills/spec-writing/SKILL.md diff --git a/.claude/skills/spec-writing-draft-outline/SKILL.md b/.claude/skills/spec-writing-draft-outline/SKILL.md new file mode 100644 index 0000000..d3a58b3 --- /dev/null +++ b/.claude/skills/spec-writing-draft-outline/SKILL.md @@ -0,0 +1,41 @@ +--- +name: spec-writing-draft-outline +description: > + Scaffold the frontmatter and bullet-note placeholders for all 13 required + sections of a page spec. Use at the start of writing a spec, before any + prose is written. Trigger phrases: "draft the outline", "scaffold the spec", + "create the spec outline". Called from the spec-writing skill step 3. +--- + +# Spec — Draft Outline + +Produces a scaffolded `SPEC.md` with frontmatter and placeholder bullets. No +prose is written yet — that is done by `spec-writing-write-section`. + +## Steps + +1. Read `docs/pages/PAGE-SPEC.md`: + - Note the 6 required frontmatter keys and their allowed values. + - Note the 13 required section headings in order. + +2. Read `docs/pages/INDEX.md` to confirm the page's slug, title, route, and + tag for this page. + +3. Open `docs/pages//SPEC.md` (create if missing). + +4. Write the YAML frontmatter block at the top of the file. All 6 keys are + required; set `status: draft`. Infer `backend_dependent` from the tag in + INDEX.md (`browser-only` / `static` → `no`; `backend` → `yes`; mixed → + `partial`). + +5. Add all 13 section headings in the exact order specified in PAGE-SPEC.md. + Use the exact heading text shown in the table (e.g. `## Route & Access`). + +6. Under each section heading, write 2–4 bullet notes that describe what + this specific page will need in that section. Draw context from: + - INDEX.md (the page's one-sentence description and tag). + - `docs/INITIAL_PROMPT.md` (feature requirements that affect this page). + - Sibling `docs/pages//SPEC.md` files for cross-page links. + Add `[citation needed]` where a footnote reference will be required. + +7. Do not write prose or fill any section beyond bullet notes. Save and stop. diff --git a/.claude/skills/spec-writing-review/SKILL.md b/.claude/skills/spec-writing-review/SKILL.md new file mode 100644 index 0000000..6bbbae9 --- /dev/null +++ b/.claude/skills/spec-writing-review/SKILL.md @@ -0,0 +1,54 @@ +--- +name: spec-writing-review +description: > + Validate a complete page spec against PAGE-SPEC.md. Checks frontmatter, + section completeness, format rules, citation coverage, and line count. + Use after all sections are written. Trigger phrases: "review the spec", + "validate the spec", "check the spec", "review SPEC.md". Called from + spec-writing skill step 5. +--- + +# Spec — Review & Validate + +Validates a finished `docs/pages//SPEC.md` against the schema in +`docs/pages/PAGE-SPEC.md`. Produces a pass/fail checklist. + +## Steps + +1. Read `docs/pages/PAGE-SPEC.md` in full — this is the checklist you + validate against. + +2. Read `docs/pages//SPEC.md` in full. + +3. **Frontmatter check.** Verify all 6 required keys are present and hold + valid values: + - `title` matches INDEX.md. + - `slug` matches the directory name. + - `route` has the correct URL pattern (`:param` for dynamic segments). + - `tag` is one of: `browser-only` | `backend` | `static` | `system`. + - `status` is one of: `draft` | `reviewed` | `live`. + - `backend_dependent` is one of: `no` | `partial` | `yes`. + +4. **Section order check.** Confirm all 13 sections appear in the exact order + from PAGE-SPEC.md. No heading may be missing; empty sections must contain + `_None._` not an empty body. + +5. **Section format checks:** + - `## States` — 4-column table with a State, Trigger, and Renders column at + minimum. Every state must name its trigger and what it renders. + - `## Data` — each datum named, sourced, and marked `local` or `remote`. + - `## Interactions` — every bullet uses `action → outcome` format. + - `## Layout` — contains a Mermaid diagram or ASCII sketch (not prose only). + - `## References` — only footnote definitions (`[^N]: ...`); no inline links. + +6. **Citation check.** For any non-obvious claim (fact, constraint, or design + decision that a builder would question), verify a `[^N]` reference exists + and is defined in `## References`. + +7. **Line count.** Count the file's lines. Flag in the report if > 250. + +8. **Produce a checklist report** listing every item above as PASS or FAIL. + For each FAIL, state the section and what is missing or malformed. + +9. If any FAILs remain, return to the `spec-writing` skill at step 6 for the + affected sections. Re-run this review after each fix. diff --git a/.claude/skills/spec-writing-write-section/SKILL.md b/.claude/skills/spec-writing-write-section/SKILL.md new file mode 100644 index 0000000..6ec9c74 --- /dev/null +++ b/.claude/skills/spec-writing-write-section/SKILL.md @@ -0,0 +1,45 @@ +--- +name: spec-writing-write-section +description: > + Fill in one section of a page spec — replace bullet-note placeholders with + polished prose, tables, or diagrams following the section's format rules. + Use after spec-writing-draft-outline, for each section in turn. Trigger + phrases: "write section X", "fill in the section", "complete section". + Called from spec-writing skill step 4. +--- + +# Spec — Write Section + +Fills one named section of a `docs/pages//SPEC.md` with finished +content. Run once per section; called 13 times total per spec. + +## Steps + +1. Identify the section to fill (e.g. `## States`) and read its bullet notes + in the current `SPEC.md`. + +2. Read the matching row in the section table in `docs/pages/PAGE-SPEC.md` + for this section's content rules. For `## States` and `## Data`, also + read the good/bad examples in that file. + +3. Write the section content using the correct format: + - `## Summary` — 1–3 sentences of plain prose. + - `## Route & Access` — URL pattern, tag value, preconditions. + - `## Users & Entry Points` — prose or bullets of who arrives and from where. + - `## Layout` — Mermaid `flowchart` or ASCII sketch of page regions. + - `## Components` — bulleted list, one component per line with a one-line role. + - `## States` — 4-column table (State | Trigger | Renders | Notes). + - `## Interactions` — `action → outcome` bullets. + - `## Data` — bulleted list; each item named, described, marked `local` or `remote`. + - `## Navigation` — in-links and out-links. + - `## Responsive` — prose or bullets on mobile/narrow adaptations. + - `## Open Questions` — bulleted list, or `_None._`. + - `## References` — markdown footnote definitions (`[^N]: ...`). + +4. Resolve all `[citation needed]` placeholders in this section. Add a + `[^N]` inline reference and define it in `## References`. + +5. Wrap prose at ~90 columns. If the section content alone would exceed + ~40 lines, note it in `## Open Questions` rather than silently trimming. + +6. Save the section. Verify the heading text matches PAGE-SPEC.md exactly. diff --git a/.claude/skills/spec-writing/SKILL.md b/.claude/skills/spec-writing/SKILL.md new file mode 100644 index 0000000..e6faced --- /dev/null +++ b/.claude/skills/spec-writing/SKILL.md @@ -0,0 +1,50 @@ +--- +name: spec-writing +description: > + Write a complete page spec (SPEC.md) for a farish site page. Use when asked + to "write the spec for X", "fill in the spec", "create SPEC.md for ", + "author the page spec", or when working through prompt step 12. Orchestrates + the draft-outline → write-section → review subskills for one page at a time. +--- + +# Spec Writing + +Process for writing a single `docs/pages//SPEC.md`. Designed so step 12 +of the initial prompt is "for each page in INDEX.md, run this skill". + +See `docs/pages/PAGE-SPEC.md` for the required shape, section rules, and +good/bad examples. This skill does not inline those rules — refer to that +document throughout. + +## Steps + +1. Identify the target page. Read `docs/pages/INDEX.md` and note the page's + slug, title, route, tag, and backend_dependent value. + +2. Verify that `docs/pages//SPEC.md` exists (it may be empty from + prompt step 8). Create the file and its parent directory if missing. + +3. Run `Skill(spec-writing-draft-outline)` to write the YAML frontmatter and + add bullet-note placeholders under each of the 13 required section headings. + +4. For each section in order (1 through 13), run + `Skill(spec-writing-write-section)` to replace the bullet notes with + polished prose, tables, or diagrams as appropriate for that section. + +5. Run `Skill(spec-writing-review)` to validate the complete spec against + `docs/pages/PAGE-SPEC.md`. + +6. For each issue the review identifies, return to step 4 for the affected + section(s), then re-run step 5. Repeat until the review passes with no + remaining issues. + +7. Commit the completed spec atomically: + `docs(pages): add page spec` + +## Notes + +- Keep the spec under ~250 lines (PAGE-SPEC.md rule). If it grows past that, + raise it in `## Open Questions` rather than silently trimming content. +- All Mermaid diagrams must render on GitHub (amendment A6 of the initial + prompt). Test locally if unsure. +- Use `[^N]` footnotes in `## References` for any non-obvious claim. From 0a005fd1a57116e85c2f65e4f43eb8c979654763 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 04:59:42 +0000 Subject: [PATCH 017/142] chore: add .gitignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ignore local-only Claude Code artifacts: settings.local.json (may hold secrets), .claude/tmp/ (disposable working files), and .claude/worktrees/ (sub-agent git worktrees — local working areas, never committed). Task records under .claude/tasks/ are intentionally NOT ignored — they are a committed, git-tracked artifact. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..64f2281 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Claude Code — local/personal settings (never committed; may hold secrets) +.claude/settings.local.json + +# Claude Code — temporary / disposable working files +.claude/tmp/ + +# Sub-agent git worktrees (local working areas, never committed) +.claude/worktrees/ From 9ff09e25b60690d21ed8a1ceafd047f7e4c23208 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:00:43 +0000 Subject: [PATCH 018/142] docs(pages): add home page spec --- docs/pages/home/SPEC.md | 112 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/docs/pages/home/SPEC.md b/docs/pages/home/SPEC.md index e69de29..ff5b090 100644 --- a/docs/pages/home/SPEC.md +++ b/docs/pages/home/SPEC.md @@ -0,0 +1,112 @@ +--- +title: Home +slug: home +route: / +tag: static +status: draft +backend_dependent: no +--- + +# Home + +## Summary + +The landing page introduces farish to new and returning visitors, presents the +primary call-to-action into the Generate page, and shows a preview strip of +trending models. The strip is backend-enhanced: it populates from the shared +model store when available and degrades gracefully to a static hero when the +backend is unreachable.[^1] + +## Route & Access + +- **Route:** `/` +- **Tag:** `static` — ships fully functional without a backend.[^2] +- **Preconditions:** None. Publicly accessible with no authentication or API key + required. + +## Users & Entry Points + +- **New visitors** arriving via direct URL, organic search, or a shared link. +- **Returning users** via bookmarks or the site logo from any inner page. +- No referrer precondition — this is the root of the site. + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar — links to Generate · Explore · Leaderboards · Library] + Hero[Hero — headline · tagline · primary Generate CTA] + Strip[Trending Preview Strip — scrollable card row, backend-enhanced] + Footer[Footer — About · Settings · GitHub link] + Nav --> Hero --> Strip --> Footer +``` + +## Components + +- **NavBar** — site-wide top bar with links to Generate, Explore, Leaderboards, + My Library, and a Settings icon. +- **HeroSection** — headline ("AI-generated 3D models, instantly"), brief + tagline explaining farish, and the primary CTA button. +- **GenerateCTA** — primary button linking to [`../generate/SPEC.md`](../generate/SPEC.md). +- **TrendingStrip** — horizontally scrollable row of `ModelCard` components + sourced from the most-viewed models endpoint; hidden in the `degraded` state. +- **ModelCard** — thumbnail preview, model title, and author chip; navigates to + [`../model-detail/SPEC.md`](../model-detail/SPEC.md) on click. +- **Footer** — links to About, Settings, and the project GitHub repository. + +## States + +| State | Trigger | Renders | +| ---------- | --------------------------------------- | --------------------------------------------------- | +| `default` | Backend reachable, trending fetch done | Hero + populated TrendingStrip | +| `loading` | Trending fetch in flight | Hero + TrendingStrip with skeleton cards | +| `degraded` | Trending fetch failed or backend absent | Hero only; TrendingStrip hidden with no error shown | + +## Interactions + +- **Click GenerateCTA** → navigate to `/generate`. +- **Click a ModelCard in TrendingStrip** → navigate to `/m/:modelId`. +- **Click Explore in NavBar** → navigate to `/explore`. +- **Click Leaderboards in NavBar** → navigate to `/leaderboards`. +- **Click My Library in NavBar** → navigate to `/library`. +- **Click Settings icon** → navigate to `/settings`. + +## Data + +- `trendingModels` — list of top-N most-viewed models (id, title, thumbnailUrl, + authorName). `remote`, read-only. The strip is suppressed (not errored) when + this fetch fails. + +## Navigation + +**In-links:** root URL (`/`); site logo in NavBar from every page. + +**Out-links:** +- `/generate` — primary CTA and NavBar +- `/explore` — NavBar +- `/leaderboards` — NavBar +- `/library` — NavBar +- `/m/:modelId` — TrendingStrip cards +- `/settings` — NavBar icon +- `/about` — Footer + +## Responsive + +Desktop (default): hero spans full viewport width; TrendingStrip scrolls +horizontally in a single row. Mobile/narrow: hero copy stacks vertically, +CTA button goes full-width; TrendingStrip becomes a 2-column card grid. + +## Open Questions + +- Should TrendingStrip surface Most Viewed, Best Rated, or Most Rated models? + Defaulting to Most Viewed for "trending" semantics — revisit once the + leaderboard data model is settled.[^3] + +## References + +[^1]: Initial prompt — home page description with degradable trending strip — + [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^2]: INDEX.md — Home tagged `static` — + [`../INDEX.md`](../INDEX.md). +[^3]: Leaderboard time-bucket design — + [`../leaderboards/SPEC.md`](../leaderboards/SPEC.md). From b402e2680585ea4e2b5bd71bbe4b555e43b0ed16 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:01:16 +0000 Subject: [PATCH 019/142] chore: track step-12 task record Task records under .claude/tasks/ are a committed, git-tracked artifact (the task-utils MCP server auto-commits them by design). Track the step-12 page-specs task record. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/tasks/step-12-page-specs.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 .claude/tasks/step-12-page-specs.json diff --git a/.claude/tasks/step-12-page-specs.json b/.claude/tasks/step-12-page-specs.json new file mode 100644 index 0000000..899e92b --- /dev/null +++ b/.claude/tasks/step-12-page-specs.json @@ -0,0 +1 @@ +{"id":"step-12-page-specs","subject":"#step-12: Write page specs for all 11 farish pages","status":"in_progress","description":"Write docs/pages//SPEC.md for all 11 pages: home, explore, leaderboards, generate, model-detail, my-library, profile, settings, about, coming-soon, not-found. Following spec-writing skill process and PAGE-SPEC.md schema."} From 340188bb3379f3cca603d0dff6e3eeeb14b31e5e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:01:36 +0000 Subject: [PATCH 020/142] docs(pages): add explore page spec --- docs/pages/explore/SPEC.md | 127 +++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/docs/pages/explore/SPEC.md b/docs/pages/explore/SPEC.md index e69de29..aec508d 100644 --- a/docs/pages/explore/SPEC.md +++ b/docs/pages/explore/SPEC.md @@ -0,0 +1,127 @@ +--- +title: Explore +slug: explore +route: /explore +tag: backend +status: draft +backend_dependent: yes +--- + +# Explore + +## Summary + +The browsable gallery of publicly shared models. Search, sort, and filter +controls are first-class — search is a mode of this page, not a separate route. +The page ships as a Coming Soon placeholder until the shared backend exists; +the spec describes the full intended design for post-backend implementation.[^1] + +## Route & Access + +- **Route:** `/explore` +- **Tag:** `backend` — ships as Coming Soon; full functionality requires the + shared model store.[^2] +- **Preconditions:** None for browsing (public gallery). Sharing a model (the + action that populates this gallery) requires a connected Claude account or API + key set in [`../settings/SPEC.md`](../settings/SPEC.md). + +## Users & Entry Points + +- **Browsers** wanting to discover shared community models. +- **Searchers** arriving with a specific topic or keyword in mind. +- Entry from: NavBar (all pages), Home hero secondary links, Model Detail "by + this author" or "similar models" links. + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + SearchBar[Search Bar — full-width text input] + Controls[Controls Row — sort selector · filter chips] + subgraph Body + Sidebar[Filter Panel — collapsible sidebar] + Grid[Model Grid — responsive card grid] + end + Pagination[Pagination / Load More] + Nav --> SearchBar --> Controls --> Body --> Pagination +``` + +## Components + +- **SearchBar** — debounced text input; updates `?q=` URL param on change. +- **SortSelector** — dropdown: Newest, Highest Rated, Most Popular, Most Viewed. +- **FilterChips** — active filters shown as removable chips in the controls row. +- **FilterPanel** — sidebar with category/tag checkboxes; collapses to a + bottom-sheet drawer on mobile. +- **ModelGrid** — responsive grid rendering `ModelCard` for each result. +- **ModelCard** — thumbnail, title, author chip, rating stars, view count; + links to [`../model-detail/SPEC.md`](../model-detail/SPEC.md). +- **EmptyState** — illustration + "No models yet" message (empty gallery). +- **NoResultsState** — "No matches for '{query}'" + Clear Search button. +- **ComingSoonOverlay** — full-page overlay from [`../coming-soon/SPEC.md`](../coming-soon/SPEC.md) + rendered until backend is live. + +## States + +| State | Trigger | Renders | +| -------------- | ------------------------------ | --------------------------------------------------- | +| `coming-soon` | Backend not yet live | ComingSoonOverlay over ghost wireframe | +| `default` | Gallery loaded, no query | SearchBar + Controls + populated ModelGrid | +| `loading` | Fetch in flight | Controls + ModelGrid with skeleton cards | +| `empty` | Zero models in the store | EmptyState illustration | +| `no-results` | Query returns zero matches | NoResultsState + Clear Search button | +| `error` | Fetch failed | Inline error card with Retry button | + +## Interactions + +- **Type in SearchBar** → debounce 300 ms → update `?q=` param → re-fetch results. +- **Change sort** → update `?sort=` param → re-fetch. +- **Toggle a filter** → update `?filter=` param → re-fetch. +- **Remove a filter chip** → remove that param → re-fetch. +- **Click ModelCard** → navigate to `/m/:modelId`. +- **Click author chip** → navigate to `/u/:username`. +- **Click Load More / scroll to bottom** → fetch next page and append cards. +- **Click Clear Search** (no-results state) → clear `?q=` → return to default. + +## Data + +- `models` — paginated list of shared models (id, title, thumbnailUrl, + authorName, ratingAvg, viewCount, createdAt). `remote`, read-only. +- `query` — active search text. `local` (URL param `?q=`). +- `sortBy` — active sort field (newest|rating|popular|views). `local` (URL + param `?sort=`). +- `filters` — active category/tag filter set. `local` (URL param `?filter=`). +- `cursor` — pagination cursor or page number. `local` (URL param `?page=`). + +## Navigation + +**In-links:** NavBar (all pages); Home hero secondary CTA; Model Detail "Explore +more" link. + +**Out-links:** +- `/m/:modelId` — ModelCard click +- `/u/:username` — author chip click + +## Responsive + +Desktop (default): FilterPanel fixed sidebar on the left; ModelGrid 3–4 +columns; SearchBar and Controls in a top bar row. Mobile/narrow: FilterPanel +collapses into a bottom-sheet drawer triggered by a "Filters" button; +ModelGrid drops to 2 columns; SearchBar and sort selector stack vertically. + +## Open Questions + +- **Infinite scroll vs. pagination.** Defaulting to infinite scroll (Load More + button at bottom) for a gallery feel; confirm before wireframing.[^3] +- **Filter taxonomy.** Category/tag list is unknown until models are generated; + defer to API design step. + +## References + +[^1]: Initial prompt — "browsable gallery of shared models with search, sort, + and filter controls" — [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^2]: INDEX.md — Explore tagged `backend`, ships as Coming Soon — + [`../INDEX.md`](../INDEX.md). +[^3]: Coming Soon placeholder design — + [`../coming-soon/SPEC.md`](../coming-soon/SPEC.md). From 0be322a7e0c2a7a8d541e872440df0d5935125e8 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:02:19 +0000 Subject: [PATCH 021/142] docs(pages): add leaderboards page spec --- docs/pages/leaderboards/SPEC.md | 112 ++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/docs/pages/leaderboards/SPEC.md b/docs/pages/leaderboards/SPEC.md index e69de29..59fa454 100644 --- a/docs/pages/leaderboards/SPEC.md +++ b/docs/pages/leaderboards/SPEC.md @@ -0,0 +1,112 @@ +--- +title: Leaderboards +slug: leaderboards +route: /leaderboards +tag: backend +status: draft +backend_dependent: yes +--- + +# Leaderboards + +## Summary + +Three ranked boards — Best Rated, Most Rated (Popular), and Most Viewed — each +filterable by four time buckets: 1 week, 1 month, 1 year, and all time.[^1] +The page ships as a Coming Soon placeholder until the shared backend exists. + +## Route & Access + +- **Route:** `/leaderboards` +- **Tag:** `backend` — ships as Coming Soon.[^2] +- **Preconditions:** None — leaderboards are publicly visible without login or + API key. + +## Users & Entry Points + +- **Discovery browsers** wanting to find the highest-quality or most popular + community models. +- **Competitive creators** checking where their own models rank. +- Entry from: NavBar (all pages), Home hero section (secondary link). + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Tabs[Board Tabs — Best Rated · Most Rated · Most Viewed] + Bucket[Time Bucket Selector — 1W · 1M · 1Y · All] + List[Ranked Model List — ordered entries with rank badge + metric] + Nav --> Tabs --> Bucket --> List +``` + +## Components + +- **BoardTabs** — three tabs selecting the active ranking metric. +- **TimeBucketSelector** — four toggle buttons (1W / 1M / 1Y / All); updates + URL param on selection. +- **RankedList** — ordered list of up to 50 `RankedModelCard` entries. +- **RankedModelCard** — rank badge (1–50), thumbnail, model title, author chip, + and the board's metric value (average rating / rating count / view count). +- **EmptyState** — "No models ranked yet for this period." +- **ComingSoonOverlay** — full-page overlay from + [`../coming-soon/SPEC.md`](../coming-soon/SPEC.md) shown until backend is live. + +## States + +| State | Trigger | Renders | +| ------------- | ------------------------------------ | ------------------------------------------------ | +| `coming-soon` | Backend not yet live | ComingSoonOverlay over ghost wireframe | +| `default` | Board data loaded | Tabs + Bucket selector + populated RankedList | +| `loading` | Fetch in flight after tab/bucket change | Tabs + Bucket + RankedList with skeleton rows | +| `empty` | No models qualify for this period | EmptyState message | +| `error` | Fetch failed | Inline error card with Retry button | + +## Interactions + +- **Click a BoardTab** → update `?board=` URL param → re-fetch rankings. +- **Click a TimeBucket button** → update `?period=` URL param → re-fetch. +- **Click a RankedModelCard** → navigate to `/m/:modelId`. +- **Click an author chip** → navigate to `/u/:username`. + +## Data + +- `boardType` — active board (rated|popular|viewed). `local` (URL param + `?board=`). +- `timeBucket` — active time window (1w|1m|1y|all). `local` (URL param + `?period=`). +- `rankings` — ordered list of model records with rank position and metric + value (id, title, thumbnailUrl, authorName, rank, metricValue). `remote`, + read-only. + +## Navigation + +**In-links:** NavBar (all pages); Home hero secondary link. + +**Out-links:** +- `/m/:modelId` — RankedModelCard click +- `/u/:username` — author chip click + +## Responsive + +Desktop (default): BoardTabs and TimeBucketSelector in a top bar row; +RankedList full-width below. Mobile/narrow: BoardTabs scroll horizontally; +TimeBucketSelector becomes a compact dropdown; RankedModelCard drops the +thumbnail, showing text-only rank + title + metric. + +## Open Questions + +- **List length.** Defaulting to top 50 per board/period; adjust once API + performance is known. +- **Tie-breaking.** When models share the same metric value, tie-break rule + (e.g., earlier creation date wins) is deferred to API design.[^3] + +## References + +[^1]: Initial prompt — "best rated (1w/1m/1y/all), most rated (aka popular) + (1w/1m/1y/all), most viewed (same buckets)" — + [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^2]: INDEX.md — Leaderboards tagged `backend`, ships as Coming Soon — + [`../INDEX.md`](../INDEX.md). +[^3]: Explore page for shared browse context — + [`../explore/SPEC.md`](../explore/SPEC.md). From 93be45bfce27b5c8c3e5d61c39b6f7ee983bae84 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:03:24 +0000 Subject: [PATCH 022/142] docs(pages): add generate page spec --- docs/pages/generate/SPEC.md | 144 ++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/docs/pages/generate/SPEC.md b/docs/pages/generate/SPEC.md index e69de29..7540712 100644 --- a/docs/pages/generate/SPEC.md +++ b/docs/pages/generate/SPEC.md @@ -0,0 +1,144 @@ +--- +title: Generate +slug: generate +route: /generate +tag: browser-only +status: draft +backend_dependent: no +--- + +# Generate + +## Summary + +The core feature page. Users enter a natural language prompt, configure model +parameters, answer AI-driven clarification questions when the prompt is +underspecified, and watch the live agent loop produce a 3D model.[^1] When no +API key is configured, the page prompts inline to connect one via Settings — +there is no separate onboarding page.[^2] + +## Route & Access + +- **Route:** `/generate` +- **Tag:** `browser-only` — runs entirely in the browser; all AI calls originate + from the client using the user's own Claude API key or OAuth token.[^1] +- **Preconditions (soft):** A Claude API key or OAuth token set in + [`../settings/SPEC.md`](../settings/SPEC.md). Without one, the page renders + a `no-key` banner rather than blocking navigation. + +## Users & Entry Points + +- **New creators** arriving from the Home CTA or NavBar. +- **Returning creators** bookmarking the page or navigating from My Library. +- **Remixers** arriving from Model Detail ("Generate similar"). +- May receive a deep-link with a pre-filled prompt via URL param `?prompt=`. + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Workspace[Generation Workspace] + Nav --> Workspace + Workspace --> Prompt[Prompt Bar — text area + Submit] + Workspace --> Params[Parameters Panel — collapsible sidebar] + Workspace --> Progress[Live Progress — agent-loop stream + 3D preview] + Workspace --> Result[Result View — viewer + Download · Save · Share] +``` + +## Components + +- **NoKeyBanner** — inline banner shown when no API key is set; links to + [`../settings/SPEC.md`](../settings/SPEC.md). +- **PromptBar** — multiline text area with a Submit / Generate button; accepts + optional `?prompt=` URL param to pre-fill. +- **ParametersPanel** — collapsible sidebar with controls for geometry + resolution, artistic style, and complexity level. +- **ClarificationDialog** — inline panel where the AI asks follow-up questions + when the prompt is underspecified; user answers before generation starts. +- **GenerationStream** — live scrolling feed of agent-loop steps (tokens, + tool calls, progress events) streamed via the Claude Agent SDK.[^3] +- **ModelPreview** — real-time 3D viewer that updates as geometry is produced. +- **ResultActions** — Download, Save to Library, and Share buttons shown after + generation completes. +- **ErrorPanel** — generation error description + Retry button. + +## States + +| State | Trigger | Renders | +| ------------- | ---------------------------------------- | --------------------------------------------------------------- | +| `no-key` | No API key/OAuth token in storage | NoKeyBanner above PromptBar; Generate button disabled | +| `idle` | Key set, no active generation | PromptBar + ParametersPanel; Generate button enabled | +| `specifying` | Prompt submitted, AI needs clarification | ClarificationDialog; PromptBar locked | +| `generating` | Generation agent loop running | GenerationStream + live ModelPreview; Cancel button available | +| `complete` | Model geometry produced | ModelPreview (final) + ResultActions | +| `error` | Generation failed or cancelled | ErrorPanel with error detail + Retry button | + +## Interactions + +- **Type in PromptBar** → enables Generate button (if key is set). +- **Click "Connect key" in NoKeyBanner** → navigate to `/settings?return=/generate`. +- **Submit prompt** (complete, well-specified) → enter `generating` state. +- **Submit prompt** (underspecified) → enter `specifying`; AI poses questions. +- **Answer clarification question** → next question or auto-start generation. +- **Click Cancel during generation** → abort agent loop → enter `error` state + with "Cancelled" message. +- **Click Download** → trigger browser download of the generated geometry file. +- **Click Save to Library** → persist model record to local browser storage → + navigate to [`../my-library/SPEC.md`](../my-library/SPEC.md). +- **Click Share** → open share dialog (publish model to backend, copy URL); + shows coming-soon state for sharing until backend exists. +- **Click Retry** → re-run generation with same prompt and parameters. +- **Click New** → clear result and stream → return to `idle`. + +## Data + +- `apiKey` — Claude API key or OAuth token. `local` (browser storage, never + sent to farish servers). +- `prompt` — active natural language description. `local` (session draft). +- `parameters` — model config (resolution, style, complexity). `local` + (persisted in browser storage across sessions). +- `clarificationHistory` — the AI's questions and the user's answers. `local` + (session only). +- `generationStream` — live agent-loop step events. `local` (streamed, session). +- `generatedModel` — completed model (geometry blob URL, prompt, params, + thumbnail). `local` (held in memory; written to library on "Save"). + +## Navigation + +**In-links:** Home primary CTA; NavBar "Generate" link; Model Detail "Generate +similar" button; My Library empty-state CTA. + +**Out-links:** +- `/settings` — NoKeyBanner link (with `?return=/generate`) +- `/library` — after "Save to Library" +- `/m/:modelId` — after "Share" publishes model (backend-gated) + +## Responsive + +Desktop (default): ParametersPanel as a collapsible left sidebar (~280 px); +PromptBar and Progress occupy the center column; ResultActions appear below the +preview. Mobile: ParametersPanel collapses into a bottom-sheet drawer; PromptBar +is full-width at the bottom of the screen; progress stream and 3D preview stack +vertically above it. + +## Open Questions + +- **3D output format.** GLB (binary glTF) is assumed as the interchange format + for broad browser/viewer support — confirm during API design.[^4] +- **Clarification: before vs. during generation.** Current plan is to pause and + ask before starting the agent loop; consider streaming clarification inline + during generation for faster UX. +- **Share without backend.** The Share action is coming-soon until the backend + exists; the button should be visible but show the ComingSoon state on click. + +## References + +[^1]: Initial prompt — core Generate feature: "enter a prompt … the AI will + generate a 3d model … with a pause for specifications if not already + provided" — [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^2]: INDEX.md — "Generate prompts inline to connect a key … no separate + onboarding page" — [`../INDEX.md`](../INDEX.md). +[^3]: Claude Agent SDK — used for streaming the generation loop — + . +[^4]: glTF 2.0 spec — . From 59d979b8204fe5cf99be14fa8d0af1fe8b7d12a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:04:32 +0000 Subject: [PATCH 023/142] docs(pages): add model-detail page spec --- docs/pages/model-detail/SPEC.md | 140 ++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/docs/pages/model-detail/SPEC.md b/docs/pages/model-detail/SPEC.md index e69de29..637311f 100644 --- a/docs/pages/model-detail/SPEC.md +++ b/docs/pages/model-detail/SPEC.md @@ -0,0 +1,140 @@ +--- +title: Model Detail +slug: model-detail +route: /m/:modelId +tag: browser-only +status: draft +backend_dependent: partial +--- + +# Model Detail + +## Summary + +An interactive 3D viewer for a single model alongside its prompt, parameters, +and metadata. The viewer runs entirely client-side for both local (browser- +stored) and remote models. Social actions — rating and sharing — require the +backend and ship as Coming Soon until it is available.[^1] + +## Route & Access + +- **Route:** `/m/:modelId` — `:modelId` is either a remote UUID (from the + backend) or a local identifier prefixed `local:` (from browser storage).[^2] +- **Tag:** `browser-only` (viewer); social actions are `backend` (partial). +- **Preconditions:** The model identified by `:modelId` must exist either in + browser storage or be publicly accessible on the backend. A missing model + triggers the `error` state. + +## Users & Entry Points + +- **Creators** viewing their own model after generation or from My Library. +- **Community members** clicking through from Explore, Leaderboards, or a + shared link. +- **Remixers** wanting to generate a similar model. +- Entry from: [`../generate/SPEC.md`](../generate/SPEC.md) (post-save), + [`../my-library/SPEC.md`](../my-library/SPEC.md) (card click), + [`../explore/SPEC.md`](../explore/SPEC.md) (card click), + [`../leaderboards/SPEC.md`](../leaderboards/SPEC.md) (card click), + [`../profile/SPEC.md`](../profile/SPEC.md) (card click), direct URL share. + +## Layout + +```mermaid +flowchart LR + Nav[Navigation Bar] + Viewer[3D Viewer — interactive orbit/pan/zoom canvas] + Info[Info Panel — prompt · parameters · metadata · author] + Actions[Action Bar — Download · Save · Rate · Share · Generate Similar] + Nav --> Viewer + Nav --> Info + Viewer --- Actions + Info --- Actions +``` + +## Components + +- **ThreeDViewer** — WebGL canvas with orbit, pan, and zoom controls; renders + the model geometry (expected format: GLB).[^3] +- **ViewerControls** — camera-reset, fullscreen, and lighting-preset toggle + buttons overlaid on the viewer. +- **PromptDisplay** — read-only display of the prompt used to generate the model. +- **ParamsDisplay** — collapsible panel showing generation parameters + (resolution, style, complexity). +- **MetadataPanel** — author chip, creation date, view count, average rating. +- **AuthorChip** — author avatar + name; links to + [`../profile/SPEC.md`](../profile/SPEC.md) (coming-soon state until backend). +- **DownloadButton** — triggers browser download of the geometry file. +- **SaveButton** — writes model record to local browser storage (My Library). +- **RatingWidget** — 5-star input; shows coming-soon overlay (backend-gated). +- **ShareButton** — copies canonical URL or shows coming-soon overlay. +- **GenerateSimilarButton** — navigates to `/generate?prompt=`. + +## States + +| State | Trigger | Renders | +| ------------- | ------------------------------------ | -------------------------------------------------------------- | +| `local` | `:modelId` starts with `local:` | Viewer + Info from browser storage; no remote fetch | +| `loading` | Remote model fetch in flight | Skeleton viewer + shimmer on Info panel | +| `default` | Remote model loaded | Viewer + Info panel + Action bar | +| `error` | Model not found or fetch failed | Error card "Model not found" with Back and Retry buttons | +| `coming-soon` | Rate or Share clicked, no backend | ComingSoonOverlay from [`../coming-soon/SPEC.md`](../coming-soon/SPEC.md) | + +## Interactions + +- **Orbit / pan / zoom in viewer** → camera transforms; geometry stays fixed. +- **Click camera-reset** → snap back to default camera position. +- **Click fullscreen** → expand viewer to fill the viewport. +- **Click Download** → trigger browser download of the GLB geometry file. +- **Click Save to Library** → write model record to local browser storage. +- **Click Rate** → coming-soon overlay (backend-gated). +- **Click Share** → copy URL to clipboard if model is already published; else + coming-soon overlay. +- **Click Generate Similar** → navigate to + `/generate?prompt=`. +- **Click author chip** → navigate to `/u/:username` (coming-soon state on + Profile until backend). + +## Data + +- `model` — model record (id, prompt, params, geometryUrl, thumbnailUrl, + authorName, authorId, createdAt, viewCount, ratingAvg, ratingCount). + `remote` for shared models; `local` for browser-stored models. +- `viewerSettings` — camera position and active lighting preset. `local` + (browser storage; persisted across sessions). +- `userRating` — the current user's own star rating. `remote`, write + (backend-gated; null until backend exists). + +## Navigation + +**In-links:** Generate (post-save redirect); My Library (card click); Explore, +Leaderboards, Profile (card clicks); direct shared URL. + +**Out-links:** +- `/generate` — Generate Similar button (with `?prompt=`) +- `/library` — Save to Library confirmation +- `/u/:username` — AuthorChip +- `/explore` — browser back or "Back to Explore" breadcrumb + +## Responsive + +Desktop (default): ThreeDViewer occupies ~65 % of the width; Info panel is a +fixed right sidebar; Action bar sits at the viewer's bottom edge. Mobile/narrow: +viewer goes full-width at top; Info and Actions collapse into accordion sections +below; sticky Download button pinned to the bottom of the screen. + +## Open Questions + +- **Local model URL scheme.** How is `local:` prefixed in the URL? Consider + a dedicated sub-route `/m/local/:localId` to keep URL parsing clean.[^4] +- **View count increment.** Should viewing a local model increment a view + counter when the model is also published remotely? Deferred to API design. + +## References + +[^1]: INDEX.md — "browser-only viewer, backend social" dual nature — + [`../INDEX.md`](../INDEX.md). +[^2]: Initial prompt — "interactive 3D viewer … download, share, and rating + actions" — [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^3]: glTF 2.0 / GLB format — . +[^4]: My Library spec for local model storage — + [`../my-library/SPEC.md`](../my-library/SPEC.md). From bed48773db64599d594b2c0665730fdd7ad0335f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:05:05 +0000 Subject: [PATCH 024/142] chore: track farish-build orchestration task MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the orchestration task record to farish/.claude/tasks/ — the committed flat task store. Task records belong in the repo (the task-utils MCP server auto-commits them by design); my prior records were wrongly kept in the legacy ~/.claude/tasks// location. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/tasks/farish-build.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .claude/tasks/farish-build.json diff --git a/.claude/tasks/farish-build.json b/.claude/tasks/farish-build.json new file mode 100644 index 0000000..17d8989 --- /dev/null +++ b/.claude/tasks/farish-build.json @@ -0,0 +1,9 @@ +{ + "id": "farish-build", + "subject": "Build the farish AI 3D-model generator - drive prompt steps 1-37 (nsheaps/farish#1)", + "activeForm": "Building the farish AI 3D-model generator (nsheaps/farish#1)", + "status": "in_progress", + "description": "Orchestration task tracking the whole farish build per docs/INITIAL_PROMPT.md.\n\n## Progress\n- Steps 1-4: Claude Code config, marketplaces, plugins, web-onboarding hook, rules - done.\n- Steps 5-10: page index (docs/pages/INDEX.md, 11 pages), empty per-page SPEC.md scaffolds, PAGE-SPEC.md meta-spec - done.\n- Step 11: spec-writing skill + 3 subskills - done.\n- Step 12: writing all 11 page specs with the spec-writing skill - in progress (see step-12-page-specs.json).\n- Side: task-utils MCP task server built + CI fixed on nsheaps/agents PR #157; local-checkout marketplaces configured.\n\n## Next\n- Step 13: review page specs as a whole. Steps 14-20: wireframing + API specs. Step 21+: code.\n\n## 2026-05-21T05:04:53Z - record created in farish/.claude/tasks/ (committed flat store) per handler direction; prior records were wrongly in legacy ~/.claude/tasks//.", + "createdAt": "2026-05-21T05:04:53Z", + "updatedAt": "2026-05-21T05:04:53Z" +} From 891e02031dc8e6cb9382a1fcd1992044173af971 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:05:17 +0000 Subject: [PATCH 025/142] docs(pages): add my-library page spec --- docs/pages/my-library/SPEC.md | 119 ++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/docs/pages/my-library/SPEC.md b/docs/pages/my-library/SPEC.md index e69de29..e015819 100644 --- a/docs/pages/my-library/SPEC.md +++ b/docs/pages/my-library/SPEC.md @@ -0,0 +1,119 @@ +--- +title: My Library +slug: my-library +route: /library +tag: browser-only +status: draft +backend_dependent: no +--- + +# My Library + +## Summary + +The current user's personal collection of generated models, stored in browser +local storage. The library works fully offline and without a backend account — +no sign-in is required. Models can be viewed, downloaded, deleted, or (once the +backend exists) shared directly from this page.[^1] + +## Route & Access + +- **Route:** `/library` +- **Tag:** `browser-only` — reads and writes only to browser local storage.[^2] +- **Preconditions:** None. An API key is not required to view previously saved + models; it is only needed to generate new ones. + +## Users & Entry Points + +- **Creators** who have generated one or more models and want to manage them. +- **Returners** who saved a model in a prior session and want to retrieve it. +- Entry from: [`../generate/SPEC.md`](../generate/SPEC.md) ("Save to Library" + action); [`../model-detail/SPEC.md`](../model-detail/SPEC.md) (Save action); + NavBar "Library" link. + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Header[Library Header — title · sort selector · Clear All button] + Grid[Model Grid — LibraryModelCard per saved model] + Empty[Empty State — illustration + Generate CTA] + Nav --> Header --> Grid + Header -. no models .-> Empty +``` + +## Components + +- **LibraryHeader** — page title ("My Library"), sort dropdown, and a + "Clear All" button that triggers a confirmation dialog. +- **ModelGrid** — responsive card grid; switches to `EmptyState` when the + library is empty. +- **LibraryModelCard** — model thumbnail, title, creation date, and an actions + menu (View, Download, Delete). +- **EmptyState** — illustrative placeholder with a "Generate your first model" + CTA linking to [`../generate/SPEC.md`](../generate/SPEC.md). +- **DeleteConfirmDialog** — modal asking the user to confirm before removing a + model from storage. + +## States + +| State | Trigger | Renders | +| --------- | -------------------------------- | ------------------------------------------------ | +| `default` | One or more models in storage | LibraryHeader + populated ModelGrid | +| `empty` | No models in browser storage | LibraryHeader (no Clear All) + EmptyState | +| `loading` | Storage read in progress (brief) | LibraryHeader + skeleton card grid | + +## Interactions + +- **Click a LibraryModelCard** → navigate to `/m/local:`. +- **Click Download in card actions** → trigger browser download of the GLB + geometry file. +- **Click Delete in card actions** → open DeleteConfirmDialog. +- **Confirm delete** → remove model from storage → update grid; if last model, + switch to `empty` state. +- **Change sort selector** → re-order grid in place (no fetch). +- **Click Clear All** → confirmation dialog → clear all models from storage → + switch to `empty` state. +- **Click Generate CTA** (empty state) → navigate to `/generate`. + +## Data + +- `libraryModels` — list of saved model records (id, prompt, thumbnailUrl, + geometryBlob, params, createdAt). `local` (browser storage), read/write. +- `sortPreference` — active sort order (date-desc | date-asc | name-asc). + `local` (persisted preference, browser storage). + +## Navigation + +**In-links:** Generate ("Save to Library" post-action); Model Detail (Save +action); NavBar "Library" link. + +**Out-links:** +- `/m/local:` — LibraryModelCard click +- `/generate` — EmptyState CTA + +## Responsive + +Desktop (default): 3–4 column ModelGrid. Mobile/narrow: 2-column grid; +LibraryModelCard actions exposed via a long-press menu or a swipe-to-reveal +action strip. + +## Open Questions + +- **Cross-device sync.** Should the library sync to the backend once a user + is signed in? Deferred to post-backend implementation; the local-only model + must remain the foundation.[^3] +- **Storage quota.** Geometry blobs can be large; the page should gracefully + handle `QuotaExceededError` from the storage API — surface in Open Questions + for the implementation step. + +## References + +[^1]: INDEX.md — "current user's own generated models, stored in the browser + so the library works offline and without an account" — + [`../INDEX.md`](../INDEX.md). +[^2]: Initial prompt — browser-only constraint; backend deferred — + [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^3]: Model Detail for the local model URL scheme — + [`../model-detail/SPEC.md`](../model-detail/SPEC.md). From 022bde8f0e6774050bfab66561dc73e69621ac45 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:05:59 +0000 Subject: [PATCH 026/142] docs(pages): add profile page spec --- docs/pages/profile/SPEC.md | 113 +++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/docs/pages/profile/SPEC.md b/docs/pages/profile/SPEC.md index e69de29..280d9a4 100644 --- a/docs/pages/profile/SPEC.md +++ b/docs/pages/profile/SPEC.md @@ -0,0 +1,113 @@ +--- +title: Profile +slug: profile +route: /u/:username +tag: backend +status: draft +backend_dependent: yes +--- + +# Profile + +## Summary + +A public profile page showing a creator's shared models alongside summary +stats — total models shared, average rating received, and cumulative view +count. The page ships as a Coming Soon placeholder until the shared backend +exists.[^1] + +## Route & Access + +- **Route:** `/u/:username` — `:username` is the creator's public handle. +- **Tag:** `backend` — ships as Coming Soon; requires the shared model store + and user account system.[^2] +- **Preconditions:** None — profiles are publicly visible without login. + The `:username` must resolve to an existing account; an unknown username + triggers the `error` state. + +## Users & Entry Points + +- **Fans and collaborators** wanting to see all shared work by a specific + creator. +- **Creators** checking their own public presence. +- Entry from: [`../model-detail/SPEC.md`](../model-detail/SPEC.md) (author + chip); [`../explore/SPEC.md`](../explore/SPEC.md) (author chip); + [`../leaderboards/SPEC.md`](../leaderboards/SPEC.md) (author chip). + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Header[Profile Header — avatar · username · join date · stats row] + Grid[Model Grid — user's shared ModelCards] + Empty[Empty State — no shared models yet] + Nav --> Header --> Grid + Header -. zero models .-> Empty +``` + +## Components + +- **ProfileHeader** — avatar image, display name, username handle, join date, + and a stats row (model count, average rating, total views). +- **StatsBadge** — individual stat chip reused within ProfileHeader. +- **ModelGrid** — responsive grid of `ModelCard` showing the user's public + models, newest first by default. +- **ModelCard** — thumbnail, title, rating, views; links to + [`../model-detail/SPEC.md`](../model-detail/SPEC.md). +- **EmptyState** — "No shared models yet" message. +- **ComingSoonOverlay** — full-page overlay from + [`../coming-soon/SPEC.md`](../coming-soon/SPEC.md) shown until backend is live. + +## States + +| State | Trigger | Renders | +| ------------- | -------------------------------- | --------------------------------------------------- | +| `coming-soon` | Backend not yet live | ComingSoonOverlay over ghost wireframe | +| `loading` | Profile data fetch in flight | Skeleton ProfileHeader + skeleton ModelGrid | +| `default` | Profile and models loaded | ProfileHeader + populated ModelGrid | +| `empty` | User has no shared models | ProfileHeader + EmptyState message | +| `error` | Username not found / fetch fails | Error card "Profile not found" with Home link | + +## Interactions + +- **Click a ModelCard** → navigate to `/m/:modelId`. +- **Click author in ModelCard** → same page if same user (no-op or scroll top). + +## Data + +- `userProfile` — user record (username, displayName, avatarUrl, joinDate, + modelCount, avgRating, totalViews). `remote`, read-only. +- `userModels` — paginated list of the user's shared models (id, title, + thumbnailUrl, ratingAvg, viewCount, createdAt). `remote`, read-only. + +## Navigation + +**In-links:** Model Detail author chip; Explore author chip; Leaderboards +author chip. + +**Out-links:** +- `/m/:modelId` — ModelCard click + +## Responsive + +Desktop (default): ProfileHeader full-width banner with stats inline; +ModelGrid 3–4 columns. Mobile/narrow: avatar and stats stack vertically; +ModelGrid drops to 2 columns. + +## Open Questions + +- **Username source.** Is the public handle derived from the Claude OAuth + account name, or is it a separate farish-specific field? Deferred to + authentication design.[^3] +- **Pagination.** How many models per page? Default to 24 with a Load More + button; confirm during API design. + +## References + +[^1]: INDEX.md — "public user's models and stats … backend" — + [`../INDEX.md`](../INDEX.md). +[^2]: Initial prompt — social/sharing features require shared backend — + [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^3]: Settings spec for authentication/connection model — + [`../settings/SPEC.md`](../settings/SPEC.md). From 62cba77d434df23df52202f95ec113f2b1c6bcfd Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:06:57 +0000 Subject: [PATCH 027/142] docs(pages): add settings page spec --- docs/pages/settings/SPEC.md | 136 ++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/docs/pages/settings/SPEC.md b/docs/pages/settings/SPEC.md index e69de29..83d3f18 100644 --- a/docs/pages/settings/SPEC.md +++ b/docs/pages/settings/SPEC.md @@ -0,0 +1,136 @@ +--- +title: Settings +slug: settings +route: /settings +tag: browser-only +status: draft +backend_dependent: no +--- + +# Settings + +## Summary + +The Settings page is the login and key-management surface for farish — there is +no separate Login page.[^1] Users connect a Claude account via OAuth or enter an +API key manually. All credentials are stored in the browser and never sent to +farish servers. Preferences (theme, default generation parameters) and a +local-data management section complete the page. + +## Route & Access + +- **Route:** `/settings` +- **Tag:** `browser-only` — reads and writes only to browser local storage.[^2] +- **Preconditions:** None. Any visitor may view and update settings without + being connected. The page accepts a `?return=` query param so Generate's + NoKeyBanner can deep-link back after a successful connection. + +## Users & Entry Points + +- **New users** directed from Generate's `no-key` NoKeyBanner. +- **Connected users** wanting to change their key or update preferences. +- Entry from: [`../generate/SPEC.md`](../generate/SPEC.md) (NoKeyBanner); + NavBar Settings icon (all pages); [`../about/SPEC.md`](../about/SPEC.md) + (credential-privacy section link). + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Connect[Connection Section — OAuth button · API key input · status] + Storage[Storage Note — where credentials live, privacy guarantee] + Prefs[Preferences — theme toggle · default generation params] + Danger[Danger Zone — Clear All Data] + Nav --> Connect --> Storage --> Prefs --> Danger +``` + +## Components + +- **ConnectionStatus** — banner showing "Connected as \" (OAuth) or + "API key set" (manual) or "Not connected". +- **ConnectWithClaudeButton** — initiates the Claude OAuth flow.[^3] +- **APIKeyInput** — password-type text input with show/hide toggle and a Save + button; accepts a `sk-ant-…` format API key. +- **DisconnectButton** — clears all stored credentials; shown only when + connected. +- **StorageNote** — plain-prose explanation that credentials are stored in + `localStorage` and never transmitted to farish servers. +- **ThemeToggle** — light / dark / system three-way toggle. +- **DefaultParamsEditor** — sliders and selects for default resolution, style, + and complexity (mirrors ParametersPanel in Generate). +- **ClearDataButton** — triggers a confirmation dialog then wipes all browser + storage (credentials, library, preferences). + +## States + +| State | Trigger | Renders | +| ----------------- | ------------------------------- | ---------------------------------------------------- | +| `disconnected` | No token or key in storage | ConnectWithClaudeButton + APIKeyInput (empty) | +| `connecting` | OAuth popup opened | Loading indicator on ConnectWithClaudeButton | +| `connected-oauth` | OAuth token stored | ConnectionStatus (name) + DisconnectButton | +| `connected-key` | Manual API key stored | ConnectionStatus ("API key set") + DisconnectButton | +| `error` | OAuth failed or key rejected | Inline error message below the relevant control | + +## Interactions + +- **Click Connect with Claude** → open OAuth popup/redirect → on success, store + token → switch to `connected-oauth`; on failure, show `error`. +- **Enter API key + click Save** → validate key prefix format → store in + `localStorage` → switch to `connected-key`; if invalid format, show error. +- **Click Disconnect** → clear token/key from storage → switch to + `disconnected`; library and preferences are NOT cleared. +- **Toggle theme** → persist choice → apply CSS class immediately (no reload). +- **Edit DefaultParams** → auto-save to storage on blur/change. +- **Click Clear All Data** → confirmation dialog → wipe entire + `localStorage` for farish → redirect to `/` with a cleared-session notice. +- **Successful connection with `?return=` param** → redirect to the return URL + after storing credentials. + +## Data + +- `apiToken` — Claude OAuth access token OR manual API key string. `local` + (browser storage; stored securely, never logged or transmitted). +- `connectionType` — active connection method (oauth | manual | none). `local`. +- `connectedUsername` — display name from the Claude OAuth response (null for + manual key). `local`. +- `theme` — active theme preference (light | dark | system). `local`. +- `defaultParams` — default generation parameters object. `local`. + +## Navigation + +**In-links:** Generate NoKeyBanner (with `?return=/generate`); NavBar +Settings icon; About credential-privacy link. + +**Out-links:** +- `?return=` target URL — after successful connection +- `/about` — credential-privacy details link + +## Responsive + +Desktop (default): settings content in a centered container (max-width ~640 px); +section headings and controls laid out with generous spacing. Mobile/narrow: +container goes full-width; OAuth button and APIKeyInput span full width; +DefaultParamsEditor sliders become larger touch targets. + +## Open Questions + +- **Claude OAuth availability.** The initial prompt notes "preferably + login-with-Claude but I think they'll need to provide a token".[^4] Confirm + whether Anthropic exposes a public OAuth flow; API-key fallback is the safe + default. +- **Key format validation.** Validating only the `sk-ant-` prefix client-side + is lightweight but can show false positives. Accept this trade-off and let + the first actual API call surface a bad key. + +## References + +[^1]: INDEX.md — "Settings is the connect surface — no separate Login page" — + [`../INDEX.md`](../INDEX.md). +[^2]: Initial prompt — "user can input their claude-code api key or oauth api + key" and browser-only storage requirement — + [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^3]: Claude API key documentation — + . +[^4]: Initial prompt amendment A3 context; "preferably login-with-claude" — + [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). From 3e84f556d4f14010d5e3cdb42ed1455333006040 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:07:46 +0000 Subject: [PATCH 028/142] docs(pages): add about page spec --- docs/pages/about/SPEC.md | 106 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/docs/pages/about/SPEC.md b/docs/pages/about/SPEC.md index e69de29..264b120 100644 --- a/docs/pages/about/SPEC.md +++ b/docs/pages/about/SPEC.md @@ -0,0 +1,106 @@ +--- +title: About +slug: about +route: /about +tag: static +status: draft +backend_dependent: no +--- + +# About + +## Summary + +A narrative page covering three topics: the history of William Farish and +isometric projection that inspired the project name; a plain-language +explanation of how AI model generation works; and the credential privacy +model — why users' API keys are safe.[^1] No dynamic data; the page is fully +static. + +## Route & Access + +- **Route:** `/about` +- **Tag:** `static` — no backend or API key required.[^2] +- **Preconditions:** None. Publicly accessible to any visitor. + +## Users & Entry Points + +- **Curious visitors** wanting context on the project's name and purpose. +- **Privacy-conscious users** investigating how credentials are handled before + connecting a key. +- Entry from: Footer "About" link (all pages); [`../settings/SPEC.md`](../settings/SPEC.md) + credential-privacy detail link. + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Hero[About Hero — project name and one-sentence tagline] + History[William Farish — history of isometric projection, 1822] + HowItWorks[How Generation Works — agent-loop diagram + prose] + Privacy[Credential Privacy — local-only key storage explanation] + SettingsCTA[CTA — Connect a key in Settings] + Footer[Footer] + Nav --> Hero --> History --> HowItWorks --> Privacy --> SettingsCTA --> Footer +``` + +## Components + +- **AboutHero** — page heading ("About farish") and a one-sentence tagline + describing the project. +- **FarishHistory** — prose section about William Farish (1759–1837) and his + 1822 formalization of isometric projection; explains why the project is named + after him.[^3] +- **GenerationDiagram** — Mermaid sequence diagram illustrating the generation + loop: user prompt → Claude Agent SDK → tool calls → geometry output → viewer. +- **HowItWorksProse** — brief plain-language companion text to the diagram. +- **PrivacySection** — explanation that API keys and OAuth tokens are stored + in `localStorage` on the user's device and are never transmitted to farish + servers. +- **SettingsCTA** — secondary CTA button "Connect your key in Settings" linking + to [`../settings/SPEC.md`](../settings/SPEC.md). + +## States + +| State | Trigger | Renders | +| --------- | ---------- | ------------------ | +| `default` | Page loads | Full static content | + +## Interactions + +- **Click SettingsCTA** → navigate to `/settings`. +- **NavBar links** → navigate to the respective page. + +## Data + +_None._ The page is fully static — no local or remote data dependencies. + +## Navigation + +**In-links:** Footer "About" link (all pages); Settings "learn more" credential +privacy link. + +**Out-links:** +- `/settings` — SettingsCTA button + +## Responsive + +Desktop (default): content in a centered reading column (max-width ~720 px) +with comfortable line length. GenerationDiagram renders at full column width. +Mobile/narrow: full-width single column; diagram scrolls horizontally if wider +than the viewport. + +## Open Questions + +_None._ + +## References + +[^1]: Initial prompt — "project background — William Farish and the history of + isometric projection — how generation works, and the credential-privacy + explanation" — [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^2]: INDEX.md — About tagged `static` — + [`../INDEX.md`](../INDEX.md). +[^3]: William Farish (scientist), Wikipedia — + . From 232592528a7e9c7495e7ff4721226ff8ef856993 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:08:31 +0000 Subject: [PATCH 029/142] docs(pages): add coming-soon page spec --- docs/pages/coming-soon/SPEC.md | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/docs/pages/coming-soon/SPEC.md b/docs/pages/coming-soon/SPEC.md index e69de29..ca2e674 100644 --- a/docs/pages/coming-soon/SPEC.md +++ b/docs/pages/coming-soon/SPEC.md @@ -0,0 +1,113 @@ +--- +title: Coming Soon +slug: coming-soon +route: /coming-soon +tag: system +status: draft +backend_dependent: no +--- + +# Coming Soon + +## Summary + +A reusable placeholder for backend-dependent pages before the shared backend +exists. It renders a ghost wireframe of the target page (populated with mock +data and placeholder thumbnails) behind a centered "Coming Soon" overlay card. +The preferred pattern is an in-page overlay so the user stays on the target +route; `/coming-soon` exists as a direct fallback route.[^1] + +## Route & Access + +- **Route:** `/coming-soon` — direct fallback route; also used as an in-page + overlay component rendered by backend-dependent pages at their own routes. +- **Tag:** `system` — infrastructure page, no data dependency.[^2] +- **Preconditions:** None. + +## Users & Entry Points + +- **Any user** who navigates to a backend-dependent page (Explore, Leaderboards, + Profile) before the backend is live. The target page renders this overlay at + its own URL rather than redirecting. +- Entry from: [`../explore/SPEC.md`](../explore/SPEC.md) (in-page overlay); + [`../leaderboards/SPEC.md`](../leaderboards/SPEC.md) (in-page overlay); + [`../profile/SPEC.md`](../profile/SPEC.md) (in-page overlay); any internal + link that would reach a backend-gated feature. + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Ghost[Ghost Wireframe — blurred/dimmed mock rendering of the target page] + Overlay[Coming Soon Card — centered over the ghost wireframe] + Nav --> Ghost + Ghost --> Overlay + Overlay --> Icon[Rocket or clock icon] + Overlay --> Headline[Page title + 'is coming soon'] + Overlay --> Note[One-sentence explanation] + Overlay --> HomeButton[Back to Home button] +``` + +## Components + +- **GhostWireframe** — a dimmed (e.g. 30 % opacity, blurred) rendering of the + target page using hardcoded mock data (lorem ipsum titles, placeholder + thumbnail images). Makes the future design tangible without real data. +- **ComingSoonCard** — centered modal-style card containing the icon, headline, + note, and action button. Not dismissible. +- **HomeButton** — secondary button navigating to `/`. +- **PageIcon** — contextual icon representing the target page category + (e.g. gallery icon for Explore, trophy for Leaderboards). + +## States + +| State | Trigger | Renders | +| --------- | ---------- | --------------------------------------------------- | +| `default` | Page loads | Ghost wireframe + ComingSoonCard overlay (centered) | + +## Interactions + +- **Click Back to Home** → navigate to `/`. +- **NavBar links** → navigate to the respective page normally. + +## Data + +- `targetPageName` — the human-readable name of the coming-soon page (e.g. + "Explore"). `local` (passed as a route param or component prop). +- Ghost wireframe mock data is hardcoded static content — no storage or + remote call. + +## Navigation + +**In-links:** Explore, Leaderboards, and Profile pages render this as an +in-page overlay at their own routes. The `/coming-soon` route is a direct +fallback. + +**Out-links:** +- `/` — HomeButton + +## Responsive + +Desktop (default): ghost wireframe fills the viewport below the NavBar; +ComingSoonCard is centered with ~480 px max-width. Mobile/narrow: card +occupies most of the viewport width; ghost wireframe is less prominent +(lower opacity or replaced with a solid dimmed background). + +## Open Questions + +- **Overlay vs. redirect.** The in-page overlay pattern (stays on `/explore`, + `/leaderboards`, `/u/:username`) is preferred because it shows users what the + page will look like. Confirm this over a full redirect to `/coming-soon`.[^3] +- **Mock data freshness.** The ghost wireframe uses static mock thumbnails and + titles. These should be visually plausible but need no maintenance; confirm + during wireframing step. + +## References + +[^1]: Initial prompt — "a reusable placeholder … ghost wireframe rendered with + mock data behind it" — [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^2]: INDEX.md — Coming Soon tagged `system` — + [`../INDEX.md`](../INDEX.md). +[^3]: Explore spec for context on how the overlay is used — + [`../explore/SPEC.md`](../explore/SPEC.md). From 12a9a0150f9aeb5b372ff89b906a09ba8fed04bb Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:09:07 +0000 Subject: [PATCH 030/142] docs(pages): add not-found page spec --- docs/pages/not-found/SPEC.md | 97 ++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/docs/pages/not-found/SPEC.md b/docs/pages/not-found/SPEC.md index e69de29..4c8e510 100644 --- a/docs/pages/not-found/SPEC.md +++ b/docs/pages/not-found/SPEC.md @@ -0,0 +1,97 @@ +--- +title: Not Found +slug: not-found +route: /* +tag: system +status: draft +backend_dependent: no +--- + +# Not Found + +## Summary + +The 404 page rendered for any route that does not match a known page. Keeps +the experience friendly and recoverable — a clear error message, a primary +link back to Home, and a secondary suggestion to search Explore.[^1] + +## Route & Access + +- **Route:** `/*` — Vue Router catch-all; matched when no other route applies. +- **Tag:** `system` — infrastructure page, no data dependency.[^2] +- **Preconditions:** None. + +## Users & Entry Points + +- **Users** who typed an incorrect URL or followed a stale/broken link. +- **Bots** crawling non-existent paths. +- No specific entry referrer — any unknown URL triggers this page. + +## Layout + +```mermaid +flowchart TB + Nav[Navigation Bar] + Illustration[404 Illustration — geometric / isometric icon] + Headline[Headline — Page not found] + Message[Message — friendly one-liner + attempted URL] + HomeButton[Home Button — primary CTA] + ExploreLink[Explore Link — secondary suggestion] + Nav --> Illustration --> Headline --> Message --> HomeButton --> ExploreLink +``` + +## Components + +- **NotFoundIllustration** — an isometric or geometric graphic evoking the + project's aesthetic; displays the numeral "404" or equivalent. +- **NotFoundHeadline** — "Page not found" in the site's heading typeface. +- **NotFoundMessage** — one-sentence friendly explanation, optionally showing + the attempted path (e.g., "We couldn't find `{path}`"). +- **HomeButton** — primary button linking to `/`. +- **ExploreLink** — secondary text link: "Try searching in Explore" linking + to `/explore`. + +## States + +| State | Trigger | Renders | +| --------- | --------------------- | ------------------------------------------------- | +| `default` | Unknown route matched | Illustration + Headline + Message + action buttons | + +## Interactions + +- **Click HomeButton** → navigate to `/`. +- **Click ExploreLink** → navigate to `/explore`. + +## Data + +_None._ The attempted path may be read from the router for display in +`NotFoundMessage` but is not persisted or sent anywhere. + +## Navigation + +**In-links:** Any broken or unknown URL navigated by the browser or router. + +**Out-links:** +- `/` — HomeButton +- `/explore` — ExploreLink + +## Responsive + +Desktop (default): content centered vertically and horizontally; illustration +above the text block. Mobile/narrow: same layout; illustration scales down to +fit; buttons go full-width. + +## Open Questions + +- **Route suggestion.** Should the page attempt to surface the nearest matching + route? Deferred — too complex for v1; a simple Home + Explore pair is + sufficient.[^3] + +## References + +[^1]: Initial prompt — "Not Found — The 404 page for unknown routes" — + [`../INITIAL_PROMPT.md`](../INITIAL_PROMPT.md). +[^2]: INDEX.md — Not Found tagged `system` — + [`../INDEX.md`](../INDEX.md). +[^3]: Vue Router catch-all route documentation — + . From e9299fbf360f0a6357e5d227e6b122432ad508f2 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:18:12 +0000 Subject: [PATCH 031/142] docs(specs): fix cross-spec navigation inconsistencies (step 13) - home: add secondary hero CTAs to Explore and Leaderboards; align out-links to match what Explore/Leaderboards specs list as in-links - model-detail: add Home TrendingStrip as a missing in-link entry point - explore: rename Model Detail in-link from "Explore more" to "Back to Explore" breadcrumb to match the Model Detail spec's out-link label - about: narrow in-links from "all pages Footer" to "Home Footer" (only Home and About carry a Footer in their layouts); add Open Question about About's reachability from inner pages; add [^4] reference - coming-soon: clarify that GhostWireframe + ComingSoonCard together form the "ComingSoonOverlay" composite referenced by backend-dependent page specs https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/pages/about/SPEC.md | 16 ++++++++++++---- docs/pages/coming-soon/SPEC.md | 6 +++++- docs/pages/explore/SPEC.md | 6 ++++-- docs/pages/home/SPEC.md | 9 ++++++--- docs/pages/model-detail/SPEC.md | 5 ++++- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/docs/pages/about/SPEC.md b/docs/pages/about/SPEC.md index 264b120..895d10f 100644 --- a/docs/pages/about/SPEC.md +++ b/docs/pages/about/SPEC.md @@ -28,8 +28,8 @@ static. - **Curious visitors** wanting context on the project's name and purpose. - **Privacy-conscious users** investigating how credentials are handled before connecting a key. -- Entry from: Footer "About" link (all pages); [`../settings/SPEC.md`](../settings/SPEC.md) - credential-privacy detail link. +- Entry from: Home Footer "About" link; + [`../settings/SPEC.md`](../settings/SPEC.md) credential-privacy detail link. ## Layout @@ -47,6 +47,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **AboutHero** — page heading ("About farish") and a one-sentence tagline describing the project. - **FarishHistory** — prose section about William Farish (1759–1837) and his @@ -60,6 +62,7 @@ flowchart TB servers. - **SettingsCTA** — secondary CTA button "Connect your key in Settings" linking to [`../settings/SPEC.md`](../settings/SPEC.md). +- **Footer** — site footer with links to the project GitHub repository. ## States @@ -78,7 +81,7 @@ _None._ The page is fully static — no local or remote data dependencies. ## Navigation -**In-links:** Footer "About" link (all pages); Settings "learn more" credential +**In-links:** Home Footer "About" link; Settings "learn more" credential privacy link. **Out-links:** @@ -93,7 +96,10 @@ than the viewport. ## Open Questions -_None._ +- **About link placement.** Currently only the Home and About pages include a + Footer with the About link, so About is not reachable from most inner pages. + Decide whether to add a site-wide Footer to all pages or promote About to a + NavBar link before wireframing.[^4] ## References @@ -104,3 +110,5 @@ _None._ [`../INDEX.md`](../INDEX.md). [^3]: William Farish (scientist), Wikipedia — . +[^4]: INDEX.md — only Home and About include a Footer section in their layouts — + [`../INDEX.md`](../INDEX.md). diff --git a/docs/pages/coming-soon/SPEC.md b/docs/pages/coming-soon/SPEC.md index ca2e674..07c62fb 100644 --- a/docs/pages/coming-soon/SPEC.md +++ b/docs/pages/coming-soon/SPEC.md @@ -51,11 +51,15 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **GhostWireframe** — a dimmed (e.g. 30 % opacity, blurred) rendering of the target page using hardcoded mock data (lorem ipsum titles, placeholder thumbnail images). Makes the future design tangible without real data. - **ComingSoonCard** — centered modal-style card containing the icon, headline, - note, and action button. Not dismissible. + note, and action button. Not dismissible. Together with GhostWireframe this + constitutes the **ComingSoonOverlay** referenced by backend-dependent page + specs (Explore, Leaderboards, Profile, Model Detail). - **HomeButton** — secondary button navigating to `/`. - **PageIcon** — contextual icon representing the target page category (e.g. gallery icon for Explore, trophy for Leaderboards). diff --git a/docs/pages/explore/SPEC.md b/docs/pages/explore/SPEC.md index aec508d..13726d0 100644 --- a/docs/pages/explore/SPEC.md +++ b/docs/pages/explore/SPEC.md @@ -49,6 +49,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **SearchBar** — debounced text input; updates `?q=` URL param on change. - **SortSelector** — dropdown: Newest, Highest Rated, Most Popular, Most Viewed. - **FilterChips** — active filters shown as removable chips in the controls row. @@ -96,8 +98,8 @@ flowchart TB ## Navigation -**In-links:** NavBar (all pages); Home hero secondary CTA; Model Detail "Explore -more" link. +**In-links:** NavBar (all pages); Home hero secondary CTA; Model Detail "Back to +Explore" breadcrumb. **Out-links:** - `/m/:modelId` — ModelCard click diff --git a/docs/pages/home/SPEC.md b/docs/pages/home/SPEC.md index ff5b090..6dc843d 100644 --- a/docs/pages/home/SPEC.md +++ b/docs/pages/home/SPEC.md @@ -46,7 +46,8 @@ flowchart TB - **NavBar** — site-wide top bar with links to Generate, Explore, Leaderboards, My Library, and a Settings icon. - **HeroSection** — headline ("AI-generated 3D models, instantly"), brief - tagline explaining farish, and the primary CTA button. + tagline explaining farish, the primary CTA button, and secondary text links + to Explore and Leaderboards. - **GenerateCTA** — primary button linking to [`../generate/SPEC.md`](../generate/SPEC.md). - **TrendingStrip** — horizontally scrollable row of `ModelCard` components sourced from the most-viewed models endpoint; hidden in the `degraded` state. @@ -65,6 +66,8 @@ flowchart TB ## Interactions - **Click GenerateCTA** → navigate to `/generate`. +- **Click "Explore" secondary link in HeroSection** → navigate to `/explore`. +- **Click "Leaderboards" secondary link in HeroSection** → navigate to `/leaderboards`. - **Click a ModelCard in TrendingStrip** → navigate to `/m/:modelId`. - **Click Explore in NavBar** → navigate to `/explore`. - **Click Leaderboards in NavBar** → navigate to `/leaderboards`. @@ -83,8 +86,8 @@ flowchart TB **Out-links:** - `/generate` — primary CTA and NavBar -- `/explore` — NavBar -- `/leaderboards` — NavBar +- `/explore` — NavBar and HeroSection secondary link +- `/leaderboards` — NavBar and HeroSection secondary link - `/library` — NavBar - `/m/:modelId` — TrendingStrip cards - `/settings` — NavBar icon diff --git a/docs/pages/model-detail/SPEC.md b/docs/pages/model-detail/SPEC.md index 637311f..f369948 100644 --- a/docs/pages/model-detail/SPEC.md +++ b/docs/pages/model-detail/SPEC.md @@ -53,6 +53,8 @@ flowchart LR ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **ThreeDViewer** — WebGL canvas with orbit, pan, and zoom controls; renders the model geometry (expected format: GLB).[^3] - **ViewerControls** — camera-reset, fullscreen, and lighting-preset toggle @@ -107,7 +109,8 @@ flowchart LR ## Navigation **In-links:** Generate (post-save redirect); My Library (card click); Explore, -Leaderboards, Profile (card clicks); direct shared URL. +Leaderboards, Profile (card clicks); Home (TrendingStrip card click); direct +shared URL. **Out-links:** - `/generate` — Generate Similar button (with `?prompt=`) From bdc3c439e3db7f67a9ab1a7428c7fb05cc2a3ed0 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:18:22 +0000 Subject: [PATCH 032/142] docs(specs): add NavBar to Components section of all remaining pages The NavBar appears in the Layout flowchart of every page but was only listed under ## Components in the Home spec. Adding it to the remaining 10 specs ensures the Components section is complete for wireframing (step 15) and serves as a build checklist item for implementation (step 30+). The Footer was already present in Home; About receives it now to match its Layout flowchart. https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- docs/pages/generate/SPEC.md | 2 ++ docs/pages/leaderboards/SPEC.md | 2 ++ docs/pages/my-library/SPEC.md | 2 ++ docs/pages/not-found/SPEC.md | 2 ++ docs/pages/profile/SPEC.md | 2 ++ docs/pages/settings/SPEC.md | 2 ++ 6 files changed, 12 insertions(+) diff --git a/docs/pages/generate/SPEC.md b/docs/pages/generate/SPEC.md index 7540712..160d0f2 100644 --- a/docs/pages/generate/SPEC.md +++ b/docs/pages/generate/SPEC.md @@ -48,6 +48,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **NoKeyBanner** — inline banner shown when no API key is set; links to [`../settings/SPEC.md`](../settings/SPEC.md). - **PromptBar** — multiline text area with a Submit / Generate button; accepts diff --git a/docs/pages/leaderboards/SPEC.md b/docs/pages/leaderboards/SPEC.md index 59fa454..6022b80 100644 --- a/docs/pages/leaderboards/SPEC.md +++ b/docs/pages/leaderboards/SPEC.md @@ -42,6 +42,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **BoardTabs** — three tabs selecting the active ranking metric. - **TimeBucketSelector** — four toggle buttons (1W / 1M / 1Y / All); updates URL param on selection. diff --git a/docs/pages/my-library/SPEC.md b/docs/pages/my-library/SPEC.md index e015819..a42c152 100644 --- a/docs/pages/my-library/SPEC.md +++ b/docs/pages/my-library/SPEC.md @@ -45,6 +45,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **LibraryHeader** — page title ("My Library"), sort dropdown, and a "Clear All" button that triggers a confirmation dialog. - **ModelGrid** — responsive card grid; switches to `EmptyState` when the diff --git a/docs/pages/not-found/SPEC.md b/docs/pages/not-found/SPEC.md index 4c8e510..47c38cd 100644 --- a/docs/pages/not-found/SPEC.md +++ b/docs/pages/not-found/SPEC.md @@ -42,6 +42,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **NotFoundIllustration** — an isometric or geometric graphic evoking the project's aesthetic; displays the numeral "404" or equivalent. - **NotFoundHeadline** — "Page not found" in the site's heading typeface. diff --git a/docs/pages/profile/SPEC.md b/docs/pages/profile/SPEC.md index 280d9a4..627fe14 100644 --- a/docs/pages/profile/SPEC.md +++ b/docs/pages/profile/SPEC.md @@ -48,6 +48,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **ProfileHeader** — avatar image, display name, username handle, join date, and a stats row (model count, average rating, total views). - **StatsBadge** — individual stat chip reused within ProfileHeader. diff --git a/docs/pages/settings/SPEC.md b/docs/pages/settings/SPEC.md index 83d3f18..7a176be 100644 --- a/docs/pages/settings/SPEC.md +++ b/docs/pages/settings/SPEC.md @@ -47,6 +47,8 @@ flowchart TB ## Components +- **NavBar** — site-wide navigation bar; links to Generate, Explore, + Leaderboards, My Library, and Settings. - **ConnectionStatus** — banner showing "Connected as \" (OAuth) or "API key set" (manual) or "Not connected". - **ConnectWithClaudeButton** — initiates the Claude OAuth flow.[^3] From d5c5ab048ef5a61006ef3de74d92ac49a37fac43 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:20:28 +0000 Subject: [PATCH 033/142] chore: track step-13 task record https://claude.ai/code/session_01AiWbZuSU6UCjuXnrBBFk9p --- .claude/tasks/step-13-spec-review.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 .claude/tasks/step-13-spec-review.json diff --git a/.claude/tasks/step-13-spec-review.json b/.claude/tasks/step-13-spec-review.json new file mode 100644 index 0000000..3ba12ec --- /dev/null +++ b/.claude/tasks/step-13-spec-review.json @@ -0,0 +1 @@ +{"id":"step-13-spec-review","subject":"step-13: Cross-spec consistency review and adjustments","status":"in_progress","description":"Review all 11 page specs as a whole for navigation consistency, shared concept naming, PAGE-SPEC.md conformance, and completeness. Make adjustments in place."} From 434dcec429d3db43858789b97b74bb9cea4c50d7 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:26:15 +0000 Subject: [PATCH 034/142] docs(research): add Vuetify 3 design system choice and component vocabulary --- docs/research/design-system-choice.md | 131 ++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 docs/research/design-system-choice.md diff --git a/docs/research/design-system-choice.md b/docs/research/design-system-choice.md new file mode 100644 index 0000000..1fe3d4d --- /dev/null +++ b/docs/research/design-system-choice.md @@ -0,0 +1,131 @@ +# Design System Choice — farish + +Research and recommendation for the Vue 3 off-the-shelf design system to use +across farish (initial prompt step 15). This document is the source of truth +for the component vocabulary used in wireframes and implementation. + +## Decision + +**Chosen: Vuetify 3 (Material Design 3 for Vue 3)**[^vuetify-home] + +## Candidates Evaluated + +Four mature Vue 3 component libraries were considered. Nuxt UI was excluded +early: it is designed around the Nuxt framework, which farish does not use.[^nuxt-ui] + +| Library | GitHub Stars | Weekly npm DL | Design basis | +| --------------- | -----------: | ------------: | ----------------------- | +| **Vuetify 3** | ~41 000[^vuetify-gh] | ~943 000[^npm-trends] | Material Design 3 | +| Element Plus | ~25 000[^element-gh] | ~430 000[^npm-trends] | Element (enterprise) | +| PrimeVue 4 | ~14 000[^primevue-gh] | ~422 000[^npm-trends] | Design-agnostic | +| Naive UI | ~17 000[^naive-gh] | ~79 000[^npm-trends] | Neutral/custom | + +### Vuetify 3 + +Pros: largest community and download volume by a wide margin; Material Design 3 +is modern and polished; has every component farish needs out of the box +(`VRating`, `VDataTable`, `VNavigationDrawer`, `VDialog`, `VOverlay`, +`VCard`); strong responsive grid; excellent TypeScript support; Material +theming is fully overridable so the default Google aesthetic is not locked +in.[^vuetify-theming] + +Cons: the Material Design aesthetic requires deliberate theme customization to +avoid a generic look; opinionated class/prop naming. + +### PrimeVue 4 + +Pros: 90+ components — slightly more breadth than Vuetify; design-agnostic with +an "unstyled" mode for complete freedom; strong Tailwind CSS integration.[^primevue-home] + +Cons: "unstyled" mode means non-trivial setup to ship a consistent look without +extra design work; steeper learning curve; smaller community than Vuetify. + +### Element Plus + +Pros: mature, very stable; excellent form/table components.[^element-home] + +Cons: enterprise/admin aesthetic that would require heavy restyling for a +creative tool; Material-agnostic, which is less aligned with the modern +browser UI direction farish wants. + +### Naive UI + +Pros: Vue 3-native, TypeScript-first, tree-shakeable, clean aesthetic.[^naive-home] + +Cons: significantly smaller download base (~79 k/week vs Vuetify's ~943 k/week); +fewer community examples; some critical components (e.g. a built-in rating +widget) less polished than Vuetify equivalents. + +## Rationale for Vuetify 3 + +1. **Component coverage.** Every UI primitive farish needs is available as a + first-class Vuetify component — no custom wrappers required at the wireframe + stage (see Component Vocabulary below). + +2. **Community and ecosystem.** ~41 k GitHub stars and ~943 k weekly npm + downloads[^npm-trends] means StackOverflow coverage, active issue responses, + and long-term maintenance confidence. + +3. **Responsive grid.** `VRow`/`VCol` with the `xs`/`sm`/`md`/`lg` breakpoint + props maps directly to the desktop-default / mobile-friendly layout + requirement.[^vuetify-grid] + +4. **Rating widget.** `VRating` is built in and maps directly to the star-rating + mechanic in Model Detail, Explore cards, and Leaderboards.[^vuetify-rating] + +5. **Theming.** Vuetify 3 uses a CSS custom-property theme engine — one + `createVuetify()` call with a custom palette moves the entire UI away from + the default Material colours.[^vuetify-theming] + +6. **Amendment A6 alignment.** Vuetify's slot-based layout produces predictable, + testable DOM that Playwright can screenshot reliably (needed for the CI + screenshot workflow in steps 27–29). + +## Component Vocabulary + +The table below is the canonical mapping used by the wireframing skill. When a +wireframe labels a component, it uses the **Farish name** (left column); the +**Vuetify component** (right column) is what gets built. + +| Farish Component | Vuetify 3 Component(s) | Notes | +| ----------------------- | --------------------------------------------------- | -------------------------------------------- | +| NavBar | `VAppBar` + `VBtn` | Sticky top bar; mobile hamburger via `VMenu` | +| NavDrawer | `VNavigationDrawer` | Sidebar on mobile / Settings nav | +| ModelCard | `VCard` + `VRating` | Thumbnail, title, author, rating | +| ModelGrid | `VRow` / `VCol` (`cols="12" sm="6" md="4" lg="3"`) | Responsive card grid | +| FilterPanel | `VNavigationDrawer` (secondary) | Collapsible; bottom-sheet on mobile | +| ParametersPanel | `VNavigationDrawer` (secondary) | Collapsible; bottom-sheet on mobile | +| Dialog / Modal | `VDialog` | ClarificationDialog, ShareDialog, etc. | +| ComingSoonOverlay | `VOverlay` + `VCard` | Full-page ghost overlay | +| ThreeDViewer | Custom canvas in `VCard` | WebGL; no native Vuetify equivalent | +| SearchBar | `VTextField` with `append-inner-icon="mdi-magnify"` | Debounced; bound to URL param | +| SortSelector | `VSelect` | Newest / Highest Rated / Most Popular | +| FilterChips | `VChip` + `VChipGroup` | Removable active-filter chips | +| LeaderboardTable | `VDataTable` | Sortable columns; time-bucket tabs via `VTab`| +| TabBar (time buckets) | `VTabs` + `VTab` | 1w / 1m / 1y / All time | +| RatingWidget | `VRating` | 5-star input | +| ActionBar | `VToolbar` + `VBtn` | Download / Save / Share / Rate | +| SettingsForm | `VForm` + `VTextField` + `VSwitch` | API key, preferences | +| Banner / Alert | `VAlert` | NoKeyBanner, error messages | +| Skeleton / Loading | `VSkeletonLoader` | Card and viewer loading states | +| EmptyState | `VCard` with centered illustration | No-results / empty library | +| ProgressFeed | `VList` + `VListItem` (streaming) | Agent-loop step stream in Generate | +| Tooltip / Popover | `VTooltip` / `VMenu` | Contextual hints | +| Snackbar / Toast | `VSnackbar` | Save-confirmation, copy-URL feedback | + +## References + +[^vuetify-home]: Vuetify official site — +[^vuetify-gh]: Vuetify GitHub repository — +[^vuetify-theming]: Vuetify 3 theming docs — +[^vuetify-grid]: Vuetify 3 grid system docs — +[^vuetify-rating]: Vuetify 3 VRating component — +[^primevue-home]: PrimeVue official site — +[^primevue-gh]: PrimeVue GitHub repository — +[^element-home]: Element Plus official site — +[^element-gh]: Element Plus GitHub repository — +[^naive-home]: Naive UI official site — +[^naive-gh]: Naive UI GitHub repository — +[^nuxt-ui]: Nuxt UI requires the Nuxt framework — +[^npm-trends]: npm download trends snapshot (2025–2026) — + From c31a4283bd6878ce446c77322ee99e49a08270be Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:26:19 +0000 Subject: [PATCH 035/142] feat(skills): add page-wireframing skill family (step 14) --- .../skills/page-wireframing-ascii/SKILL.md | 67 +++++++++++++++++++ .../skills/page-wireframing-image/SKILL.md | 64 ++++++++++++++++++ .../skills/page-wireframing-review/SKILL.md | 52 ++++++++++++++ .claude/skills/page-wireframing/SKILL.md | 51 ++++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 .claude/skills/page-wireframing-ascii/SKILL.md create mode 100644 .claude/skills/page-wireframing-image/SKILL.md create mode 100644 .claude/skills/page-wireframing-review/SKILL.md create mode 100644 .claude/skills/page-wireframing/SKILL.md diff --git a/.claude/skills/page-wireframing-ascii/SKILL.md b/.claude/skills/page-wireframing-ascii/SKILL.md new file mode 100644 index 0000000..213de17 --- /dev/null +++ b/.claude/skills/page-wireframing-ascii/SKILL.md @@ -0,0 +1,67 @@ +--- +name: page-wireframing-ascii +description: > + Stage 1 of wireframing: produce ASCII art wireframes for a farish page and + each of its modals/popovers. Use when asked to "draw the ASCII wireframe", + "sketch the page layout", or from page-wireframing skill step 4. +--- + +# Wireframing — ASCII Stage + +Produces rough ASCII art wireframes. One file for the full page; one file per +modal or popover. Files go in `docs/pages//wireframes/`. + +## Layout vocabulary + +Use this vocabulary consistently across all pages so wireframes look coherent: + +``` +┌─────────────────────────────────────────────────┐ +│ NAVBAR [Logo] [Generate] [Explore] [≡] │ ← VAppBar (full width) +├─────────────────────────────────────────────────┤ +│ (page body — varies per page) │ +│ │ +│ SIDEBAR │ MAIN CONTENT │ ← VNavigationDrawer + VMain +│ ┌─────────────┐ │ ┌─────────────────────┐ │ +│ │ filter / │ │ │ card grid / viewer │ │ ← VCard, VRow/VCol +│ │ params panel│ │ │ │ │ +│ └─────────────┘ │ └─────────────────────┘ │ +│ │ [ action bar ] │ ← VToolbar / VBtn +├─────────────────────────────────────────────────┤ +│ (no footer — single-page app) │ +└─────────────────────────────────────────────────┘ +``` + +Box-drawing chars: `┌ ┐ └ ┘ │ ─ ├ ┤ ┬ ┴ ┼`. Use `[ Button ]` for buttons, +`( radio )` for radio inputs, `[x]` for checkboxes, `[___field___]` for text +inputs, `★★★☆☆` for ratings, `▓▓▓▓░` for progress. + +## Steps + +1. Read `docs/pages//SPEC.md` — collect all components from `## Components` + and all states from `## States`. + +2. Read `docs/research/design-system-choice.md` — note the Vuetify component + for each spec component so the ASCII labels match implementation reality. + +3. Create `docs/pages//wireframes/page.ascii.md`. Draw the full-page + wireframe at desktop width (~80 chars wide). Rules: + - Show the NavBar at the top on every page. + - Depict every component listed in `## Components` — place them in the + layout region described in `## Layout` of the spec. + - Label each region with its component name and its Vuetify equivalent + in parentheses, e.g. `FILTER PANEL (VNavigationDrawer)`. + - Show the `default` state. Add a short note below the diagram for each + non-default state that changes the layout significantly. + +4. For each modal, popover, or overlay named in `## Components` or + `## Interactions` of the spec, create a separate file: + `docs/pages//wireframes/.ascii.md`. + Draw the modal at ~60 chars wide, centered, with a dimmed-backdrop indicator. + +5. If the page has a `coming-soon` state, create + `docs/pages//wireframes/coming-soon-overlay.ascii.md` showing the + ghost-wireframe-behind-overlay layout. + +6. Save all files. Do not proceed to stage 2 until every component from the + spec has a visible representation in the wireframes. diff --git a/.claude/skills/page-wireframing-image/SKILL.md b/.claude/skills/page-wireframing-image/SKILL.md new file mode 100644 index 0000000..452857f --- /dev/null +++ b/.claude/skills/page-wireframing-image/SKILL.md @@ -0,0 +1,64 @@ +--- +name: page-wireframing-image +description: > + Stage 2 of wireframing: produce a Mermaid-based visual wireframe for a farish + page (more detailed than ASCII; renders as an image on GitHub). Use when asked + to "create the visual wireframe", "draft the image wireframe", or from + page-wireframing skill step 5. +--- + +# Wireframing — Image (Mermaid) Stage + +Produces a detailed Mermaid diagram wireframe — the "drafty image-based version" +from initial prompt step 15. Uses Mermaid `block-beta` or `flowchart` syntax so +the diagram renders natively on GitHub and GitHub Pages (amendment A6).[^mermaid] + +Output file: `docs/pages//wireframes/page.mermaid.md` + +## Steps + +1. Read the completed ASCII wireframe at + `docs/pages//wireframes/page.ascii.md` — use it as the spatial + reference for component placement. + +2. Read `docs/pages//SPEC.md` sections `## Layout` and `## Components` + for the authoritative region hierarchy. + +3. Read `docs/research/design-system-choice.md` — confirm Vuetify component + names for each region so labels in the Mermaid diagram are implementation- + accurate. + +4. Write `docs/pages//wireframes/page.mermaid.md`. The file must contain: + - A heading: `# — Visual Wireframe` + - One Mermaid `flowchart TB` (or `block-beta`) diagram that shows: + - Every component from `## Components` as a labelled node. + - Layout regions (NavBar at top, sidebar left of main, action bar at bottom) + using subgraphs to group related nodes. + - Arrows indicating primary user flow through the page. + - A short "Component key" table below the diagram mapping each label to its + Vuetify equivalent (copied from `design-system-choice.md`). + - One paragraph noting which states change the diagram significantly. + +5. Keep the Mermaid diagram under ~40 nodes. If the page has enough modals to + warrant it, produce a second diagram for the primary modal in the same file + under a `## Modal` heading. + +6. Validate the diagram renders without syntax errors. Mermaid syntax rules: + - Node IDs must be alphanumeric or underscored. + - Subgraph labels in quotes if they contain spaces. + - Arrows: `-->` (flow) or `---` (association, no arrowhead). + +7. Save the file. + +## Notes + +- This diagram is "drafty" — it does not need to be pixel-perfect. Its purpose + is to validate that every component has a logical place in the layout. +- A6 requires Mermaid over images where a diagram is sufficient. If a component + cannot be meaningfully represented in Mermaid (e.g. the 3D WebGL canvas), use + a rectangular node labelled `[ThreeDViewer — custom WebGL canvas]`. + +## References + +[^mermaid]: Mermaid — renders natively on GitHub and GitHub Pages — + diff --git a/.claude/skills/page-wireframing-review/SKILL.md b/.claude/skills/page-wireframing-review/SKILL.md new file mode 100644 index 0000000..3a6150f --- /dev/null +++ b/.claude/skills/page-wireframing-review/SKILL.md @@ -0,0 +1,52 @@ +--- +name: page-wireframing-review +description: > + Stage 3 of wireframing: review all wireframes for a page against its spec + and identify gaps or inconsistencies. The "one more round of improvement" from + initial prompt step 15. Use when asked to "review the wireframes", "check + wireframes against spec", or from page-wireframing skill step 6. +--- + +# Wireframing — Review Stage + +Validates all wireframes for a page against the page spec and produces a +pass/fail checklist. One iteration of improvement is mandatory per prompt +step 15; iterate until all items pass. + +## Steps + +1. Read `docs/pages//SPEC.md` in full. + +2. List all wireframe files in `docs/pages//wireframes/`. Confirm: + - `page.ascii.md` exists (stage 1, full page). + - `page.mermaid.md` exists (stage 2, visual draft). + - One ASCII file per modal, popover, or overlay named in `## Components`. + - `coming-soon-overlay.ascii.md` exists if the spec has a `coming-soon` state. + +3. **Component coverage check.** For every component in `## Components` of the + spec, confirm it appears in both the ASCII and Mermaid wireframes. + Flag any component that is missing. + +4. **State coverage check.** For each state in `## States`, confirm: + - The default state is fully depicted. + - Each significant non-default state has at least a note in `page.ascii.md` + or a separate diagram if it substantially changes the layout. + +5. **Spec alignment check.** Compare the layout in the wireframes against + `## Layout` in the spec (the Mermaid flowchart or ASCII sketch). Flag any + region described in the spec that is absent from the wireframes. + +6. **Design-system consistency check.** Read + `docs/research/design-system-choice.md`. Confirm each component label in + the wireframes corresponds to a Vuetify component in the vocabulary table. + Flag any label that is ambiguous or unmapped. + +7. **Cross-page consistency check.** The NavBar must appear on every page + wireframe. Cards displaying model data must use the `ModelCard` label. + Flag violations. + +8. **Produce a checklist report** — PASS or FAIL for each item above. + For each FAIL, state which file is affected and what is missing. + +9. For each FAIL, update the relevant wireframe file(s), then re-run steps 2–8. + Continue iterating until all items PASS. diff --git a/.claude/skills/page-wireframing/SKILL.md b/.claude/skills/page-wireframing/SKILL.md new file mode 100644 index 0000000..65a0192 --- /dev/null +++ b/.claude/skills/page-wireframing/SKILL.md @@ -0,0 +1,51 @@ +--- +name: page-wireframing +description: > + Draft wireframes for a farish page. Use when asked to "wireframe the X page", + "create wireframes for X", "start wireframing", or when working through prompt + step 15. Runs the three-stage process: ASCII sketch → Mermaid visual draft → + one review/improvement round. Produces at least one whole-page wireframe plus + one per modal or popover. +--- + +# Page Wireframing + +Three-stage wireframing process for a single farish page. Designed so prompt +step 15 is "for each page in INDEX.md, run this skill". + +Design system: **Vuetify 3**. Component vocabulary is in +`docs/research/design-system-choice.md` — read it before starting. + +## Steps + +1. Read `docs/pages//SPEC.md` in full. Note every component, modal, + popover, and state in `## Components` and `## States`. + +2. Read `docs/research/design-system-choice.md` — confirm the Vuetify component + that maps to each component named in the spec. + +3. Create the directory `docs/pages//wireframes/` if it does not exist. + +4. Run `Skill(page-wireframing-ascii)` to produce the ASCII wireframe(s) — + one for the full page plus one per modal or popover identified in step 1. + +5. Run `Skill(page-wireframing-image)` to produce the Mermaid visual wireframe + for the full page (and modals, if complex enough to warrant it). + +6. Run `Skill(page-wireframing-review)` to validate all wireframes against the + page spec and identify gaps. + +7. For each gap found in step 6, update the affected wireframe file(s), then + re-run step 6. Iterate until the review passes with no remaining gaps. + +8. Commit the wireframes atomically: + `docs(wireframes): add page wireframes` + +## Notes + +- Wireframe files live in `docs/pages//wireframes/`. Never place them + elsewhere. +- The ASCII stage is stage 1; the Mermaid stage is stage 2; the review is the + "one more round of improvement" from the initial prompt (step 15). +- If a page has a `coming-soon` state (backend-gated), include a wireframe of + the ghost overlay state as a separate file: `coming-soon-overlay.ascii.md`. From 9ba941d8edd031caf5cc1708ad5c066abb02fca1 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:26:22 +0000 Subject: [PATCH 036/142] chore: track step-14 task record --- .claude/tasks/step-14-wireframing-skill.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 .claude/tasks/step-14-wireframing-skill.json diff --git a/.claude/tasks/step-14-wireframing-skill.json b/.claude/tasks/step-14-wireframing-skill.json new file mode 100644 index 0000000..9c4fccf --- /dev/null +++ b/.claude/tasks/step-14-wireframing-skill.json @@ -0,0 +1 @@ +{"id":"step-14-wireframing-skill","subject":"[done] step-14: Create page-wireframing skill and design system research","status":"done","description":"Design a page-wireframing skill that keeps wireframes consistent for each page. Research and recommend a Vue design system. Created docs/research/design-system-choice.md (recommends Vuetify 3) and .claude/skills/page-wireframing/ skill family (4 skills)."} From 67cd8b6034b90d421e425676bb37ebdb4765b5eb Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 05:38:31 +0000 Subject: [PATCH 037/142] docs(wireframes): add home page wireframes --- docs/pages/home/wireframes/page.ascii.md | 56 +++++++++++++++++++++ docs/pages/home/wireframes/page.mermaid.md | 58 ++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 docs/pages/home/wireframes/page.ascii.md create mode 100644 docs/pages/home/wireframes/page.mermaid.md diff --git a/docs/pages/home/wireframes/page.ascii.md b/docs/pages/home/wireframes/page.ascii.md new file mode 100644 index 0000000..48420ab --- /dev/null +++ b/docs/pages/home/wireframes/page.ascii.md @@ -0,0 +1,56 @@ +# Home — ASCII Wireframe (Desktop, default state) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ NAVBAR (VAppBar) │ +│ [farish] Generate Explore Leaderboards Library [⚙ icon] │ +└─────────────────────────────────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ HERO SECTION (VCard / full-width section) │ +│ │ +│ ╔═══════════════════════════════════════════╗ │ +│ ║ AI-generated 3D models, instantly. ║ │ +│ ║ ║ │ +│ ║ farish turns your words into interactive ║ │ +│ ║ 3D geometry — no modelling skills needed.║ │ +│ ║ ║ │ +│ ║ [ ▶ Start Generating ] ║ ← GenerateCTA (VBtn primary) +│ ║ ║ │ +│ ║ Explore community → Leaderboards → ║ ← secondary links │ +│ ╚═══════════════════════════════════════════╝ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ TRENDING STRIP (VRow — horizontally scrollable) │ +│ Trending models ─────────────────────────────────────────────── → scroll │ +│ │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌──────────┐ │ +│ │ [img 16:9]│ │ [img 16:9]│ │ [img 16:9]│ │ [img 16:9]│ │[img 16:9]│ │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ │ Model A │ │ Model B │ │ Model C │ │ Model D │ │ Model E │ │ +│ │ @alice │ │ @bob │ │ @carol │ │ @dan │ │ @eve │ │ +│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ └──────────┘ │ +│ ← ModelCard (VCard) │ +└─────────────────────────────────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ FOOTER │ +│ About · Settings · GitHub ↗ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +## State Notes + +| State | Difference from default | +| --------- | ------------------------------------------------------------------- | +| `loading` | TrendingStrip shows 5× VSkeletonLoader cards instead of ModelCards | +| `degraded` | TrendingStrip section hidden entirely; Hero section unchanged | + +## Responsive (mobile) + +- NavBar collapses links into `[≡]` hamburger → VNavigationDrawer slide-in. +- HeroSection copy stacks vertically; CTA button spans full width. +- TrendingStrip becomes a 2-column VRow/VCol card grid instead of a scroll row. diff --git a/docs/pages/home/wireframes/page.mermaid.md b/docs/pages/home/wireframes/page.mermaid.md new file mode 100644 index 0000000..cd0af9c --- /dev/null +++ b/docs/pages/home/wireframes/page.mermaid.md @@ -0,0 +1,58 @@ +# Home — Visual Wireframe + +```mermaid +flowchart TB + subgraph NavBar["NavBar (VAppBar)"] + Logo["[farish logo]"] + NavGenerate["Generate"] + NavExplore["Explore"] + NavLeaderboards["Leaderboards"] + NavLibrary["Library"] + NavSettings["⚙ Settings icon"] + end + + subgraph HeroSection["HeroSection (VCard / full-width)"] + Headline["AI-generated 3D models, instantly."] + Tagline["farish turns your words into interactive 3D geometry"] + GenerateCTA["[ ▶ Start Generating ] (VBtn, primary)"] + SecondaryLinks["Explore community → Leaderboards →"] + end + + subgraph TrendingStrip["TrendingStrip (VRow — scrollable)"] + Card1["ModelCard 1\n[img]\nModel A · @alice\n(VCard)"] + Card2["ModelCard 2\n[img]\nModel B · @bob\n(VCard)"] + Card3["ModelCard 3\n[img]\nModel C · @carol\n(VCard)"] + Card4["ModelCard 4\n[img]\nModel D · @dan\n(VCard)"] + Card5["ModelCard 5\n[img]\nModel E · @eve\n(VCard)"] + end + + subgraph Footer["Footer"] + AboutLink["About"] + SettingsLink["Settings"] + GithubLink["GitHub ↗"] + end + + NavBar --> HeroSection + HeroSection --> TrendingStrip + TrendingStrip --> Footer + + GenerateCTA -->|"navigate to /generate"| GenPage(("/generate")) + SecondaryLinks -->|"navigate to /explore"| ExpPage(("/explore")) + Card1 & Card2 & Card3 & Card4 & Card5 -->|"navigate to /m/:modelId"| DetailPage(("/m/:modelId")) +``` + +## Component Key + +| Wireframe Label | Vuetify 3 Component | +| ----------------- | ---------------------------------------- | +| NavBar | `VAppBar` + `VBtn` | +| HeroSection | Full-width `VCard` or plain `
` | +| GenerateCTA | `VBtn` (variant="elevated", color="primary") | +| TrendingStrip | `VRow` (overflow-x scroll) | +| ModelCard | `VCard` (with thumbnail slot) | +| Footer | Static `