{"path":"README.md","size":5643,"locked":false,"binary":false,"truncated":false,"content":"# Anchr CLI (MVP)\n\n[![CI](https://github.com/mrphatom/Anchr/actions/workflows/ci.yml/badge.svg)](https://github.com/mrphatom/Anchr/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\nDeploy static frontends to IPFS and resolve them via a Solana Name Service\n(`.sol`) domain — `init` and `deploy`, nothing else, on purpose.\n\n## Project structure\n\n```\nbin/anchr.js       CLI entry point\nlib/               init/deploy orchestration, framework detection,\n                    Storacha upload, SNS record read/write\ntests/             unit tests (Node's built-in test runner)\ndocs/              architecture + roadmap (useful for grant write-ups)\nexample/           how to spin up a test site to deploy against\ndashboard/         status/pitch site for the project, deployed through\n                    Anchr itself — its own package.json, separate from\n                    the CLI's\n.github/           CI, issue/PR templates, dependabot\n```\n\n## Scope (locked for MVP)\n\n- Frameworks: Vite, Next.js (static export only), Create React App\n- Pinning: Storacha (default) or Filebase (fallback) — see \"Alternate\n  pinning provider\" below\n- Domains: SNS (`.sol`) only, **V2 record format** — confirmed working via\n  a real devnet transaction (see `lib/sns.js` and `CHANGELOG.md`); V1 was\n  tried first and abandoned after repeated unexplained signer errors\n- No `logs`, no env-var UI, no multi-provider-at-once pinning — that's all v2+\n\n## One-time setup\n\n**1. Install the Storacha CLI and create a Space** (see project notes for\nthe full from-scratch walkthrough):\n\n```bash\nnpm install -g @storacha/cli\nstoracha login your+anchr@gmail.com\nstoracha space create anchr-project\n```\n\n**2. Generate CI credentials** for this CLI to use non-interactively:\n\n```bash\nstoracha key create --json\n# copy the \"key\" value → ANCHR_STORACHA_KEY\n\nstoracha delegation create <did-from-above> --can 'space/blob/add' --can 'upload/add' --base64\n# copy the output → ANCHR_STORACHA_PROOF\n```\n\n**3. Copy `.env.example` to `.env`** and fill in:\n- `ANCHR_STORACHA_KEY` / `ANCHR_STORACHA_PROOF` (from step 2)\n- `ANCHR_WALLET_SECRET_KEY` — the Solana wallet that owns your `.sol` domain,\n  as a JSON array (paste the contents of a Solana CLI keypair file)\n\n**4. Install dependencies:**\n\n```bash\nnpm install\n```\n\n## Usage\n\n```bash\nanchr init      # detects your framework, writes anchr.json\nanchr deploy    # builds + pins to IPFS; also writes the SNS record if\n                # anchr.json has a \"domain\" set (optional — omit it to\n                # just get a pinned CID + gateway link)\n```\n\n## ⚠️ Before running against a real domain\n\nImportant limitation, confirmed via testing: `lib/sns.js` uses the SDK's\n**top-level** V2 record functions, which have no devnet override at all\n(same gap as `getRecordV2`'s missing cluster option) — attempting to run\nthem against devnet fails with \"program does not exist,\" since they're\nhardcoded to mainnet's program ID. This means **`lib/sns.js` cannot be\ndevnet-tested directly.** The devnet confirmation we do have (see\n`CHANGELOG.md`) used `devnet.bindings` equivalents instead — that proves\nthe underlying Name Service Program's create-then-update *pattern*\nworks, not literally this file's own code path.\n\nPractical result: the create path is proven at the protocol level; the\nupdate-fallback in `writeIpfsRecord` has **no verification path available\nbefore mainnet** — you'll be testing it for real the first time you\nredeploy to a domain that already has a record set. Use `readIpfsRecord()`\nafterward to confirm it landed correctly.\n\n## Relative asset paths (important)\n\nIPFS serves your site from a `/ipfs/<CID>/` subpath, not domain root — so\ndefault absolute asset paths will produce a **blank page**, even though\nthe deploy itself succeeds. Confirmed via a real deploy: Vite needs\n`base: './'` in `vite.config.js` (`anchr init` prints this as a note\nwhen it detects Vite). CRA needs `\"homepage\": \".\"` in `package.json`.\nNext.js likely needs a similar `assetPrefix` fix but this hasn't been\nconfirmed with a real deploy yet.\n\n## Alternate pinning provider (Filebase)\n\nStoracha is the default, but if its upload endpoint is unreachable, set\n`\"provider\": \"filebase\"` in `anchr.json` and fill in the Filebase env vars\nin `.env` (see `.env.example`) instead. It uses Filebase's S3-compatible\nupload path under the hood (`@filebase/sdk`'s `ObjectManager`), not their\nIPFS Pinning Service API — that API is for re-pinning an *existing* CID,\nnot uploading new local content, so it doesn't fit Anchr's use case.\n\nThis is a fallback switch, not a \"run both\" setup — only one provider is\nactive per deploy, matching the MVP's \"one pinning provider\" scope.\n\n## Known prior art\n\n`Bonfida/sns-deploy` did something similar back in 2021 (Infura pinning +\nraw wallet.json path, no CI integration, no framework detection). Anchr's\ndifferentiation: modern pinning via Storacha/UCAN, automatic framework\ndetection, and a CI-friendly credential model — built for a GitHub-push\ndeploy flow rather than a one-off manual CLI run.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) — note that MVP scope is intentionally\nlocked, so check [docs/ROADMAP.md](docs/ROADMAP.md) before proposing new\nfeatures. This project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).\n\n## Security\n\nHandling a Solana wallet key and IPFS upload credentials — see\n[SECURITY.md](SECURITY.md) before reporting anything sensitive, and for\nguidance on keeping the signing wallet scoped to just this domain.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n"}