Skip to content

user-brx/merka-app

Repository files navigation

🌍 Merka

Decentralized open-source marketplace built on the Nostr protocol

License: MIT React TypeScript Nostr Version Website


What is Merka?

Merka is a free, open-source, censorship-resistant marketplace built on the Nostr protocol. It allows anyone in the world to buy, sell, and trade goods and services without relying on any central server, company, or intermediary.

πŸ”— Open Merka Web App directly in your browser.

No accounts with companies. No phone numbers. No email addresses. Just your cryptographic identity β€” yours alone, forever.

"Merka is the open market. Global by nature. Human by essence."


What does Merka do?

Feature Description
πŸ“¦ Buy & Sell Post marketplace listings on the Nostr network tagged with #Merka
🌍 Global Feed Browse real-time listings from traders around the world
πŸ‘₯ Follow Network Build a personal network of trusted buyers and sellers
πŸ” Search Users Find any user by npub, hex pubkey, name, NIP-05 address or bio text
πŸ” Private Messaging End-to-end encrypted direct messages (NIP-17 + NIP-44)
πŸ” Search Full-text search across the decentralized network (NIP-50)
🌐 15 Languages Fully localized: EN, PT, ES, IT, DE, HI, JA, ZH, AR, RU, FR, TR, FA, VI, UK
⚑ Lightning Zaps Generate BOLT11 invoices in-app, scan QR code, or pay via WebLN wallet extension β€” full NIP-57 flow
β‚Ώ Bitcoin On-chain Accept Bitcoin on-chain payments alongside Lightning β€” both in the same payment modal
🌐 Relay Management Add, remove and monitor relays in real time. NIP-65 relay lists published to Nostr
πŸ“± PWA Installable progressive web app β€” works on any device, no app store needed
🏷️ Custom Tags Filter and categorize listings with custom hashtags

Technology Stack

Merka is built entirely on open standards and open-source libraries, with no external UI framework and no backend.

Protocol Layer

Technology Role
Nostr Protocol Decentralized relay-based messaging
nostr-tools v2.23 Nostr implementation library
Bitcoin / Lightning Network Payments and value transfer

NIPs Implemented

NIP Description
NIP-01 Basic protocol β€” kind:0 profiles, kind:1 posts
NIP-02 Follow lists (kind:3)
NIP-04 Legacy encrypted DMs (kind:4) β€” maintained for compatibility
NIP-17 Private direct messages with gift wrap (kind:1059)
NIP-19 Bech32 entity encoding β€” npub, nsec, note1
NIP-25 Reactions β€” kind:7 likes
NIP-44 ChaCha20-Poly1305 authenticated encryption for DMs
NIP-49 Password-protected private keys (ncryptsec1 format)
NIP-50 Full-text relay search
NIP-57 Lightning Zaps β€” kind:9734 zap request, kind:9735 receipt, LNURL-pay, BOLT11 invoice generation
NIP-65 User relay lists (kind:10002) β€” published on relay changes

Frontend

Technology Role
React 19 + TypeScript UI framework
Vite 7 Build tool and dev server
Custom CSS No UI framework β€” glass-panel/purple design system
@fontsource/outfit Self-hosted fonts (no Google Fonts CDN)
react-qr-code QR code generation for Zap and donation addresses

Testing

Tool Role
Vitest 4 Test runner β€” fast, Vite-native
@testing-library/react Component testing β€” behavior-driven
@testing-library/user-event Realistic user interaction simulation
jsdom Browser environment for tests

Coverage: 379 tests across 12 test files covering all Nostr protocol functions, UI components, modals, hooks, i18n completeness (15 languages), and security boundaries.

npm test              # run all tests
npm run test:watch    # watch mode
npm run test:coverage # coverage report

Relays (default)

Merka connects to 6 well-known public relays by default: relay.damus.io, relay.primal.net, nos.lol, nostr.wine, purplepag.es, relay.snort.social


How Merka Protects You

Security and privacy are first-class citizens in Merka. Here is what is built in:

πŸ”‘ Your Keys, Your Identity

Your Nostr private key (nsec) never leaves your device. Merka stores it locally using NIP-49 encryption β€” you can set a password so even if someone accesses your browser storage, they cannot use your key without it.

πŸ” End-to-End Encrypted Messaging

