SkillStreamsConnect
A production SaaS marketplace that connects local service seekers with verified providers through intelligent job routing, a credit-based lead economy, and end-to-end real-time coordination — from the first request to the final review.
A service marketplace built around a request, not a directory.
SkillStreamsConnect is a job-request marketplace. Seekers describe what they need through a guided wizard, the platform routes the request to the best-matched providers, and providers compete to claim the lead and quote a price range. The seeker confirms, work happens off-platform, and both sides leave structured reviews.
The model replaces three tired patterns at once — post-and-pray directory listings, the cold-call "buy any lead" economy, and the fragmented "open six tabs and compare quotes" seeker experience — with a single integrated product spanning onboarding, matching, payments, communication, dispute handling, and reputation.
Every model in the category leaks value.
- Directory sites (Yelp, Google, Thumbtack) make seekers cold-call multiple strangers with no transparent way to compare quotes.
- Lead-gen platforms sell the same lead to five-plus providers and race them to the bottom on price.
- Operators struggle to moderate disputes and set fair tier-based pricing without a structured audit trail.
Request-first, claim-based coordination.
Seekers submit a job through a 5-step wizard; the routing engine matches it to the top two providers in-area; providers spend complexity-tier credits to claim; the claimer quotes a price range; the seeker confirms; and work completes off-platform. If a provider claims but doesn't contact, or a seeker never confirms, credits auto-refund.
The result rewards providers for being responsive and quoting fairly, protects seekers from price bait-and-switch, and keeps the platform out of the service transaction itself.
Four roles, one platform.
Service seeker
Homeowners and local customers describing the work they need, comparing quoted prices, confirming a provider, and leaving structured reviews once work completes.
Service provider
Verified professionals who browse routed leads, claim the ones that fit, quote a price range, and coordinate with the seeker via in-app chat.
Admin
Platform operators running KPI dashboards, moderating users and reviews, processing refunds, tuning complexity tiers, and broadcasting targeted notifications.
Provider applicant
Prospective providers working through an application with profile, certifications, and service-area configuration before admin approval.
What the platform does.
For service seekers
- 5-step guided request wizard with category-specific dynamic questions and ZIP-code service-area validation.
- Personal dashboard — active, completed, and closed jobs with monthly spending trends and top-rated providers.
- Price-confirmation workflow — review quotes from claiming providers, then confirm, reject, or negotiate in chat.
- Real-time Socket.IO chat scoped to claimed jobs.
- Multi-dimensional reviews on completion — overall plus quality, communication, professionalism, and value.
- Refund requests with structured reason codes routed to the admin queue.
- Notification center with tabbed filtering, bulk actions, and per-channel preferences.
For service providers
- Earnings dashboard with monthly trends, success rate, completion rate, and category breakdowns via Chart.js.
- Marketplace with filters for category, location, complexity tier, and live search.
- Credit-based claim system — 1 to 5-plus credits per claim tied to an auto-computed complexity tier.
- Min/max price-range modal posted to the seeker for confirmation.
- Tabbed job views — Available, Claimed, Completed, Refunded.
- Spam reporting for low-quality leads.
- Stripe Checkout credit purchase with tiered packages.
- Provider profile with photo, bio, service areas, certifications, and verified badge.
For admins
- Real-time KPI dashboard — users, jobs, revenue, funnels, geographic distribution, heatmaps, CSV export.
- User moderation — ban, suspend, warn, adjust credits, approve applicants — all written to an immutable audit log.
- Job oversight with manual provider assignment, status overrides, and refund approvals.
- Dynamic form-question builder — eight input types, scored options, no code deploys.
- Complexity-tier and ZIP-code service-area management.
- Three-step broadcast wizard for targeted in-app and email notifications.
- Review moderation with flag, hide, and restore controls.
- Audit-log viewer with IP, reason, and before/after metadata.
For public visitors
- Marketing landing with hero CTAs, how-it-works visual, trust indicators, and FAQ.
- About, Help, Privacy, and Terms pages.
- Registration with password-strength meter and email verification.
- Password reset and cross-tab auth synchronisation.
How it holds together.
Intelligent routing engine
A custom service decides which providers receive each new job — three-tier ZIP matching (exact service area, then base ZIP, then Haversine radius), a scoring formula blending rating, completed bookings, response rate, distance, and recency, and a graceful MANUAL_FULFILLMENT_REQUIRED fallback when no providers match.
Credit economy & payment integrity
Stripe Checkout sessions fund provider credits; the webhook handler checks for an existing Transaction keyed by the Stripe session id before granting, so retries and replays cannot double-credit. An immutable ledger snapshots credit balance before and after every operation.
Dynamic form system
Job-request forms are composed at runtime from an admin-managed JobFormQuestion collection. Eight input types, weighted options, and a normalized 0-to-100 complexity score that auto-maps to a ComplexityTier — admins add categories without a code deploy.
Real-time layer
Socket.IO with a JWT-authenticated handshake, per-user rooms for direct delivery, role-based broadcast rooms, online-presence sync, unread-count sync across tabs, a 25-second keepalive, and automatic fallback from WebSocket to long-polling.
Scheduled background jobs
A 5-minute cron runs three time-based jobs — routing-expiry moves stale SENT_TO_PROVIDERS jobs to manual fulfillment; auto-completion closes CONTACTED jobs past their window and refunds credits if the seeker never confirmed; stale-claim refund returns credits when a provider claimed but never contacted. Every action writes to the admin audit log.
Modern, proven, boring-where-it-matters.
Frontend
- Next.js 15 (App Router)
- React 18
- Tailwind CSS 3.4 (custom tokens, animations)
- Headless UI (accessible modals + dropdowns)
- Chart.js + react-chartjs-2
- Socket.IO client
- Axios (centralized API layer)
- react-hot-toast
- isomorphic-dompurify (XSS sanitization)
Backend
- Node.js 18+ with Express 4
- Mongoose 7 + MongoDB
- Socket.IO 4 (JWT handshake, rooms)
- Stripe SDK (Checkout + webhooks)
- Nodemailer (SMTP pooling, HTML templates)
- Multer + Sharp (uploads + image optimization)
- Helmet, express-rate-limit, express-mongo-sanitize
- bcrypt (10 rounds)
- jsonwebtoken
- Morgan (request logging)
Infrastructure
- Ubuntu 24.04 VPS
- PM2 cluster mode (zero-downtime restarts)
- Nginx reverse proxy (SSL + WebSocket upgrade)
- MongoDB (Atlas-compatible)
- Let's Encrypt auto-renewing certificates
- TLS-only SMTP transport
The hard parts — and how they got solved.
Webhook replay safety
Stripe retries webhooks aggressively when a handler returns anything other than 2xx. A naive credit-grant on checkout.session.completed would double-credit on every retry. Every credit grant first looks up Transaction.stripeChargeId — the Stripe session id doubles as the idempotency key, with no separate key to manage.
Stripe signatures vs. JSON parsing
Signature verification needs the raw request body, but express.json() consumes the stream. Both webhook endpoints mount express.raw({ type: 'application/json' }) before the global JSON middleware, so signatures verify correctly while every other route still gets parsed JSON.
Cached vs. live provider ratings
Provider rating was originally cached on the User document and drifted out of sync after review moderation. The dashboard now recomputes ratings live via Review.aggregate() and writes the result back. The UI renders an em-dash for reviewCount === 0 — distinguishing 'no data yet' from 'bad rating'.
Modal close-animation race
The admin category edit modal briefly flashed 'Create Category' mid-fadeout because formMode flipped before the close animation completed. A dedicated formMode state, decoupled from the modal's open state, now flips only after the animation finishes.
Replacing the legacy pipeline
The first version was built on a Leads → Bookings → Services pipeline that didn't match real seeker and provider behaviour. A staged 2026 refactor unified everything into a single Job model — about 5 models, 12 routes, and 15 client directories removed with zero production downtime. Transaction enums were preserved for backward compatibility while UI labels were updated.
Fourteen core entities.
Schemas
- UserSeekers, providers, admins, applicants — profile, role, credit balance, provider metrics, moderation state.
- JobRequest lifecycle from submission through routing, claim, contact, completion, and review.
- CategoryService category with per-category question bindings and routing configuration.
- JobFormQuestionAdmin-managed dynamic form schema — eight input types with weighted options feeding complexity scoring.
- ComplexityTierMaps a normalized complexity score to a credit cost for claiming — globally or per category.
- ServiceAreaEnabled ZIP codes with coverage notes and provider counts.
- TransactionImmutable credit ledger — Stripe session id for idempotency plus before/after balance snapshots.
- ReviewOverall rating plus quality, communication, professionalism, and value sub-ratings.
- Notification30-plus event types with tabbed filtering, bulk actions, and per-channel delivery preferences.
- ConversationChat thread scoped to a claimed job between seeker and provider.
- MessageTyped chat message with read-receipt state and live Socket.IO delivery.
- RefundSeeker-initiated refund requests with reason codes routed to the admin queue.
- AuditLogImmutable record of every admin action with admin id, IP, reason, and before/after metadata.
- ApplicationProvider-applicant workflow from submission through admin approval.
Hardened by default.
The platform handles real money and real PII, so security was treated as a first-class feature — sanitization, rate limiting, webhook integrity, and audit logging in the foundation, not retrofitted.
What's included
- JWT with HS256, signed and verified server-side
- Real-time ban and suspension re-check on every authenticated request
- bcrypt password hashing (10 rounds) with complexity rules enforced at signup
- express-mongo-sanitize strips MongoDB operators from every request body
- All admin search regex inputs escaped before construction (ReDoS prevention)
- Whitelisted sort keys on admin list endpoints — user-supplied values rejected
- Rate limiting — 15 req / 15 min per IP on auth, 300 req / min global, configurable per-seeker daily inquiry cap
- Helmet defaults including HSTS, X-Frame-Options, X-Content-Type-Options
- Stripe signature verification on the raw request body, mounted before any JSON parsing
- 30-second global request timeout to mitigate slowloris-style attacks
- Multer MIME validation with Sharp re-encoding on image uploads
- isomorphic-dompurify on all user-generated content rendered to the DOM
What "production-grade" looked like.
What the team shipped.
- Production-grade marketplace live at skillstreamsconnect.com with real users and real Stripe payments.
- Custom routing engine combining ZIP-tier matching, provider scoring, and a graceful manual-fulfillment fallback.
- Credit ledger with webhook idempotency — replays and retries cannot double-credit.
- Dynamic form CMS letting admins add categories and questions without a code deploy.
- Real-time coordination layer covering chat, presence, and 30-plus notification types.
- Audit-logged admin console spanning user moderation, refunds, tiers, ZIP management, and broadcasts.
- Automated refund flows triggered by stale claims and unconfirmed prices.
Capabilities proven at production scale.
- End-to-end product ownership — discovery, design, implementation, deployment, and ops.
- Production payment integration with webhook integrity and idempotent credit granting.
- Real-time and scheduled-job architecture coexisting cleanly in a single Node process family.
- Refactor maturity — replacing an entire legacy pipeline with a unified Job model, zero production downtime.
- Pragmatic infrastructure decisions — PM2 cluster on a VPS, MongoDB for dynamic schemas, Nodemailer over a paid API.
- Security engineered in from day one — ReDoS-safe regex, sort-key whitelisting, real-time ban re-check, webhook signature verification.
- Admin tooling treated as a first-class surface rather than an afterthought.
- Design-system thinking — custom Tailwind tokens, Headless UI primitives, Chart.js visualisations tied to live data.
Shipped to production.
- Production deployment on an Ubuntu VPS with Nginx, auto-renewing TLS, and PM2 cluster supervision.
- Idempotent seed.js script provisioning categories, complexity tiers, ZIP codes, and admin users — safe to re-run.
- Scheduled cron jobs for routing expiry, auto-completion, and stale-claim refund — every action audit-logged.
- Transactional email pipeline covering verification, password reset, and notification events.
- Observability via Morgan HTTP logs and PM2 process logs.
Let's talk about your platform.
If SkillStreamsConnect looks close to what you're building — two-sided marketplace, real-time coordination, payment integration, role-based admin tooling — we'd like to hear about it.