Kontractz — B2B Trade Marketplace Platform
A custom B2B trade platform — trade leads, RFQs, vendor storefronts, deal rooms and memberships — built as an application rather than a website.
- Client
- Kontractz
- Industry
- B2B trade / marketplace
- Services
- Platform development · Web development · Database design · Payments integration
What this is based on: Full application source in the repository (Next.js, Prisma schema, 56 routes) plus the live site. Every feature listed below was read from the code, not from a brief.

Kontractz is a B2B trade marketplace connecting buyers and suppliers around trade leads, product listings and negotiated deals. It is not a brochure site with a contact form bolted on — it is a multi-role application with authenticated dashboards, a document-bearing deal workflow, real-time messaging and paid memberships.
- Project type
- Custom B2B marketplace platform
- Sector
- B2B trade / marketplace
The challenge
A trade marketplace has to serve two populations with opposite needs from the same data. Buyers want to describe a requirement once and reach qualified suppliers. Suppliers want visibility, and control over what they publish. Both then need somewhere for a negotiation to happen that is more structured than email and more auditable than a chat thread — with documents attached to the stage of the deal they belong to.
The objectives
- One platform serving buyers, sellers, startups and investors without four separate products
- Trade leads and RFQs that route to relevant suppliers rather than broadcasting
- A structured deal workflow with documents attached to stages, not to an inbox
- Paid membership tiers with real gating, billed automatically
- An admin layer able to moderate every entity on the platform
- Multi-language support from the start rather than retrofitted
Approach
Model the domain before building any interface. A marketplace lives or dies on whether its data model reflects how trade actually works — who owns a lead, what states an order moves through, what a deal room contains at each stage. Those decisions were made in the Prisma schema first, and the interfaces were built against them.
Implementation
Data model first
The schema defines the platform. Around thirty models and twenty enumerations covering:
| Domain | Models |
|---|---|
| Identity | User, Account, Session, VerificationToken, UserRole |
| Supply side | Vendor, Product, ProductInquiry |
| Demand side | Lead with typed states, RFQ flow |
| Transactions | Order, OrderEvent, OrderDoc, OrderMessage |
| Negotiation | DealRoom, DealStageData, DealParticipant, DealAction, DealStageDoc, DealMessage |
| Commercial | MembershipPlan, UserMembership, Payment |
| Capital | Startup, Investor |
| Platform | Conversation, Message, Notification, UserDocument, Setting |
The deal-room cluster is the part that makes it a trade platform rather than a directory. A deal has stages; each stage has its own data, its own documents and its own action history. That structure is what allows a negotiation to be audited afterwards, which is the thing email cannot do.
Typed enumerations rather than free-text status fields throughout — LeadStatus, OrderStatus, DealStage, VendorStatus and the rest. Status as a string is how marketplaces end up with six spellings of "pending" and reporting nobody trusts.
Application structure
Next.js App Router, with routes grouped by audience:
- Public marketplace — products, vendors, trade leads, RFQ, post-requirements, investments, plus separate explainer routes for buyers and for sellers
- Authentication — login, register, forgot-password, reset-password
- Member dashboard — leads, products, orders, inquiries, messages, deal rooms, documents, membership, notifications, profile
- Administration — members, vendors, products, orders, leads, inquiries, deal rooms, documents, investments, membership plans, messages, notifications, backup, and settings including email and Stripe configuration
Every locale-aware route sits under a locale segment, so internationalisation is structural rather than a translation layer bolted on afterwards.
Real-time and asynchronous work
Pusher carries live messaging and notifications, so a buyer sees a supplier's reply without refreshing. Email runs through Resend with Nodemailer as the transport fallback, and React Email for templating — transactional mail that renders consistently matters more on a platform where a missed notification is a missed deal.
File handling goes through UploadThing, which keeps document uploads off the application server.
Commercial layer
Stripe handles membership billing. Plans are data rather than code — MembershipPlan with UserMembership recording status — so tiers can change without a deployment. Payments are recorded as their own entity with typed status rather than being inferred from Stripe webhooks alone.
Administration
The admin surface covers every entity, not a subset. That is deliberate: a marketplace where the operator cannot moderate a listing, a lead or a deal without a developer is a marketplace that stops working the first time something needs intervening on.
Technology
- Next.js (App Router)
- TypeScript
- Prisma
- MySQL
- NextAuth
- Stripe
- Pusher
- UploadThing
- Resend
- React Email
- next-intl
- TanStack Query
- Zustand
- Radix UI
- Tailwind CSS
- Zod
Functionality
Live on kontractz.com
- Public marketplace: product listings, vendor profiles, trade leads
- Separate onboarding paths for buyers and for sellers
- Post a trade lead / post requirements
- RFQ entry point
- Startups and investors listings
- Account registration and login
- Member dashboard
Implemented in the codebase
- Deal rooms with per-stage data, documents, participants and action history
- Order lifecycle with events, documents and per-order messaging
- Product inquiries routed to vendors
- Direct conversations and messaging, with Pusher for real-time delivery
- Membership plans and subscriptions with Stripe billing
- Document vault per user
- Notification system with typed notification kinds
- Full administration panel across every entity, including email and Stripe settings
- Platform backup route in the admin area
- Multi-language routing via next-intl
Decisions worth explaining
Typed enumerations for every status field
Free-text status is how a marketplace ends up with six spellings of 'pending' and reporting nobody believes. Enumerations make invalid states unrepresentable and keep the admin filters honest.
Deal rooms modelled as staged entities rather than a chat thread
A negotiation that lives in a chat log cannot be audited. Attaching documents and actions to the stage they belong to is what makes the history usable after the fact — which is the whole reason a business would use a platform instead of email.
Membership plans stored as data, not code
Pricing and tier structure on a marketplace change more often than the software does. Plans in the database mean a commercial change is an admin action rather than a deployment.
Internationalisation designed in from the start
Retrofitting locale routing onto an application with sixty routes is substantially more work than starting with it, and trade platforms are cross-border by definition.
What it produces
A production B2B marketplace running at kontractz.com, with the public marketplace, registration and member dashboard live, and the full deal-room, order, membership and administration layer implemented in the codebase. No traffic, transaction or revenue figures are claimed here — none were supplied or measured, and the platform's commercial performance is the client's data, not mine to publish.
What it teaches
- On a marketplace, the schema is the product. Interfaces are comparatively cheap to change; a wrong data model is not.
- Separating 'live' from 'implemented' is worth doing honestly — a platform of this size always has more built than is switched on.
- Real-time messaging changes the support burden more than it changes the user experience, and that cost belongs in the plan.
What this project demonstrates
- Multi-role application architecture — four audiences served from one data model.
- Domain modelling as the first deliverable, not an implementation detail.
- Payments, real-time messaging, file handling and transactional email integrated as a working system rather than as separate features.
- An administration layer scoped to every entity, so the operator is never blocked on a developer.
Related services
Related guides
SEO
Internal Linking: A Practical SEO Guide
The most under-used lever in SEO, mostly because it is invisible and nobody sells it as a product.
SEO
How to Create an SEO-Friendly Website Structure
Structure is decided early and expensive to change. Here is how to get it right the first time.
Conversion & Growth
Why Website Visitors Are Not Turning Into Leads
Work through these in order. The first one is more common than anyone expects, and it is entirely invisible.
Conversion & Growth
How to Create a High-Converting Service Page
The structure, in order, and the two decisions that matter most: what goes first and whether you publish a price.
Worked examples
Questions about this project
If yours isn't here, send it over — I reply within one working day.
A B2B trade marketplace. Buyers post trade leads and requirements, suppliers list products and maintain vendor profiles, and negotiations run through structured deal rooms rather than email.
Next.js with the App Router and TypeScript, Prisma against MySQL, NextAuth for authentication, Stripe for membership billing, Pusher for real-time messaging, UploadThing for file handling, Resend for transactional email, and next-intl for multi-language routing.
The deal-room model. Getting stages, documents, participants and actions into a structure that is auditable afterwards, without making the interface unusable, took more iteration than any other part of the platform.