All direct messages use NIP-17 gift wrap + NIP-44 (ChaCha20-Poly1305) β€” a modern authenticated encryption scheme that is significantly stronger than the deprecated NIP-04 (AES-CBC) used by older Nostr clients:

  • Authenticated: messages cannot be tampered without detection
  • Gift wrap (NIP-17): hides sender, receiver, and real timestamp from relay operators
  • Strong primitives: ChaCha20-Poly1305 via libsodium-compatible APIs

πŸ›‘οΈ Content Security Policy

A strict CSP header prevents:

  • Loading scripts or styles from external sources
  • Clickjacking and injection attacks
  • Unauthorized WebSocket connections to untrusted hosts

πŸ”— Safe Link Validation

All external links are validated against an https:// / http:// allowlist before rendering. Dangerous protocols (javascript:, data:, vbscript:, etc.) are silently dropped.

πŸ“‘ Trusted Relay Allowlist

When auto-discovering relays from the network, Merka only connects to a curated allowlist of known trusted relay domains β€” preventing relay injection attacks from malicious relay lists.

πŸ–ΌοΈ No External Image Loading

Merka does not load any external images β€” including profile pictures from Nostr profiles. Profile pictures are replaced by a deterministic text avatar derived from the last 2 characters of the user's public key. This completely eliminates tracking pixel attacks, where a malicious user could discover the IP address of anyone who views their posts.

🚫 No Tracking, No Servers

Merka has no backend, no analytics, no cookies, and no accounts. Everything runs in your browser and communicates directly with Nostr relays via WebSocket. Your data belongs to you.

Security Audit

A full security audit was performed covering:

  • Private key exposure risks
  • XSS and content injection
  • Relay trust model
  • Cryptographic correctness (NIP-44 vs NIP-04)
  • Content Security Policy
  • Unsafe URL protocols

All identified issues are resolved. See docs/security-audit.md for the full report.


Running Locally

# 1. Clone the repository
git clone https://github.com/YOUR_USERNAME/merka.git
cd merka

# 2. Install dependencies
npm install

# 3. Start the development server
npm run dev
# Open http://localhost:5173

# 4. Build for production
npm run build

# 5. Preview the production build
npm run preview

Requirements: Node.js 18+, npm 9+


Project Structure

