Why Washly
What makes it better
than the alternatives
- 01
Single-tenant architecture
One installation serves one laundry business with full data isolation and no multi-tenancy overhead
- 02
Ownership guards on every API endpoint
Customers and drivers can only read and change their own records, enforced by ApiOwnershipFilter
- 03
Role/page permission matrix
39 Admin pages with granular read/save/update/delete rights per staff role, checked by AdminPageAccessFilter
- 04
Hosted payment pages with Apple Pay
Mastercard Payment Gateway Services integration, signed payment tickets (JWT, 30 min), saved cards and wallet top-up
- 05
Comprehensive audit trail
Every foreign key has an index, cascade deletes only for owned rows, soft deletes for business data, no dynamic SQL
Customer App (Flutter)
- Sign in with OTP by SMS or email (no password)
- Service catalogue: wash & fold
- clean & press
- dry cleaning
- home care
- shoes & bags with per-item prices
- Order with collection/delivery time slots
- address book with map pin
- driver instructions
- Promo codes
- coupons with wallet cashback
- wallet balance and top-up
- Card payment and Apple Pay through hosted payment page
- Live order status
- proof-of-collection and proof-of-delivery photos
- invoices (PDF)
- Push notifications (Firebase)
- support tickets
- FAQ
Driver App (Flutter)
- Jobs for today: collections and deliveries assigned to the driver
- Status updates (collected
- delivered
- attempt failed with reason)
- Proof photos with bag
- hanger and package counts
- Navigation to customer's address (Google Maps)
- Push notifications for new assignments
Admin Panel (ASP.NET Core MVC)
- Dashboard with order and customer statistics (stored procedure DashBoardStatistics)
- Orders: list
- search
- edit
- invoice (PDF)
- receipt
- assign drivers
- bulk item upload from Excel
- Service catalogue: categories
- groups
- items
- bags
- promo codes
- coupons
- Drivers: list
- create
- schedule
- performance reports
- Customers: list
- details
- transaction history
- wallet top-up
- Corporate accounts (Businesses): employees
- orders
- invoices
- Areas
- delivery charges
- time slots
- unavailable days
- Staff users with role-based page access (39 pages
- read/save/update/delete per role)
- Reports: revenue
- sales
- customer
- driver
- payment (Excel export with ClosedXML)
- Push notifications to customers and drivers
- Settings: onboarding screens
- terms & conditions
- FAQ
- landing page HTML
REST API (62 endpoints)
- Public: catalogue (areas
- bags
- items
- service categories
- time slots)
- onboarding screens
- FAQ
- Sign-in: OTP request and verify (SMS/email)
- JWT token issue (30 days)
- Orders: place
- list
- details
- cancel
- rate
- proof photos
- Payments: saved cards
- Apple Pay
- wallet top-up
- hosted payment page ticket issue
- User: profile
- address book
- wallet balance
- transactions
- Driver: assigned jobs
- status update
- proof upload
- schedule
- Business employee: login
- items
- place order
- Ownership guards: every userId
- customerId
- driverId
- orderId checked against caller's identity
Payment Integration
- Mastercard Payment Gateway Services (API v71
- Apple Pay v100)
- Hosted payment pages with signed tickets (JWT
- 30 min
- one user)
- Saved cards (tokenization
- last 4 digits
- brand
- expiry)
- Apple Pay (merchant id in 3 files: Info.plist
- Runner.entitlements
- apple_pay_config.json)
- Wallet top-up and cashback from coupons
- Refunds (PaymentGateWayService.RefundsAndCards.cs)
- Payment reports with Excel export
Database (SQL Server)
- 62 tables
- 38 foreign keys
- 151 indexes (62 primary + 89 others)
- Every foreign key column has an index (verified by query in database/README.md)
- Cascade deletes only for owned rows (order logs
- payments
- proof photos
- time slots
- role permissions)
- Soft deletes for business data (Status = 2)
- no hard deletes
- 10 stored procedures for reports and lists (DashBoardStatistics
- GetOrdersByFilter
- GetRevenueReport
- GetSalesReport
- GetUsers
- SearchCustomers
- etc.)
- No dynamic SQL: EF Core LINQ for single-entity work
- Dapper with named parameters for lists
- ORDER BY from fixed dictionary (SqlSort.cs)
- PBKDF2 password hashes with check constraint (CK_Users_Password_IsHash)
- One EF Core migration (InitialCreate)
- schema.sql matches it
Security & Access Control
- Admin panel: cookie sign-in (staff roles only)
- 8-hour session with sliding expiration
- Mobile API: JWT bearer tokens (30 days)
- issued after OTP verification
- OTP: 4 digits
- 5 minutes expiry
- 5 max attempts
- demo codes for testing
- Roles: Super Admin
- Admin
- Driver
- Customer
- Business Employee (AppRoles.cs)
- AdminPageAccessFilter: 39 pages with read/save/update/delete rights per role
- ApiOwnershipFilter: customers and drivers can only access their own records (userId
- orderId checked)
- OwnershipGuard: service methods verify caller's identity before data access
- Rate limiting: 10 sign-in attempts per minute per client address
- PBKDF2 password hashing (PasswordService.cs)
- app users sign in by OTP and have NULL password
Notifications & Communication
- Firebase Cloud Messaging for push notifications (customer and driver apps)
- SMS gateway integration (configurable
- disabled by default
- Sms:Enabled in appsettings)
- Email (SMTP
- configurable
- Smtp:Enabled
- templates in Areas/Admin/Views/Email/)
- Push notification screens in admin panel (CustomerPushNotification
- DriverPushNotification)
- Order status change notifications (OrderService.cs)
- Support tickets (UserReportsAndHelp)
Reports & Analytics
- Dashboard statistics: orders
- customers
- revenue (stored procedure DashBoardStatistics)
- Revenue report: date range
- area
- service category
- Excel export (GetRevenueReport)
- Sales report: date range
- customer
- driver
- Excel export (GetSalesReport)
- Customer report: orders
- spending
- last order date (GetUsers)
- Driver report: collections
- deliveries
- performance
- Payment report: transactions
- gateway
- wallet
- Excel export
- Order report: combined report with filters (OrderReport/Index.cshtml)
- Excel export with ClosedXML (ClosedXML 0.105.1)
Configuration & Deployment
- Docker Compose: web (ASP.NET Core)
- db (SQL Server 2019)
- init-db.sh runs schema.sql and seed.sql
- Environment variables: JWT key
- MSSQL password
- site URL
- OTP log codes (.env.example)
- appsettings.json: JWT
- OTP
- SMS
- SMTP
- payment gateway
- branding
- CORS
- Flutter build-time config: API_BASE_URL
- GOOGLE_MAPS_API_KEY
- SUPPORT_WHATSAPP
- SUPPORT_EMAIL (--dart-define)
- Firebase setup: google-services.json (Android)
- GoogleService-Info.plist (iOS) for both apps
- Release signing: key.properties (Android)
- Xcode team (iOS)
- Launcher icons: flutter_launcher_icons.yaml
- source images in assets/
| Language | Version | Framework | Used for | Share of code |
|---|---|---|---|---|
| JavaScript | — | — | Front-end | 38.6% |
| CSS | — | — | Styling | 28.2% |
| C# | — | — | Web, API, admin | 11.6% |
| Dart | — | — | Mobile app | 10.4% |
| C# (Razor) | — | — | Web pages | 5.9% |
| SCSS | — | — | Styling | 3.2% |
| SQL | — | — | Database | 1.5% |
| HTML | — | — | Front-end | 0.5% |
| Java | — | — | API | 0.1% |
| Swift | — | — | Mobile app | 0.1% |
| Shell | — | — | Scripts | 0% |
- Primary language
- C# 10 / Dart 3.13
- Framework
- ASP.NET Core 10 / Flutter 3.47
- Database
- SQL Server 2019
- Authentication
- JWT bearer (mobile), cookie (admin), OTP sign-in
- Licence
- Single-site
- Screens
- 85
- Database tables
- 62
- Supported languages
- English only
- Browser support
- Modern browsers (Chrome, Firefox, Safari, Edge)
| Minimum | Recommended | |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 4 GB RAM / 20 GB disk | 8 GB RAM / 40 GB disk |
| OS | Linux/Windows with .NET 10 SDK, SQL Server 2019+ | Linux/Windows with .NET 10 SDK, SQL Server 2019+ |
| Est. monthly hosting | $50 | $50 |
```bash cp .env.example .env # Edit .env: set MSSQL_SA_PASSWORD (8+ chars, mixed case, digit, special) and JWT_KEY (32+ chars) docker compose up -d --build # Site: http://localhost:8080 # Default admin: admin@washly.com / Admin@123 ```
```bash sudo apt update && sudo apt install -y dotnet-sdk-10.0 mssql-server sudo /opt/mssql/bin/mssql-conf setup # Choose edition, set SA password sqlcmd -S localhost -U sa -P '<password>' -C -i database/schema.sql sqlcmd -S localhost -U sa -P '<password>' -C -d Washly_db -i database/seed.sql cd "NET Project/DRYX-web" dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=Washly_db;User Id=sa;Password=<password>;TrustServerCertificate=True" dotnet user-secrets set "Jwt:Key" "<random-32-char-key>" dotnet publish -c Release -o /var/www/washly sudo systemctl enable --now washly # Configure nginx reverse proxy to port 5000 ```
```bash # Install .NET 10 SDK and SQL Server 2019+ on your machine cp .env.example .env # Edit .env: set MSSQL_SA_PASSWORD and JWT_KEY sqlcmd -S localhost -U sa -P '<password>' -C -i database/schema.sql sqlcmd -S localhost -U sa -P '<password>' -C -d Washly_db -i database/seed.sql cd "NET Project/DRYX-web" dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=Washly_db;User Id=sa;Password=<password>;TrustServerCertificate=True" dotnet user-secrets set "Jwt:Key" "<random-32-char-key>" dotnet run # Site: http://localhost:5208 # Admin: admin@washly.com / Admin@123 ```
Quality report
Manually reviewedHow to read the quality report
What this is. Every project on Vibe96 goes through an automated audit of its source code before a reviewer in Dubai checks it by hand. The score is out of 100; 75 is the minimum to be listed, and any single failing check blocks a listing regardless of the score.
- Security
- No real credentials in the code, every data-changing route protected, admin areas role-gated, no SQL built from user input.
- Code structure
- A developer can navigate and extend it: clear module boundaries, no giant files, little copy-paste.
- Docs & completeness
- The setup guide, example config, schema and required files the builder committed to are actually in the archive.
- Dependency health
- Packages pinned, no known critical vulnerabilities, no abandoned libraries in production paths.
- Build & deploy
- A clean machine can restore, build and start it by following the shipped instructions.
Warnings are problems that didn't block the listing; they stay visible here until a later version clears them. The audit reads the code — it does not run it — so always try the live demo before you buy. Lines of code are counted from the same audited archive.
90/ 100
Automated audit score
The automated audit flagged a blocking check · 4 open warnings — listed after a manual review
◷ 4 open warningsWhat to know before you buy
4 non-blocking findings shown publicly: . The seller has been notified; fixes ship in the next version.
Versions & updates
No updates yet. New versions appear here with a changelog.
Buyers receive updates free for 1 year.
What you get
- </>Full source codeThe complete audited source, delivered as a download from your account. No obfuscation.
- ▤DocumentationSetup guide, architecture notes, CLAUDE.md and AGENTS.md.
- ↻One year of updatesEvery new version the builder publishes, free for 12 months.
- ♧30 days of supportInstallation and defect support through Vibe96 tickets.