Skip to content

Repository files navigation

ScrapFlow SA

The complete scrap metal management platform for South African scrapyards

SAPS/ITAC compliant · Real-time · Multi-site · Production-ready

ASP.NET Core 8React 18PostgreSQLTailwind CSSDockerVercelLicense: MIT


Live Demo · API Docs · Report Bug


Note

Try the live demo instantly — no sign-up needed. Use any of the test accounts below:

RoleEmailPassword
Owner(full access)owner@scrapflow.co.zaScrapFlow@2026!
Managermanager@scrapflow.co.zaScrapFlow@2026!
Scale Operatorscale@scrapflow.co.zaScrapFlow@2026!
Gradergrader@scrapflow.co.zaScrapFlow@2026!
Accountantaccounts@scrapflow.co.zaScrapFlow@2026!

Frontend: https://scrap-flow-xi.vercel.app/ | API: https://scrapflow-api.onrender.com


The Problem vs. The Solution

South African scrapyards face three existential threats from legacy pen-and-paper operations:

Pain PointBefore ScrapFlowAfter ScrapFlow
Compliance ChaosPaper registers fail SAPS audits → fines & license revocationCompliance baked into code — ticket cannot complete without EFT ref + ID photos
Operational BlindnessNo real-time tonnage or profit visibilityLive dashboard with inventory value, revenue, and ticket stats
Cash Ban BurdenManual EFT tracking is error-prone and un-auditableIntegrated payment workflow with verified references and 5-year audit trail

The South African Second-Hand Goods Act and the 2024/2025 Metal Cash Ban require strict digital record-keeping. ScrapFlow acts as a Digital Auditor — hard-blocking non-compliant actions at the service layer.


Features

CategoryFeatureDetail
ComplianceCash-ban enforcementBlocks ticket completion without a verified EFT reference
ComplianceMandatory photo capture3 required photos: Seller ID, Load, Proof-of-Payment
Compliance5-year audit trailRolling registers stored per SAPS/ITAC requirements
Operations6-step inbound ticketArrive → Gross Weigh → Grade → Tare → Pay → Complete
OperationsOutbound ticketsFull customer invoice workflow with lot selection
InventoryReal-time lot trackingAutomatic lot creation on ticket completion
InventoryAdjust & write-offManager-approved lot adjustments with reason logging
Real-timeSignalR inventory hubLive updates pushed to all connected clients instantly
AutomationWebhook systemFires on ticket/inventory events → Zapier, n8n, Make
UXOffline-first PWAIndexedDB drafts survive connectivity loss
UXWeighbridge integrationWeb Serial API direct industrial scale communication
Admin5-role RBACOwner / Manager / ScaleOp / Grader / Accountant
AdminMulti-site supportManage multiple scrapyards from one account
ReportsRevenue & tonnage reportsFilterable by site, date range, and material grade

Tech Stack

BackendFrontend
ASP.NET Core 8 (Clean Architecture)React 18 (JSX + Vite)
Entity Framework Core 8Tailwind CSS + Glassmorphism UI
PostgreSQL (Supabase)Zustand state management
SignalR (real-time hubs)@microsoft/signalr client
JWT authentication (12h tokens)Axios + React Query patterns
HMAC-SHA256 webhook signingWeb Serial API (weighbridge)
Serilog structured loggingIndexedDB offline drafts
Docker + docker-composeDeployed on Vercel

Architecture

graph TD
Client["React Client\n(Vercel)"]
API["ScrapFlow.API\n(Render)"]
APP["ScrapFlow.Application\nDTOs · Interfaces · Services"]
DOMAIN["ScrapFlow.Domain\nEntities · Enums · Business Rules"]
INFRA["ScrapFlow.Infrastructure\nEF Core · Migrations · Services"]
DB[("PostgreSQL\n(Supabase)")]
SIG["SignalR Hubs\nInventory · Tickets"]
HOOK["Webhook Service\nHMAC-SHA256 signing"]
N8N["n8n / Zapier\nAutomation workflows"]
Client -- "REST + SignalR" --> API
API --> APP
APP --> DOMAIN
INFRA --> APP
INFRA --> DOMAIN
INFRA --> DB
API --> SIG
API --> HOOK
HOOK -- "HTTP POST" --> N8N
Loading

Deployment

LayerPlatformNotes
FrontendVercelAuto-deploys on push to main
Backend APIRenderDockerized ASP.NET Core 8
DatabaseSupabaseManaged PostgreSQL
Automationn8n (Docker) + Zapier4 pre-built workflow templates

Engineering Challenges & Solves

1. Circular Dependency in Clean Architecture

Problem: During the Application/Infrastructure split, services needed DbContext but DbContext needed service logic — a circular reference. Solution: Moved TicketService into the Infrastructure layer, implementing interfaces defined in Application. Maintained Clean Architecture principles while resolving the cyclic reference.

2. Dependency Injection & Service Scoping

Problem: Standalone services threw runtime errors due to missing ILogger implementations and improper DI registrations. Solution: Standardized all DI registrations in Program.cs using generic ILogger<T>. In unit tests, used Moq to provide verified mock loggers — isolating business logic from external providers.

3. In-Memory Database Versioning

Problem: The xUnit test suite failed because InMemoryDatabase v10 was incompatible with the .NET 8 target. Solution: Manual downgrade to Microsoft.EntityFrameworkCore.InMemory v8.0.0, aligning test infrastructure with the core runtime.

4. Non-Blocking Webhook Dispatch

Problem: Firing webhooks synchronously would add latency to every ticket completion HTTP response. Solution: Implemented fire-and-forget using _ = Task.Run(() => _webhookService.FireAsync(...)) — the HTTP response returns immediately while the webhook dispatches in the background. HMAC-SHA256 signature header ensures receiver authenticity.


What I Learnt

  1. Industry-Specific Architecture — Translating legal requirements (SAPS/ITAC) into strict software guards and validation logic at the service layer.
  2. Browser-Hardware Interfacing — Using the Web Serial API to bridge industrial weighbridge hardware and modern web browsers without drivers.
  3. Offline-First Resilience — PWA strategies with Service Workers + IndexedDB to handle South African connectivity instability.
  4. Clean Architecture Discipline — Maintaining strict separation of concerns even when complex infrastructure dependencies arise in real-world projects.
  5. Real-time Systems — Building SignalR hubs with group-based broadcasting (per-site) and stable client reconnection handling.

Getting Started (Local Dev)

Prerequisites

  • .NET 8 SDK
  • Node.js 18+
  • Docker Desktop

1. Clone & configure

git clone https://github.com/dev-k99/ScrapFlow.git
cd ScrapFlow
cp src/ScrapFlow.API/appsettings.example.json src/ScrapFlow.API/appsettings.json
# Edit appsettings.json — add your PostgreSQL connection string and JWT secret

2. Docker quick start

docker compose up --build
# API: http://localhost:5010# n8n: http://localhost:5678

3. Or run individually

# Backendcd src/ScrapFlow.API && dotnet run
# Frontendcd scrapflow-client && npm install && npm run dev
# → http://localhost:5173

4. Seed data

On first run, the API automatically seeds:

  • 5 user accounts (Owner, Manager, ScaleOp, Grader, Accountant)
  • 2 sites (Germiston Main Yard, Durban North Depot)
  • 20 material grades (ferrous + non-ferrous) with realistic ZAR prices
  • 10 suppliers + 3 customers + 5 sample completed tickets

API Reference

ResourceMethodEndpointAuth
AuthPOST/api/auth/loginPublic
AuthPOST/api/auth/registerPublic
DashboardGET/api/dashboard?siteId=Any role
Inbound TicketsPOST/api/tickets/inboundScaleOp+
Inbound TicketsPUT/api/tickets/inbound/{id}/gross-weightScaleOp+
Inbound TicketsPUT/api/tickets/inbound/{id}/gradingGrader+
Inbound TicketsPUT/api/tickets/inbound/{id}/paymentAccountant+
Inbound TicketsPUT/api/tickets/inbound/{id}/completeManager+
Outbound TicketsGET/POST/api/tickets/outboundScaleOp+
InventoryGET/api/inventory?siteId=&status=Any role
InventoryPUT/api/inventory/{id}/adjustManager+
InventoryPUT/api/inventory/{id}/write-offManager+
MaterialsGET/api/materialsAny role
SuppliersGET/POST/api/suppliersScaleOp+
CustomersGET/POST/api/customersScaleOp+
ReportsGET/api/reportsManager+
WebhooksGET/POST/DELETE/api/webhooksOwner only
SitesGET/POST/api/sitesOwner (POST)
Audit LogGET/api/auditlogsManager+
HealthGET/healthPublic

Designed & Engineered for South African Scrapyards

Built by Kwanele Ntshangase · Live Demo · View Source

About

Full-stack scrap metal management system for South African scrapyards. SAPS/ITAC compliant · 6-step digital ticket workflow · Real-time SignalR inventory · 5-role RBAC · Webhook automation · Offline PWA. Built with ASP.NET Core 8, React 18, PostgreSQL.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages