Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,41 @@
"name": "cavalry-collective",
"owner": {
"name": "Cavalry Collective",
"email": "adam@cavalry.sg"
"email": "adam@cavalry.sg",
"url": "https://cavalry.sg"
},
"description": "Visual Stack — interactive wireframing and UI review with your coding agent.",
"description": "Visual Stack adds a Figma-like feedback layer to AI coding agents. Comment directly on a wireframe or a running app, and get the next revision in the same place.",
"plugins": [
{
"name": "vstack",
"displayName": "Visual Stack",
"source": "./plugins/vstack",
"description": "Visual Stack is interactive wireframing for Claude Code. Build a screen from a prompt, screenshot, reference site, or design system, then comment directly on the result and receive each revision in the same browser workspace. It can also review a running app or public website route by route. Wireframes are self-contained HTML; local review state stays in the project."
"description": "Stop prompting. Start pointing. Visual Stack adds a Figma-like feedback layer to Claude Code. Create a new screen from a prompt, screenshot, reference site, or design system, or open an app you already have running. Click any element and leave feedback exactly where the problem is hiding, and Claude publishes the next revision into the same workspace. Compare revisions on a timeline, preview desktop, tablet, and mobile layouts, and keep every comment attached to the element, route, and version it refers to. Wireframes are self-contained HTML and review state stays in your project.",
"author": {
"name": "Cavalry Collective",
"email": "adam@cavalry.sg",
"url": "https://cavalry.sg"
},
"homepage": "https://www.cavalry.sg/visual-stack",
"repository": "https://github.com/Cavalry-Collective/visual-stack",
"license": "MIT",
"category": "design",
"keywords": [
"wireframe",
"wireframing",
"mockup",
"prototype",
"ui",
"ui-review",
"ux",
"design",
"design-review",
"design-feedback",
"frontend",
"annotate",
"visual-feedback",
"screenshot"
]
}
]
}
72 changes: 72 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Bug report
description: Something in a skill or workspace does not work as described.
labels: [bug]
body:
- type: markdown
attributes:
value: |
Do not report a security problem here. Follow
[SECURITY.md](https://github.com/Cavalry-Collective/visual-stack/blob/main/SECURITY.md)
instead.

- type: textarea
id: what-happened
attributes:
label: What happened
description: What you did, what you expected, and what you got instead.
validations:
required: true

- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: >
Start from the command you ran. A bug we can reproduce is a bug we can
fix.
placeholder: |
1. Run `/vstack:review Wireframe a login screen.`
2. Click the submit button and leave a comment.
3. Send the comment.
validations:
required: true

- type: dropdown
id: host
attributes:
label: Host
options:
- Claude Code
- Codex
- Grok
- Other
validations:
required: true

- type: input
id: version
attributes:
label: Visual Stack version
description: >
The version shown in the plugin manager, or the commit you installed
from.
placeholder: 4.7.0
validations:
required: true

- type: input
id: environment
attributes:
label: Operating system, Node version, and browser
placeholder: macOS 15.2, Node 22.11.0, Chrome 131
validations:
required: true

- type: textarea
id: output
attributes:
label: Server output or console errors
description: >
Anything the review server printed, or errors from the browser console.
This is pasted as code, so no backticks are needed.
render: text
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Report a security issue
url: https://github.com/Cavalry-Collective/visual-stack/blob/main/SECURITY.md
about: Follow the security policy. Do not open a public issue.
- name: Something you would rather not post publicly
url: mailto:adam@cavalry.sg
about: Email the maintainer directly.
40 changes: 40 additions & 0 deletions .github/ISSUE_TEMPLATE/idea.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Idea or feature request
description: Something Visual Stack should do that it does not do yet.
labels: [enhancement]
body:
- type: textarea
id: problem
attributes:
label: The problem
description: >
What you were trying to do, and where the current tools got in the way.
Lead with the problem rather than the solution.
validations:
required: true

- type: textarea
id: idea
attributes:
label: What you would like instead
validations:
required: true

- type: dropdown
id: area
attributes:
label: Which part of Visual Stack
options:
- review (wireframes)
- review (running app or website)
- user-story-map
- The workspace UI
- Host support
- Something else
validations:
required: true

- type: textarea
id: alternatives
attributes:
label: What you tried instead
description: Workarounds you already have, and why they fall short.
21 changes: 21 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## What this changes

<!-- What the change does, and why. A reviewer should not have to read the diff to find out. -->

## How it was tested

<!--
Installing the plugin from this branch and driving the skill end to end in a
real project. A skill that has only been read is untested. Say which host you
drove it on.
-->

## Checklist

- [ ] Installed the plugin from this branch and drove the affected skill end to end.
- [ ] Nothing writes outside the user's project, and nothing transmits anywhere, unless that is the skill's stated purpose.
- [ ] Per-machine state resolves through `lib/workdir.mjs` and lands under `.vstack/local/<tool>/`.
- [ ] Pages stay self-contained. No external requests at runtime.
- [ ] Edited `lib/shell/` rather than a stamped region, ran `node plugins/vstack/lib/build-shell.mjs stamp`, and committed both.
- [ ] Added or renamed a plugin, and updated `.claude-plugin/marketplace.json` in the same commit.
- [ ] Renamed a tool, and added its former directory name to the `LEGACY` map in `lib/workdir.mjs`.
75 changes: 75 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
tests:
name: Tests (Node ${{ matrix.node }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: ['18', '22']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Review lifecycle
run: node plugins/vstack/skills/review/tests/review-lifecycle.mjs
- name: Host profiles
run: node plugins/vstack/skills/review/tests/host-profiles.mjs
- name: Working-directory resolution
run: node plugins/vstack/skills/review/tests/workdir.mjs

shell:
name: Stamped shell is current
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
# Fails when a page's stamped region has drifted from lib/shell/.
# Fix by running `node plugins/vstack/lib/build-shell.mjs stamp`.
- name: Check for drift
run: node plugins/vstack/lib/build-shell.mjs check

manifests:
name: Manifests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Claude Code
run: npm install --global @anthropic-ai/claude-code
# The community-marketplace review pipeline runs this same check on every
# submission, so a warning here is a warning a reviewer would see.
- name: Validate the marketplace
run: claude plugin validate . --strict
- name: Validate the plugin
run: claude plugin validate ./plugins/vstack --strict
# Both hosts read a version out of their own manifest, so they can drift
# apart silently and ship the same commit under two version numbers.
- name: Host manifests declare the same version
run: |
node -e '
const { readFileSync } = require("node:fs")
const version = file => JSON.parse(readFileSync(file, "utf8")).version
const claude = version("plugins/vstack/.claude-plugin/plugin.json")
const codex = version("plugins/vstack/.codex-plugin/plugin.json")
if (claude !== codex) {
console.error(`Claude manifest says ${claude}, Codex manifest says ${codex}.`)
process.exit(1)
}
console.log(`Both host manifests declare ${claude}.`)
'
33 changes: 33 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Release

on:
push:
tags: ['v*']

permissions:
contents: read

jobs:
version-matches-tag:
name: Tag matches the manifest version
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# An explicit version in plugin.json is what Claude Code compares against
# to decide an update exists. Tagging a release without bumping it leaves
# every installed copy believing it is already current.
- name: Compare the tag against plugin.json
run: |
node -e '
const { readFileSync } = require("node:fs")
const tag = process.env.GITHUB_REF_NAME.replace(/^v/, "")
const declared = JSON.parse(
readFileSync("plugins/vstack/.claude-plugin/plugin.json", "utf8")
).version
if (declared !== tag) {
console.error(`Tag ${process.env.GITHUB_REF_NAME} does not match plugin.json version ${declared}.`)
console.error("Bump the version in both host manifests, commit, then move the tag.")
process.exit(1)
}
console.log(`Tag and manifest agree on ${declared}.`)
'
Loading
Loading