Getting Started
Setting Up Your Work Environment
Before cloning, make sure these tools are installed:
| Tool | Min Version | Purpose | Install |
|---|---|---|---|
| Node.js | 22+ | Runtime for scripts and tooling | nodejs.org |
| Bun | 1.x+ | Package manager and monorepo runner | curl -fsSL https://bun.sh/install | bash |
| Git | any | Version control | git-scm.com |
| Foundry | any | Solidity compiler and testing (forge) | curl -L https://foundry.paradigm.xyz | bash && foundryup |
| Docker | any | Runs the Envio indexer locally | docker.com |
| cloudflared | any | HTTPS tunnel for mobile device testing | brew install cloudflared |
Foundry, Docker, and cloudflared are only required for their respective workflows (contracts, indexer, mobile testing). The setup script warns but does not block if they are missing.
Running Development Setup
git clone https://github.com/greenpill-dev-guild/green-goods.git
cd green-goods
bun setup # checks deps, installs packages, creates .env
bun dev # starts all services via PM2
What bun setup does
The setup script (scripts/setup.js) runs through four steps:
- Dependency check -- verifies Node.js 22+, Bun 1.x, Git, Docker, and Foundry are available. Missing optional tools produce warnings, not errors.
- Install packages -- runs
bun installacross all workspaces ifnode_modulesdoes not exist yet. - Environment file -- generates
.envfrom.env.schemadefaults if no.envexists. For standard local 1Password CLI installs, prefer root-only*_OP_REF=op://...entries in.env. ReserveOP_ENVIRONMENTbulk loading for CI, service-account flows, or newer CLI builds that support it. - Next steps -- prints the commands to start developing.
Required Secrets & Variables
Green Goods uses a single root .env bootstrap plus committed .env.schema validation — never create package-level env files. Key variables:
| Variable | Role |
|---|---|
APP_ENV | Environment selector (development, test, staging, production) |
ETHERSCAN_API_KEY_OP_REF | Example local 1Password secret reference in root .env (op://vault/item/field) for stable desktop-app auth |
OP_ENVIRONMENT | 1Password environment name/id used only for bulk injection in CI, service-account flows, or local beta-capable CLI installs |
OP_SERVICE_ACCOUNT_TOKEN | 1Password service account token (required in CI/deployed environments, optional locally if you want service-account auth) |
VITE_CHAIN_ID | Sets the target chain at build time (e.g. 11155111 for Sepolia, 42161 for Arbitrum) |
PINATA_JWT | Pinata JWT for the shared IPFS upload path |
SEPOLIA_RPC_URL | RPC endpoint for Sepolia fork tests |
Use .env.schema as the full environment contract. Variables prefixed with VITE_ are embedded into frontend bundles at build time.
For normal local development, sign in to the standard op CLI with desktop app integration enabled, keep OP_ENABLE_ENVIRONMENT_LOAD=false, and add root .env entries like ETHERSCAN_API_KEY_OP_REF=op://vault/item/field for the secrets you need. varlock run resolves those references directly.
For CI workflows or local service-account usage, set OP_SERVICE_ACCOUNT_TOKEN, set OP_ENVIRONMENT, and enable OP_ENABLE_ENVIRONMENT_LOAD=true when you want Varlock to bulk-load a 1Password Environment.
Running services
All at once
bun dev launches every service through PM2:
| PM2 process | Package | Default port |
|---|---|---|
client | packages/client | 3001 |
admin | packages/admin | 3002 |
docs | docs | 3003 |
indexer | packages/indexer (Docker / GraphQL) | 8080 |
agent | packages/agent | -- |
tunnel | cloudflared HTTPS tunnel | -- |
storybook | packages/shared | 6006 |
Stop everything with bun dev:stop.
Individual packages
You can also run packages directly without PM2:
bun dev:client # Gardener PWA
bun dev:admin # Operator dashboard
bun dev:docs # Docusaurus site
bun dev:indexer # Envio indexer (Docker Compose)
bun dev:contracts # Anvil local chain
bun dev:agent # Agent bot
Mobile device testing
Green Goods is a mobile-first PWA, so testing on a real phone is essential. When you run bun dev, a cloudflared tunnel starts automatically alongside the other services. It creates a temporary public HTTPS URL (e.g. https://random-words.trycloudflare.com) that points to your local client on port 3001.
Once the tunnel is ready, the landing page QR code automatically switches to the tunnel URL. Open https://localhost:3001 on your laptop and scan the QR code with your phone — you'll get the full PWA experience including service worker, install prompts, and passkey auth.
# Tunnel starts automatically with bun dev.
# To run it standalone (e.g. for the admin dashboard):
bun run dev:tunnel # default: port 3001
bun run dev:tunnel -- --port 3002 # admin on port 3002
If cloudflared is not installed, the tunnel service exits silently and the QR code falls back to window.location.origin. Install it with brew install cloudflared.
If you prefer a wired connection, plug in your Android device with USB debugging enabled and run:
adb reverse tcp:3001 tcp:3001
Then navigate to https://localhost:3001 on Android Chrome. Since localhost is a secure context, the service worker registers without a trusted CA certificate.
First-run checklist
- 1
Read project rules
Start with `AGENTS.md`, `CLAUDE.md`, and `.claude/context/*` for conventions.
- 2
Configure env bootstrap
Set `APP_ENV` in root `.env`. For local 1Password on the stable CLI, add `*_OP_REF=op://...` entries there and keep `OP_ENABLE_ENVIRONMENT_LOAD=false`. Use root `.env` only -- never add package-level env files.
- 3
Start services
Run `bun dev` and verify client, admin, indexer, and docs start cleanly.
- 4
Run the quality gate
Run `bun run test`, `bun lint`, and `bun build` before pushing changes.
Development workflow
The standard edit-test-build-lint cycle:
# 1. Run tests for the package you changed (always `bun run test`, never `bun test`)
cd packages/shared && bun run test
# 2. Lint the workspace
bun lint
# 3. Build (respects dependency order: contracts -> shared -> indexer -> client/admin)
bun build
# 4. Format before committing
bun format
bun test vs bun run testbun test invokes Bun's built-in test runner, which ignores your Vitest config. Always use bun run test to run the package.json script with proper environment setup.
Troubleshooting & Common Issues
| Symptom | Cause | Fix |
|---|---|---|
forge: command not found | Foundry not installed | curl -L https://foundry.paradigm.xyz | bash && foundryup |
| Indexer fails to start | Docker not running | Start Docker Desktop, then retry bun dev:indexer |
VITE_CHAIN_ID is undefined | Missing .env | Run bun setup or run APP_ENV=development bunx varlock load --path .env.schema --format env --compact > .env |
| Port 3001/3002 in use | Another dev server running | Kill the process or change the port in the package's Vite config |
bun install hangs | Stale lockfile | Delete node_modules and bun.lockb, then bun install |
| No QR code on landing page | cloudflared not installed | brew install cloudflared, then restart bun dev |
| Tunnel URL not appearing | Client not ready yet | The tunnel waits up to 60s for port 3001 — check PM2 logs with npx pm2 logs tunnel |
Non-negotiables
- All React hooks live in
packages/shared-- client and admin only have components and views. - The target chain derives from
VITE_CHAIN_IDat build time. There is no runtime chain switching. - Deployment changes go through
bun deploy:*wrappers, never rawforgecommands. - User-facing strings must be added to all three translation files (
en.json,es.json,pt.json).
Next page
Next best action
Keep momentum by moving to the next high-value step in this journey.
Architecture