Decentralized commerce platform built on Nostr. Merchants and buyers transact directly over the protocol without Conduit custody of funds. Private commerce data is encrypted and processed by users' browsers, counterparties, and services they choose as described in the Product Privacy Policy.
Conduit code is MIT-licensed. Conduit trademarks, names, and logos are reserved. See LICENSE, TRADEMARKS.md, and OPEN_SOURCE.md.
| App | Port | Description |
|---|---|---|
Market / Conduit Shop (apps/market) |
3000 | Buyer marketplace: browse, checkout, orders, and device-local wallets |
Merchant Portal / Conduit Sell (apps/merchant) |
3001 | Seller app at sell.conduit.market: listings, orders, payments, and DMs |
Store Builder (apps/store-builder) |
3002 | Placeholder app shell |
| Package | Description |
|---|---|
@conduit/core |
Types, Nostr protocol helpers, schemas (Zod), React Query hooks, Dexie DB, utilities |
@conduit/ui |
shadcn/ui components, design tokens, theme styles |
- Bun v1.1+
- A Nostr signer browser extension (Alby, nos2x, or similar NIP-07 extension)
- (Optional) NWC wallet connection for Lightning payment requests and proofs
# Clone and install
git clone https://github.com/Conduit-BTC/conduit-mono.git
cd conduit-mono
bun install
# Start all apps
bun run devThis starts Market on http://localhost:3000, Merchant Portal on http://localhost:3001, and Store Builder on http://localhost:3002.
The plain dev command uses each app's normal Vite environment resolution. Use the :mock scripts with the local relay when you want isolated fake Lightning invoices and local-only relay traffic.
# Or start individually
bun run dev:market
bun run dev:merchant
bun run dev:store-builderA local relay keeps your dev environment isolated from public relays. Both modes expose ws://127.0.0.1:7777.
# Auto-selects Docker if available, otherwise uses a Bun WebSocket relay
bun run relay:local:start
# View logs
bun run relay:local:logs
# Stop
bun run relay:local:stopOr use Docker/Bun explicitly:
# Docker (nostr-rs-relay)
bun run relay:local:start:docker
# Bun (lightweight, no Docker needed)
bun run relay:local:start:bunEach app reads VITE_-prefixed env vars via Vite. A root .env.example shows available options. For isolated local dev, start the local relay and use the committed mock mode files.
For shared network switching, Market and Merchant also support committed mode files:
.env.mockfor local/mock development.env.mainnetfor public-relay/mainnet-style testing
Use the mode-specific scripts instead of hand-editing .env.local:
bun run dev:market:mock
bun run dev:merchant:mock
bun run dev:market:mainnet
bun run dev:merchant:mainnet.env.local should remain for personal overrides only. Keep mode files minimal and let the shared core relay defaults handle the broader fallback strategy unless a mode truly needs different values.
| Variable | Default (dev) | Description |
|---|---|---|
VITE_RELAY_URL |
— | Optional single relay hint also added to fallback relays |
VITE_DEFAULT_RELAY_URL |
— | Optional single relay added to fallback relay discovery |
VITE_DEFAULT_RELAYS |
— | Optional comma-separated relays added to fallback reads |
VITE_APP_WRITE_RELAY_URLS |
— | Optional comma-separated app write relay additions |
VITE_PUBLIC_RELAY_URLS |
— | Optional comma-separated public relay override/additions |
VITE_COMMERCE_RELAY_URLS |
— | Optional comma-separated commerce relay additions |
VITE_LIGHTNING_NETWORK |
mainnet |
mainnet, signet, testnet, or mock |
VITE_BLOSSOM_SERVER_URL |
— | Blossom media server for product images |
VITE_CACHE_API_URL |
— | Optional cache/acceleration API endpoint |
VITE_ENABLE_TELEMETRY |
false |
Enables privacy-filtered telemetry |
VITE_TELEMETRY_ALLOWED_HOSTS |
— | Required comma-separated telemetry host allowlist |
VITE_PLAUSIBLE_DOMAIN |
— | Legacy nonofficial/dev Plausible site domain |
VITE_PLAUSIBLE_SRC |
— | Legacy nonofficial/dev Plausible script URL |
VITE_POSTHOG_KEY |
— | Optional official Product browser project key |
VITE_POSTHOG_HOST |
https://e.conduit.market |
Ignored off official hosts; official hosts pin the proxy |
VITE_NIP89_RELAY_HINT |
VITE_RELAY_URL |
Relay hint for Conduit NIP-89 handler metadata |
VITE_NIP89_MARKET_PUBKEY |
— | Official Conduit Market handler pubkey |
VITE_NIP89_MERCHANT_PUBKEY |
— | Official Conduit Merchant Portal handler pubkey |
VITE_APP_VERSION |
app package version | Build-time app version surfaced on About pages |
VITE_BUILD_COMMIT |
current git commit | Commit SHA surfaced on About pages |
VITE_BUILD_BRANCH |
current git branch | Branch or preview ref surfaced on About pages |
VITE_BUILD_TIME |
current build time | Build timestamp surfaced on About pages |
VITE_SOURCE_URL |
GitHub repository URL | Source repository link surfaced on About pages |
VITE_RELEASE_CHANNEL |
local/preview/prod | Release channel surfaced on About pages |
VITE_DM_BOOTSTRAP_WRITES |
profile-controlled | Legacy compiled input for validated-order compatibility |
When telemetry is enabled, VITE_TELEMETRY_ALLOWED_HOSTS must list every
permitted hostname. A *. prefix allows exactly one preview subdomain label;
it does not match nested or lookalike domains. This allowlist may enable the
legacy Plausible test path, but it cannot enable PostHog. Product PostHog loads
only when the runtime app and hostname are the exact official pair:
shop.conduit.market for Market or sell.conduit.market for Merchant.
The canonical fallback/reset relay list is code-owned in packages/core/src/config.ts and currently starts from:
wss://relay.conduit.market
wss://nos.lol
wss://relay.ditto.pub
wss://relay.primal.net
Browser builds print a relay map in DevTools showing the code defaults, raw/normalized relay env vars, and the final resolved relay lists. Conduit-hosted deploys should leave relay env vars empty so reviewers can compare the open-source code defaults with the deployed behavior.
Public deployment behavior is repo-owned in deploy/pages-profiles.json.
Cloudflare Pages selects staging when its deployment URL belongs to a
repo-owned Signet project, preview for other non-main branches, and
production for main; CI selects its profile explicitly. Preview enables
validated-order compatibility routing so the feature is reviewable. Production
and the Signet staging profile remain independently controlled. Dashboard
VITE_* values cannot directly override those managed flags, but Pages build
metadata and operator configuration remain part of the trusted release
boundary. A runtime drift guard forces compatibility routing off when an
official Shop or Sell host receives a non-production profile or a Signet Pages
host receives a non-staging profile. Every app emits
/.well-known/conduit-deployment.json with its profile, source commit, build
time, public feature flags, and public-config digest; the manifest is a strict
non-secret allowlist.
PostHog telemetry uses sessionStorage-only SDK state, one static browser-service distinct ID, and disabled person-profile processing. The project must discard IP data. Do not enable PostHog's server-hashed cookieless mode for these events: it requires raw IP, host, and user-agent inputs that Conduit's privacy filter intentionally does not send.
Modes:
- mock — Fake
lnbcrtinvoices, yellow badge in header. Use for local dev. - signet / testnet — Real Lightning test networks. Use for integration testing.
- mainnet — Production Lightning, no badge.
SEED_NSEC=<your-test-nsec> SEED_RELAY_URLS=ws://127.0.0.1:7777 bun run seed:productsGenerate a throwaway nsec for seeding:
bun run seed:nsecConduit uses NIP-89 kind:31990 handler metadata plus outbound client tags
for protocol-level app provenance. Market and Merchant also expose human-facing
About pages with build metadata, source links, and the matching NIP-89 app
identity.
Official client/source names are:
- Market:
Conduit Market - Merchant:
Conduit Merchant Portal
Set the matching VITE_NIP89_*_PUBKEY values in deploy env before relying on
outbound client tags. The publish helper should be run with dedicated
Conduit-controlled app keys, never a user or merchant signer.
The app build injects version, commit, branch, build time, release channel, and
source URL from CI-friendly environment variables. Cloudflare Pages and GitHub
Actions variables are used when explicit VITE_BUILD_* overrides are absent.
Dry-run first:
NIP89_APP=market NIP89_NSEC=<market-nsec> NIP89_RELAY_URLS=wss://relay.conduit.market bun run nip89:publish-handler -- --dry-run
NIP89_APP=merchant NIP89_NSEC=<merchant-nsec> NIP89_RELAY_URLS=wss://relay.conduit.market bun run nip89:publish-handler -- --dry-runThen publish without --dry-run and verify the resulting 31990 events on the
target relay(s): pubkey, d, k, web, and replaceable-event address.
- Open Market (http://localhost:3000) — connect signer as buyer
- Open Merchant Portal (http://localhost:3001) in a different browser profile — connect a different signer as merchant
- Merchant: Products > New Product > publish
- Buyer: Products > Add to Cart > Checkout > Place Order
- Merchant: Orders > send payment request or confirm payment state
- Buyer: Orders > see payment request/proof state, status updates, shipping info
Market's /wallet route is device-owned and can be used without connecting a
Nostr signer. It supports multiple Portable Wallets (Spark is the first
provider) and multiple Connected Wallets (NWC is the first protocol). Wallet
credentials remain device-local; wallet identifiers and balances are excluded
from Conduit telemetry.
bun run dev # Start all apps
bun run build # Build all (core -> ui -> apps)
bun run format:fix # Format changed files
bun run format:check # Check changed-file formatting
bun run typecheck # TypeScript check all packages
bun run lint # Lint all packages
bun test # Run tests
bun run clean # Remove all node_modulesSee CONTRIBUTING.md for the full PR checklist and CI recovery notes.
conduit-mono/
├── apps/
│ ├── market/ # Buyer marketplace
│ ├── merchant/ # Seller portal
│ └── store-builder/ # Placeholder app shell
├── packages/
│ ├── core/ # Types, protocol, schemas, hooks, DB, utils
│ └── ui/ # Components, theme, styles
├── docs/
│ ├── README.md # Docs index and source-of-truth guide
│ ├── ARCHITECTURE.md # System diagrams and data flow
│ ├── DESIGN.md # Shared design system and theming guidance
│ ├── specs/ # Active feature specifications
│ └── knowledge/ # Supporting notes and references
└── scripts/ # Dev tooling, CI helpers, seed data
| Layer | Choice |
|---|---|
| Runtime | Bun |
| Build | Vite 6 + SWC |
| Framework | React 19 |
| Routing | TanStack Router (file-based, type-safe) |
| Server State | TanStack Query over shared Nostr protocol helpers |
| Client State | React Context (auth only) |
| Local Storage | Dexie (IndexedDB) for orders, messages, cache, wallet records |
| Forms | react-hook-form + Zod |
| UI | shadcn/ui + Tailwind CSS |
| Protocol | Nostr via @conduit/core helpers; NDK is the current edge library |
| Payments | Lightning via Spark, NWC (NIP-47), WebLN, invoices, and proofs |
| Messaging | NIP-17 gift-wrapped encrypted DMs |
- Code and redistributable bundled assets in this repository are MIT-licensed.
- Released legal prose under
packages/ui/src/legal/versions/is excluded from the MIT grant so a fork cannot present modified terms as Conduit-approved. - Conduit names, logos, and branded app identities are not granted under the MIT license.
- Forks are welcome, but they must not imply official Conduit operation or endorsement.
- Public client builds should remain rebuildable from the public repository without private production assets.
See OPEN_SOURCE.md for reproducible-build notes and TRADEMARKS.md for brand usage rules.
- Authentication: Durable Nostr account keys remain in external NIP-07 or NIP-46 signers. Guest checkout may create a temporary order-scoped browser key, and NIP-46 connections may use an encrypted browser-local client key; neither is a Conduit-custodied account key.
- Products: Kind 30402 replaceable events (NIP-99)
- Orders: NIP-17 gift-wrapped encrypted DMs between buyer and merchant
- Payments: Non-custodial Lightning through Portable Wallets, NWC/WebLN payment rails, invoices, and payment proofs. Portable Wallet credentials are a separate, isolated client-side boundary; no Conduit-operated service can control funds.
- Profiles: Kind 0 metadata events (NIP-01)
See ARCHITECTURE.md for system diagrams and protocol details.
- conduit.market
- Conduit Shop Product Privacy Policy
- Conduit Shop Product Terms of Service
- Conduit Sell Product Privacy Policy
- Conduit Sell Product Terms of Service
- Nostr profile
MIT for code and redistributable bundled assets in this repository, except for the released legal prose identified in LICENSE.
Conduit trademarks and logos are reserved and are not licensed under MIT. See TRADEMARKS.md.