.
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ App.tsx                    # Root orchestrator β€” auth, modal routing, state
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ constants.ts           # APP_GUID, MERKA_PUBKEY, donation addresses
β”‚   β”‚   └── constants.test.ts
β”‚   β”œβ”€β”€ hooks/
β”‚   β”‚   β”œβ”€β”€ useNostrAuth.ts        # Login, logout, NIP-49 protection, 30-day session
β”‚   β”‚   └── useRelays.ts           # Real-time relay health monitoring
β”‚   β”œβ”€β”€ services/nostr/
β”‚   β”‚   β”œβ”€β”€ nostr.ts               # Entry point β€” re-exports + publish functions
β”‚   β”‚   β”œβ”€β”€ pool.ts                # Shared SimplePool instance
β”‚   β”‚   β”œβ”€β”€ relayHealth.ts         # RELAYS list, health monitoring
β”‚   β”‚   β”œβ”€β”€ messaging.ts           # DMs: NIP-17/44 gift wrap
β”‚   β”‚   β”œβ”€β”€ auth.ts                # createKeys, loginWithKey, fetchProfile, follow lists
β”‚   β”‚   β”œβ”€β”€ zap.ts                 # NIP-57: LNURL-pay, zap request, BOLT11 invoice
β”‚   β”‚   β”œβ”€β”€ nostr.test.ts
β”‚   β”‚   └── nostr-extended.test.ts
β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”œβ”€β”€ Login/Login.tsx        # Key creation + login screen
β”‚   β”‚   └── Feed/
β”‚   β”‚       β”œβ”€β”€ Feed.tsx           # Main feed β€” subscribe, post, reactions
β”‚   β”‚       β”œβ”€β”€ ProfilePanel.tsx   # Edit profile (name, bio, lud16, BTC address, NIP-05)
β”‚   β”‚       β”œβ”€β”€ ProfilePanel.test.tsx
β”‚   β”‚       β”œβ”€β”€ ChatHistoryPanel.tsx # DM history with unread badge
β”‚   β”‚       β”œβ”€β”€ KeyWarningModal.tsx  # Secure nsec display after key creation
β”‚   β”‚       β”œβ”€β”€ ZapModal.tsx         # ⚑ Lightning + β‚Ώ Bitcoin payment modal (tabs, BOLT11, QR)
β”‚   β”‚       └── ZapModal.test.tsx
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ feed/
β”‚   β”‚   β”‚   β”œβ”€β”€ NoteCard.tsx       # Note card + AuthorProfile popup (copy npub)
β”‚   β”‚   β”‚   └── NoteCard.test.tsx
β”‚   β”‚   β”œβ”€β”€ chat/
β”‚   β”‚   β”‚   β”œβ”€β”€ ChatPanel.tsx      # Real-time encrypted DM panel
β”‚   β”‚   β”‚   └── ChatPanel.test.tsx
β”‚   β”‚   β”œβ”€β”€ ui/icons.tsx           # All SVG icons inline
β”‚   β”‚   └── modals/
β”‚   β”‚       β”œβ”€β”€ about/             # AboutMerka, AboutNostr
β”‚   β”‚       β”œβ”€β”€ donate/            # DonateModal, WalletGuide
β”‚   β”‚       β”œβ”€β”€ network/
β”‚   β”‚       β”‚   β”œβ”€β”€ NetworkListModal.tsx    # Followers/Following + search by npub/hex
β”‚   β”‚       β”‚   β”œβ”€β”€ RelaySettingsModal.tsx  # Add/remove relays + confirm before delete
β”‚   β”‚       β”‚   └── RelaySettingsModal.test.tsx
β”‚   β”‚       └── security/
β”‚   β”‚           β”œβ”€β”€ KeyProtectionModal.tsx  # NIP-49 password setup
β”‚   β”‚           β”œβ”€β”€ UnlockKeyModal.tsx      # NIP-49 decrypt on login
β”‚   β”‚           β”œβ”€β”€ KeyProtectionModal.test.tsx
β”‚   β”‚           └── UnlockKeyModal.test.tsx
β”‚   β”œβ”€β”€ i18n/
β”‚   β”‚   β”œβ”€β”€ translations.ts        # 15 languages: EN PT ES IT DE HI JA ZH AR RU FR TR FA VI UK
β”‚   β”‚   └── translations.test.ts
β”‚   └── styles/
β”‚       └── index.css              # Full design system β€” glassmorphism, purple theme
β”œβ”€β”€ public/
β”‚   └── manifest.json              # PWA manifest
└── docs/
    β”œβ”€β”€ FEATURES.md                # Nostr roadmap & feature backlog
    └── security-audit.md          # Full security audit report

Contributing

Merka is open source and contributions are welcome.

  1. Report bugs β€” open an issue describing steps to reproduce
  2. Suggest features β€” open an issue explaining the use case
  3. Submit a PR β€” fork, create a branch, code, test, pull request

Please follow the existing conventions:

  • TypeScript strict mode β€” no any without justification
  • No external UI libraries β€” custom CSS only
  • All visible text must use t.key from src/i18n/translations.ts
  • New i18n keys must be added to all 15 languages
  • Run npm test β€” all 379 tests must pass
  • Run npm run build before submitting β€” zero TypeScript errors required

Support the Creator ⚑

Merka is free software built with passion for a better, open internet. If it helps you, please consider supporting the original creator:

Method Address
⚑ Lightning (Zap) smarteranswer31@walletofsatoshi.com
β‚Ώ Bitcoin (on-chain) bc1qxdmvlzvm4p9tle5vxfh0tyns3lwryet8886vrv
🟣 Nostr npub16djn9xucugk5wp76x0trhvy5eldv3juzwq92jng72ax26puzeyls327tm6

If you fork or deploy your own version of Merka, please keep the donation addresses visible in the app's "About Merka" screen so the original creator continues to receive support from the community.


License

This project is licensed under the MIT License β€” see LICENSE.md for full details.

You are free to use, copy, modify, merge, publish, distribute, sublicense, and sell copies of this software. The only requirement is to keep the copyright notice and permission notice in all copies or substantial portions of the software.


Built with ❀️ on the Nostr protocol · No borders · No intermediaries · No barriers

nostr.com Β· Nostr Profile

About

Merka is a decentralized, censorship-resistant P2P marketplace built on the Nostr protocol. Discover, buy, and sell items securely using the Lightning Network. Features multi-language support, real-time decentralized chat, and an intuitive UI for seamless trading without intermediaries.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors