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
8 changes: 8 additions & 0 deletions CONTINUITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -1779,6 +1779,14 @@ Temporary, reversible: `./scripts/services.sh --start` and `./scripts/deploy-cau

`./scripts/data.sh --seed` now defaults to **tiny** (was small). `gen:small` and `gen:tiny` both pass `--skip-invariants`. Statement publish reuses one document store (or parallel PublishedData writes across Hardhat wallets, receipts awaited in a batch). Seed RPC clients poll every 50ms. See `fake-data-generation/generateStatements.ts`, `fake-data-generation/seedRpc.ts`, `scripts/data.sh`.

## 2026-08-24 — Cause board is the organizer publication, not the project list

Copy sweep of [cause-page-not-a-club.md](specs/product/cause-page-not-a-club.md):
the Aligning/project list is now **fundable-projects board** in UI copy and
end-user docs; **cause board** is the CauseStarter organizer publication
(leftover “cause page” left in comments). Routes still `/portal/:cid` and
`/cause/:owner/:slug`; identifiers `fundingportal*` lag.

## 2026-08-20 — Anvil `--state` restart dump

Local `hardhat-node` was coming back empty after `stack.restart-consistency` because Docker SIGTERM did not make Anvil dump `/data/state.json` (then a fresh deploy + trust wiring filled ~41 blocks with no seed). Fix: `scripts/anvil-docker-entrypoint.sh` maps SIGTERM→SIGINT, compose `--state-interval 15` and 60s grace, restart check records block height and SIGINTs Anvil before stop. Recreate `hardhat-node` to mount the wrapper.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Commonality is a system for decentralized crowdfunding of public goods: people c
- [High-level project status](./workflow/project-status.md) AKA what milestone are we currently heading for: never deployed to mainnet yet, just did first testnet deployment, see also [MVP](./specs/product/mvp.md)
- Product boundaries between the eight sites: [product UI domains](./specs/product/ui-domains.md).
- Technical domain composition and live route ownership: [technical UI domains](./specs/tech/ui-domains.md) and the actual domain manifests under [`ui/src/domains/`](./ui/src/domains/).
- **CauseStarter** ([`causestarter/`](./causestarter/), backlog [`causestarter/TODO.md`](./causestarter/TODO.md)): founder-first core domain (eventual primary entry; Tally / LazyGiving / etc. de-emphasized as tools). Included in `./scripts/services.sh --start` and `./scripts/deploy-causestarter.sh`. Local start currently publishes **only** the CauseStarter IPFS bundle (`LOCAL_UI_DOMAINS`; restore all UIs with `LOCAL_UI_DOMAINS=all` — see [local development](./workflow/local-development.md)). LLM helpers: [`cause-assist/`](./cause-assist/).
- **CauseStarter** (SPA in [`ui/src/causestarter/`](./ui/src/causestarter/), `VITE_DOMAIN=causestarter`; glue/backlog [`causestarter/`](./causestarter/), [`causestarter/TODO.md`](./causestarter/TODO.md)): founder-first core domain (eventual primary entry; Tally / LazyGiving / etc. de-emphasized as tools). Included in `./scripts/services.sh --start` and `./scripts/deploy-causestarter.sh`. Local start currently publishes **only** the CauseStarter IPFS bundle (`LOCAL_UI_DOMAINS`; restore all UIs with `LOCAL_UI_DOMAINS=all` — see [local development](./workflow/local-development.md)). LLM helpers: [`cause-assist/`](./cause-assist/).
- [Glossary](./specs/glossary.md) — the project's ubiquitous language. Read before naming anything; it also lists the known terminology drift.
- [Architecture Decision Records](./specs/decisions/README.md) — immutable log of *why* consequential decisions were made (and what was rejected). Grep before reversing something that looks wrong.
- [Role-based guidance](./workflow/roles/README.md) on what docs to read:
Expand Down
5 changes: 5 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ When an item from this page is done and no longer needs an LLM implementor's att

----

- **(Tell)** After folding CauseStarter into `ui/src/causestarter/`, leftover package
glue still talks as if `causestarter/src` is the SPA: `causestarter/vite.config.ts`
is unused, Compose/Docker docs mix `:8090` and `:5174`, and some verifier prompts
may still cite deleted paths. Sweep when touching local-dev docs.

- Add a fresh-stack integration test for the alignment-trust bootstrap: publish
an alignment vouch from a previously unknown wallet, observe the service's
`TrustSet(..., 100)`, confirm a wallet with no personal graph sees that vouch
Expand Down
6 changes: 4 additions & 2 deletions causestarter/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ COPY turbo.json ./turbo.json
RUN --mount=type=cache,target=/root/.npm HUSKY=0 npm ci --legacy-peer-deps

COPY sdk ./sdk
# In-app /docs bundles docs/end-user (endUserDocsPlugin).
COPY docs ./docs
# Cause board reuses ui/fundingportals (+ shared, lazy-giving, content-funding, delegation).
COPY ui ./ui
COPY causestarter ./causestarter
Expand All @@ -56,13 +58,13 @@ ENV VITE_WALLETCONNECT_PROJECT_ID=${VITE_WALLETCONNECT_PROJECT_ID}
ENV HUSKY=0

RUN npm run build --workspace=@commonality/sdk \
&& npm run build --workspace=causestarter
&& VITE_DOMAIN=causestarter npm run build --workspace=ui

# ---------------------------------------------------------------------------
FROM nginx:1.27-alpine AS runtime

COPY causestarter/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /workspace/causestarter/dist /usr/share/nginx/html
COPY --from=builder /workspace/ui/dist/causestarter /usr/share/nginx/html
COPY causestarter/docker-entrypoint.d/30-indexer-upstream.sh /docker-entrypoint.d/30-indexer-upstream.sh
COPY causestarter/docker-entrypoint.d/40-causestarter-config.sh /docker-entrypoint.d/40-causestarter-config.sh
RUN chmod +x /docker-entrypoint.d/30-indexer-upstream.sh \
Expand Down
30 changes: 22 additions & 8 deletions causestarter/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# CauseStarter

Organizer-first reference lens for the Commonality substrate. Where the main
[`ui/`](../ui/) package is organized as multi-domain product sites (Commonality,
Civility, CSM, LazyGiving, …), **CauseStarter** is a single app organized around
the cause-starter job:
Organizer-first reference lens for the Commonality substrate. The SPA source
lives in [`ui/src/causestarter/`](../ui/src/causestarter/) and is built as
`VITE_DOMAIN=causestarter` (`npm run causestarter:dev` → Vite on **:5174**).
This directory keeps Docker/nginx, Playwright, and the product backlog.

Where the other `ui/` domains are focused tool sites (Commonality, Civility,
CSM, LazyGiving, …), **CauseStarter** is organized around the cause-starter job:

1. **Organize a cause** — retrieve, review, and select the independent, signable statements it is made of
2. **Enroll people** — supporters (signers), volunteers, and collaborators
Expand Down Expand Up @@ -41,7 +44,7 @@ as main `CreateStatementForm`), not browser → Kubo API upload.

1. Start (or leave running) the local stack: `./scripts/services.sh --start` (or at least hardhat + indexer + **cause-assist** + gateway).
`cause-assist` is a Compose service (loopback **:3002**). You do **not** need a separate `npm run cause-assist:*` process for normal UI work.
2. Seed `causestarter/.env` from the running Docker SPA config (contract addresses + tool domain URLs):
2. Seed `ui/.env` (and optionally overlay `causestarter/.env`) from the running Docker SPA config (contract addresses + tool domain URLs). Vite HMR on :5174 reads `ui/.env`. IPFS/local publish merges `ui/.env` then `causestarter/.env`, then root contract-address mappings:

```bash
python3 scripts/seed-causestarter-vite-env.py
Expand All @@ -54,6 +57,7 @@ as main `CreateStatementForm`), not browser → Kubo API upload.

```bash
npm run causestarter:dev
# VITE_DOMAIN=causestarter in the ui package, port 5174
```

Or from this package: `npm run dev`.
Expand Down Expand Up @@ -207,6 +211,12 @@ See [`cause-assist/README.md`](../cause-assist/README.md). Bridge-cluster wordin

## Design notes

- **Landing pitch is jobs, not a movement lifecycle.** Hero and `/docs/the-jobs`
(`docs/end-user/causestarter/the-jobs.md`) are the “do the part you’d do anyway”
catalog. Do not restore Start → Grow → Deliver or “build a Movement.”
- **In-app docs** (`/docs/*`) bundle `docs/end-user/causestarter/`, `shared/`,
and `commonality/` via `endUserDocsPlugin`. Keep markdown links relative so
they resolve in that viewer.
- **CauseStarter is a lens, not a directory** ([ADR 0008](../specs/decisions/0008-operated-surfaces-are-lenses.md)).
It authors no discovery: no search, browse, ranking, featuring, or leaderboards.
A cause is reached at `/cause/:causeId` through a link its organizer circulates.
Expand Down Expand Up @@ -290,9 +300,13 @@ Then **restart Grok** so MCP tools load.
| `wallet-account-menu` | Hardhat account picker (localhost only) |
| `wallet-hardhat-0` … `wallet-hardhat-9` | Pick Hardhat account |
| `wallet-disconnect` | Disconnect |
| `home-start-cause` | Home CTA → create a draft and open the cause editor |
| `home-start-cause` | Home / `/welcome` CTA → create a draft and open the cause editor |
| `home-dashboard` | Occupied home (connected wallet and/or cause boards on this device) |
| `home-dashboard-board` | Occupied-home teaser of the personal fundable-projects board |
| `home-dashboard-see-all` | Occupied home → `/dashboard` (full personal list) |
| `personal-dashboard-page` | Full personal fundable-projects board at `/dashboard` |
| `nav-start` | Desktop/mobile nav “Start” → same (creates a new draft) |
| `cause-detail-page` | Cause page root (where all editing happens; brand-new drafts show “Start a cause” coach copy here) |
| `cause-detail-page` | Cause page root (where all editing happens; brand-new drafts show “Start a cause board” coach copy here) |
| `issue-guidance` | Static coach copy for what an issue is |
| `cause-add-plank` | Add an issue |
| `plank-text-N` | Nth issue's editable text (drafts only) |
Expand Down Expand Up @@ -329,7 +343,7 @@ CAUSESTARTER_BASE_URL=http://localhost:5174 CAUSESTARTER_HASH_ROUTING=0 \
### Example agent prompt

> Use the browser. Open http://localhost:8090/, click Connect, choose Hardhat #0,
> click “Start a cause”, describe the cause, click Continue, then add and publish
> click “Start a cause board”, describe the cause, click Continue, then add and publish
> issues on the cause page.

This package stays thinner than `ui/` (no multi-domain matrix, no Privy). Product posture:
Expand Down
4 changes: 3 additions & 1 deletion causestarter/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ open **if they stay listed here**.
- [ ] Statement `bookmarks` ref is still reserved infrastructure only — no CauseStarter (or main `ui`) surface for remembering a statement without signing it.
- [ ] No Privy path / full parity with main `ui` wallet story yet.
- [ ] Product: how CauseStarter ranks vs other domains in nav/marketing once it’s “the main thing.”
- [x] **Copy:** two-step rename in [cause-page-not-a-club.md](/specs/product/cause-page-not-a-club.md) — fundable-projects board first, then organizer **cause board**. Identifiers and leftover “cause page” still lag.
- [ ] **Personal dashboard** ([personal-dashboard.md](/specs/product/personal-dashboard.md)): home hero = fundable-projects union over signed statements (first slice shipped). Do **not** reuse unpublished cause-board drafts. Starring / named subsets / MutableRef filters stay deferred.

## Architecture

- [ ] Long-term: fold CauseStarter into the real domain/shell model (shared machinery, runtime config, domain manifests) as we make it the primary surface; avoid unbounded parallel app growth under a second package forever.
- [x] Fold CauseStarter into the real domain/shell model (`VITE_DOMAIN=causestarter` in `ui/`). Docker/e2e glue still lives in this directory.
- [ ] Optional: extract Hardhat local connectors for reuse by main `ui` local DX.

## Local stack notes
Expand Down
2 changes: 1 addition & 1 deletion causestarter/e2e/bookmarks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ test.describe('Cause bookmarks', () => {
await clearBrowserStorage(page)
await page.goto(appPath('/causes'))
await connectHardhat(page, 1)
await expect(page.getByRole('heading', { name: 'Causes', exact: true })).toBeVisible()
await expect(page.getByRole('heading', { name: 'Cause boards', exact: true })).toBeVisible()
await expect(page.getByRole('heading', { name: title, exact: true })).toHaveCount(0, {
timeout: 45_000,
})
Expand Down
12 changes: 9 additions & 3 deletions causestarter/e2e/connect-and-start.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ test.describe('CauseStarter agent smoke', () => {
await page.goto(appPath('/'))
})

test('occupied home shows the personal fundable-projects board after connect', async ({ page }) => {
await connectHardhat0(page)
await expect(page.getByTestId('home-dashboard-board')).toBeVisible({ timeout: 15_000 })
await expect(page.getByRole('heading', { name: /your fundable projects/i })).toBeVisible()
})

test('starts a cause and lands on its editable page', async ({ page }) => {
await expect(page.getByTestId('wallet-connect-button')).toBeVisible()
await expect(page.getByTestId('home-start-cause')).toBeVisible()
Expand All @@ -67,7 +73,7 @@ test.describe('CauseStarter agent smoke', () => {
// A brand-new cause has no planks, so no counts and nothing to select.
await expect(page.getByTestId('cause-view-strip')).toBeHidden()
await expect(page.getByTestId('cause-add-plank')).toBeVisible()
await expect(page.getByRole('heading', { name: /start a cause/i })).toBeVisible()
await expect(page.getByRole('heading', { name: /start a cause board/i })).toBeVisible()
})

test('edits issues in place on the cause page', async ({ page }) => {
Expand Down Expand Up @@ -105,11 +111,11 @@ test.describe('CauseStarter agent smoke', () => {
await expect(page.getByTestId('view-count-all')).toBeVisible()
})

test('Causes page starts a cause and opens the editor while connected', async ({ page }) => {
test('Cause boards page starts a cause board and opens the editor while connected', async ({ page }) => {
await connectHardhat0(page)

await page.getByTestId('nav-causes').click()
await expect(page.getByRole('heading', { name: 'Causes' })).toBeVisible()
await expect(page.getByRole('heading', { name: 'Cause boards' })).toBeVisible()
await page.getByTestId('causes-start-cause').click()

await expect(page.getByTestId('cause-detail-page')).toBeVisible({ timeout: 10_000 })
Expand Down
2 changes: 1 addition & 1 deletion causestarter/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#0f766e" />
<meta name="description" content="CauseStarter — start a cause, grow support, and deliver results toward shared goals." />
<meta name="description" content="CauseStarter — do the part you’d do anyway. Cooperate on agreement without a committee." />
<title>CauseStarter</title>
</head>
<body>
Expand Down
10 changes: 6 additions & 4 deletions causestarter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
"type": "module",
"scripts": {
"predev": "npm run build --workspace=@commonality/sdk",
"dev": "../node_modules/.bin/vite",
"typecheck": "tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.node.json --noEmit",
"build": "tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.node.json --noEmit && ../node_modules/.bin/vite build",
"dev": "npm run dev:causestarter --workspace=ui",
"typecheck": "npm run typecheck --workspace=ui",
"build": "VITE_DOMAIN=causestarter npm run build --workspace=ui",
"lint": "eslint .",
"test": "vitest run",
"test": "npm run test:vitest --workspace=ui -- src/causestarter",
"test:watch": "vitest",
"test:e2e": "playwright test --config=playwright.config.ts",
"test:e2e:headed": "playwright test --config=playwright.config.ts --headed",
Expand All @@ -25,7 +25,9 @@
"connectkit": "^1.9.1",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.18.2",
"rehype-sanitize": "^6.0.0",
"viem": "2.54.3",
"wagmi": "^3.6.21"
},
Expand Down
Loading
Loading