Skip to content

Latest commit

 

History

1,242 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Conduit

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.market

Conduit code is MIT-licensed. Conduit trademarks, names, and logos are reserved. See LICENSE, TRADEMARKS.md, and OPEN_SOURCE.md.


Apps

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

Shared Packages

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

Prerequisites

  • 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

Quick Start

# Clone and install
git clone https://github.com/Conduit-BTC/conduit-mono.git
cd conduit-mono
bun install

# Start all apps
bun run dev

This 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-builder

Local Development Setup

1. Local Relay

A 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:stop

Or use Docker/Bun explicitly:

# Docker (nostr-rs-relay)
bun run relay:local:start:docker

# Bun (lightweight, no Docker needed)
bun run relay:local:start:bun

2. Environment Variables

Each 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.mock for local/mock development
  • .env.mainnet for 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 lnbcrt invoices, yellow badge in header. Use for local dev.
  • signet / testnet — Real Lightning test networks. Use for integration testing.
  • mainnet — Production Lightning, no badge.

3. Seed Test Products

SEED_NSEC=<your-test-nsec> SEED_RELAY_URLS=ws://127.0.0.1:7777 bun run seed:products

Generate a throwaway nsec for seeding:

bun run seed:nsec

4. Publish NIP-89 Handler Metadata

Conduit 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-run

Then publish without --dry-run and verify the resulting 31990 events on the target relay(s): pubkey, d, k, web, and replaceable-event address.

5. Test a Purchase Flow

  1. Open Market (http://localhost:3000) — connect signer as buyer
  2. Open Merchant Portal (http://localhost:3001) in a different browser profile — connect a different signer as merchant
  3. Merchant: Products > New Product > publish
  4. Buyer: Products > Add to Cart > Checkout > Place Order
  5. Merchant: Orders > send payment request or confirm payment state
  6. 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.


Common Commands

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_modules

See CONTRIBUTING.md for the full PR checklist and CI recovery notes.

Project Structure

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

Tech Stack

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

Open Source

  • 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.

Protocol

  • 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.

Docs


Links

License

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.

About

Decentralized commerce on Nostr + Bitcoin Lightning

Resources

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages