About this software
About Swapio
Swapio is a production-ready classifieds marketplace combining a public website, admin panel, REST API, and Flutter mobile apps (Android/iOS) in one package. It handles motors, property, electronics, wholesale, jobs and general goods with category-specific forms, swap requests, in-app chat, push notifications and paid ad boosts. The ASP.NET Core 10 backend uses Entity Framework 6 with SQL Server, role-based access on every endpoint, salted PBKDF2 password hashing, and pluggable payments (Demo mode and Stripe). Includes Docker Compose setup, demo seed data, English and Arabic UI, and exact dependency versions for reproducible builds.
Why Swapio
What makes it better
than the alternatives
- 01
Category-specific ad forms
Separate input fields for motors (make, model, year, doors, transmission), property (bedrooms, bathrooms, area, furnishing), electronics, wholesale, jobs and general items, all driven by database attributes
- 02
Swap requests
Members can offer one of their own ads in exchange for another, creating a barter flow alongside cash sales
- 03
Job marketplace
Company profiles, job posts by recruiters, candidate profiles, applications, and an accept/reject workflow with payment on hire
- 04
Three admin roles
SuperAdmin (full access), Admin (approvals and moderation), Operation (view-only reports), each enforced by [Authorize(Roles = ...)] on every controller
- 05
No default secrets
JWT_KEY, database passwords and the first admin password must be supplied in .env; startup fails otherwise, preventing accidental deployment with placeholder credentials
Public Website (ASP.NET Core MVC)
- Home page with category tiles
- featured ads
- city selector and search bar
Areas/Website/Views/Home/Index.cshtml - Ad browsing by category
- sub-category
- city
- price range and category-specific filters
Areas/Website/Controllers/PostController.csCategoryMotor action) - Ad detail pages for motors
- property
- electronics
- wholesale
- jobs and general items
- each with category-specific fields
Areas/Website/Views/Post/MotorProductDetails.cshtmland 5 others) - Member sign-up
- sign-in
- profile edit
- password reset
Areas/Website/Controllers/AuthController.cs - MemberAuth.SignInAsync)
- Post ad forms with photo/video upload
- category selection
- then category-specific inputs
Areas/Website/Views/Post/PostAdMotor.cshtmland 5 others) - My Ads page with tabs for Active
- Pending
- Rejected
- Expired
Areas/Website/Views/Post/MyProfile.cshtml - Favourites list
- chat inbox
- notifications
Areas/Website/Controllers/PostController.csMyFavourite - ChatList
- Notification actions)
- Swap request flow: offer one of your ads for another
Areas/Website/Controllers/PostController.csSwapRequest action) - Job pages: company profile
- job post
- candidate profile
- apply
Areas/Website/Views/Post/JobRecuterDetails.cshtml - JobCandicateDetails.cshtml)
- Terms
- privacy
- support contact pages
Areas/Website/Views/Post/TermsCondition.cshtml - PrivacyPolicy.cshtml
- Support.cshtml)
- English and Arabic UI with right-to-left layout
wwwroot/Areas/Website/src/css/swapio.css - .rtl rules)
Admin Panel (ASP.NET Core MVC)
- Dashboard with sales chart
- order chart
- total ads
- total members
- pending ads
- pending jobs
Areas/Admin/Views/Dashboard/Index.cshtml - DashboardController.cs)
- Ad management: approve
- reject
- delete
- view details
Areas/Admin/Controllers/PostController.cs Views/Post/Index.cshtmlwith DataTables)- Member management: list
- view profile
- activate
- deactivate
Areas/Admin/Controllers/MemberController.cs Views/Member/Index.cshtml- Category management: add
- edit
- delete categories and sub-categories
Areas/Admin/Controllers/CategoryController.cs Views/Category/Index.cshtml- Attribute management: define category-specific fields (make
- model
- bedrooms
- etc.) with type (text
- dropdown
- checkbox)
Areas/Admin/Controllers/AttributeController.cs - City and country management
Areas/Admin/Controllers/CityController.cs - CountryController.cs)
- Banner management: upload images
- set category
- order
Areas/Admin/Controllers/BannerController.cs - Boost plan management: create plans with price
- duration
- top position
Areas/Admin/Controllers/BoostPlanController.cs - Job post approval: approve or reject company profiles and job posts
Areas/Admin/Controllers/JobController.cs - Candidate approval: approve or reject candidate profiles
Areas/Admin/Controllers/CandidateController.cs - Push notification sender: compose and send to all members
Areas/Admin/Controllers/NotificationController.csSendNotification action) - Feedback inbox: read messages from the support form
Areas/Admin/Controllers/FeedbackController.cs - Reports: ad report with Excel/PDF export
- job report
Areas/Admin/Controllers/ReportController.csPostReport - JobReport actions)
- User management: add
- edit
- delete admin panel users with role selection
Areas/Admin/Controllers/UserController.cs - Terms and privacy editor: update the public pages
Areas/Admin/Controllers/TermsConditionController.cs - PrivacyPolicyController.cs)
- Three roles enforced: SuperAdmin (all actions)
- Admin (approvals
- moderation
- reports)
- Operation (view-only reports)
Infrastructure/Auth.csAuthRoles - [Authorize(Roles = ...)] on each controller)
Mobile App (Flutter 3.35, Android/iOS)
- Home screen with category grid
- featured ads
- search bar
- city selector
lib/ui/fragment/home/HomePage.dart - Category browsing with filters: price
- city
- sub-category
- category-specific attributes
lib/ui/activity/categoriy/CategoryMotor.dart filter/FilterPage.dart- Ad detail screens for motors
- property
- electronics
- wholesale
- jobs
- general
lib/ui/activity/productItemDetails/motor/MotorProductDetailsPage.dartand 5 others) - Post ad flow: select category
- fill category-specific form
- upload photos/video
lib/ui/activity/post_ad/motor/PostAdMotorPage.dartand 5 others) - Edit ad flow: same category-specific forms pre-filled
lib/ui/activity/post_ad/update/motor/PostAdMotorUpdatePage.dartand 5 others) - My Ads with tabs: Active
- Pending
- Rejected
- Expired
lib/ui/activity/my_listing/my_listing.dart - tab_item.dart)
- Favourites list
lib/ui/activity/wish_list/wish_list.dart - Chat: conversation list and message screen
lib/ui/activity/chat_message/ChatMessagePage.dart - Swap request: offer one of your ads for another
lib/ui/activity/swap_request/SwapRequestPage.dart - Job flow: post job
- view applications
- accept candidate with payment
lib/ui/activity/job_accept/JobAccept.dart - JobAcceptCandidateDetails.dart)
- Job apply: candidate fills profile
- uploads CV
- applies
lib/ui/activity/job_apply/job_apply_page.dart - Profile edit
- change password
- delete account
lib/ui/activity/edit_profile/edit_profile.dart - Block list
- report ad
- support contact
lib/ui/activity/block_list/block_list_view.dart lib/ui/activity/support/SupportPage.dart- Push notifications via Firebase
lib/core/services/firebase_service.dart - English and Arabic with RTL layout
lib/l10n/app_en.arb - app_ar.arb
- flutter gen-l10n)
- Google Maps location picker
lib/utils/google_places_picker.dart - requires GOOGLE_MAPS_API_KEY at build time)
- One configurable server URL
lib/constant/AppConfig.dart - set with --dart-define=SERVER_URL=... at build time)
REST API (ASP.NET Core, /api/v1/)
- Member registration
- login
- OTP verification
- password reset
Controllers/MemberController.csRegistration - Login
- VerifyOTP
- ForgotPassword actions)
- JWT bearer token authentication for mobile app
Infrastructure/JwtKeyProvider.cs - Program.cs AddAuthentication JwtBearer)
- Ad CRUD: create
- update
- delete
- list by category
- search
Controllers/AddPostController.csAddPost - UpdatePost
- DeletePost
- GetPostByCategory
- SearchPost actions)
- Ad media upload: photos
- video
- documents
Controllers/PostMediaController.csUploadPostMedia action - saves to
wwwroot/uploads/ - Favourites: add
- remove
- list
Controllers/AddPostController.csAddFavourite - RemoveFavourite
- GetFavourite actions)
- Chat: send message
- get conversation list
- get messages
Controllers/ConversationController.csSendMessage - GetConversationList
- GetMessages actions)
- Swap requests: create
- accept
- reject
Controllers/AddPostController.csSwapRequest - AcceptSwapRequest
- RejectSwapRequest actions)
- Job posts: create
- update
- list
Controllers/AddPostController.csAddJobPost - UpdateJobPost
- GetJobPosts actions)
- Job applications: apply
- list applications
- accept/reject
Controllers/AddPostController.csApplyJob - GetJobApplications
- AcceptJobApplication actions)
- Boost ad: purchase boost plan
- apply to ad
Controllers/PaymentsController.csPurchaseBoost action - calls IPaymentGateway.CreatePaymentIntent)
- Report ad
- block member
Controllers/PostModerationController.csReportPost - BlockMember actions)
- Push notifications: register device token
- send notification
Controllers/NotificationController.csRegisterDevice - SendNotification actions)
- Master data: categories
- sub-categories
- attributes
- cities
- countries
- boost plans
Controllers/MasterDataController.csGetCategories - GetCities
- GetBoostPlans
- etc.)
- Rate limiting on auth endpoints (5 requests per minute per IP
Infrastructure/AuthSetup.cs- [EnableRateLimiting(AuthPolicies.AuthRateLimit)])
- Rate limiting on public ad browsing (30 requests per minute per IP
- [EnableRateLimiting(AuthPolicies.PublicApiRateLimit)])
- Every endpoint requires [Authorize(Policy = AuthPolicies.Member)] unless [AllowAnonymous]
Controllers/BaseController.cs - SECURITY.md lists every route)
Authentication & Authorization
- Admin panel: cookie authentication (scheme AuthSchemes.Admin
- 12-hour lifetime
Infrastructure/AdminAuth.cs- Website members: cookie authentication (scheme AuthSchemes.Member
- 30-day lifetime
Infrastructure/MemberAuth.cs- Mobile app: JWT bearer tokens (HS256
- 30-day expiry
Infrastructure/JwtKeyProvider.cs- secret from JWT_KEY env var)
- Passwords: salted PBKDF2-HMAC-SHA256
- 210
- 000 iterations
Helpers/PasswordHasher.csHashPassword - VerifyPassword)
- No default admin password: ADMIN_INITIAL_PASSWORD env var required
- startup fails if missing
Infrastructure/AdminBootstrap.cs - No default JWT key: JWT_KEY env var required
- startup fails if missing
Infrastructure/JwtKeyProvider.cs - Three admin roles: SuperAdmin (all actions)
- Admin (approvals
- moderation)
- Operation (view-only reports)
Infrastructure/Auth.csAuthRoles) - Role enforcement: [Authorize(Roles = AuthRoles.SuperAdmin)] on settings controllers
- [Authorize(Roles = AuthRoles.Managers)] on approval controllers
Areas/Admin/Controllers/ - Member ownership checks: every update/delete loads the row by key after checking CurrentMemberId == row.MemberId
Infrastructure/Ownership.cs DataService/methods)- Soft deletes: members
- ads
- admin users set Status = Deleted
- never hard-deleted
DataService/MemberService.csDeleteMember DataService/Admin/PostService.csDeletePost)- CSRF protection: SameSiteRequestsAttribute on every admin controller
- rejects requests with Origin/Referer from other sites
Infrastructure/SameSiteRequestsAttribute.cs - Rate limiting: 5 req/min on login/registration
- 10 req/min on report/block
- 30 req/min on public ad browsing (Program.cs AddRateLimiter
- [EnableRateLimiting(...)])
Payments (Pluggable Gateway)
- IPaymentGateway interface: CreatePaymentIntent
- ConfirmPayment
- RefundPayment
Services/Payments/IPaymentGateway.cs - Demo provider: approves every payment without charging
- for trials
Services/Payments/DemoPaymentGateway.cs - default in appsettings.json Payments:Provider=Demo)
- Stripe provider: creates PaymentIntent
- confirms
- refunds
Services/Payments/StripePaymentGateway.cs - requires Stripe:SecretKey and Stripe:PublishableKey in appsettings.json)
- Boost purchase flow: select plan
- call /
api/v1/Payments/PurchaseBoost - get client_secret
- confirm in app
Controllers/PaymentsController.csPurchaseBoost action) - Job hire payment: accept candidate
- call /
api/v1/Payments/AcceptJobApplication - get client_secret
- confirm
Controllers/AddPostController.csAcceptJobApplication action) - Payment records: Payments table with MemberId
- Amount
- Currency
- Status
- PaymentIntentId
Models/Payment.cs DataService/PaymentService.cs- No payment keys in source: Stripe keys come from appsettings.json or env vars
- never committed (appsettings.example.json shows placeholders)
Database (SQL Server, Entity Framework 6)
- 33 tables: Members
- Posts
- Categories
- SubCategories
- Attributes
- Cities
- Countries
- Conversations
- Messages
- Favourites
- SwapRequests
- JobPosts
- JobApplications
- Payments
- Notifications
- Banners
- BoostPlans
- PostReports
- BlockedMembers
- Users
- Feedbacks
- TermsConditions
- PrivacyPolicies
- etc.
database/schema.sql - Primary keys on every table
- 38 indexes on foreign-key and lookup columns
database/schema.sqlsummary at top) - Entity Framework 6 LINQ queries only
- no raw SQL (grep -rnE 'SqlCommand|ExecuteSqlCommand|SqlQuery|FromSql|CommandText' returns nothing
- CLAUDE.md)
Contexts/SwapioContext.cs: DbContext with DbSet for each table- OnModelCreating configures relationships
DataService/layer: one service class per concern (MemberService- PostService
- CategoryService
- etc.)
- all methods return models or lists
- Migrations:
database/schema.sqlcreates the schema database/seed.sqlloads demo data (21 ads- 3 members
- 5 categories
- 10 cities)
- Docker init:
database/init.shruns schema.sql and seed.sql (if SEED_DEMO_DATA=true) on first start (docker-compose.yml db service) - Connection string: from appsettings.json ConnectionStrings:DefaultConnection or env var CONNECTION_STRING
- uses swapio_app login with APP_DB_PASSWORD (docker-compose.yml
- HowToSetup.md)
Integrations & Services
- Google Maps: location picker in mobile app
lib/utils/google_places_picker.dart - requires GOOGLE_MAPS_API_KEY at build time)
- map view on ad details (Flutter
APP/README.md - Firebase Cloud Messaging: push notifications to mobile app
Services/FirebaseService.csSendNotification lib/core/services/firebase_service.dart- requires FIREBASE_PROJECT_ID and
google-services.json/GoogleService-Info.plist - SMTP email: registration confirmation
- password reset
Services/EmailService.csSendRegistrationResponse - SendPasswordReset
- requires SMTP_HOST
- SMTP_PORT
- SMTP_USERNAME
- SMTP_PASSWORD in appsettings.json)
- SMS OTP: phone verification
Services/SmsService.csSendOTP - requires SMS_API_URL and SMS_AUTH_TOKEN in appsettings.json)
- Stripe: payment processing
Services/Payments/StripePaymentGateway.cs - requires Stripe:SecretKey and Stripe:PublishableKey)
- File uploads: photos
- video
- documents saved to
wwwroot/uploads/with unique filenamesControllers/PostMediaController.csUploadPostMedia - 500 MB limit in web.config and Program.cs)
- No keys in source: all API keys
- SMTP credentials
- Firebase config come from appsettings.json or env vars
- never committed (appsettings.example.json
- .env.example
- Flutter
APP/README.md
Deployment & DevOps
- Docker Compose: one-command setup with SQL Server
- ASP.NET Core app
- automatic database init (docker-compose.yml
- HowToSetup.md)
- Dockerfile: multi-stage build
- .NET SDK 10.0
- runs on port 8080 (NET
Project/IraqShopping/Dockerfile - Environment variables: .env.example lists all required and optional settings
- .env holds real secrets (never committed)
- Reproducible builds: packages.lock.json (NuGet)
- pubspec.lock (Flutter)
- global.json (.NET SDK 10.0.101) pin exact versions (NET
Project/IraqShopping/packages.lock.json - Flutter
APP/pubspec.lock - NET
Project/global.json - No vulnerable packages: dotnet list package --vulnerable --include-transitive returns clean (CHANGELOG.md 2025-01-15 entry)
- Health check: /health endpoint returns 200 OK (Program.cs app.MapHealthChecks)
- Logging: Serilog to console and file
- structured JSON (Program.cs UseSerilog
- appsettings.json Serilog section)
- IIS deployment: web.config with aspNetCore handler
- 500 MB upload limit
- .apk and .webp MIME types (NET
Project/IraqShopping/web.config - Server install without Docker: HowToSetup.md section 2 lists SQL Server 2019+
- .NET SDK 10.0
- IIS setup steps
Localization & Branding
- English and Arabic UI throughout: website
- admin panel
- mobile app
wwwroot/Areas/Website/src/css/swapio.css.rtl rules - Flutter
APP/lib/l10n/app_en.arb - app_ar.arb)
- Right-to-left layout: CSS .rtl class on body
- Flutter Directionality widget
wwwroot/Areas/Website/src/css/swapio.css lib/ui/widget/swapio/auth_scaffold.dart- Brand colors: primary #087FF5
- secondary #FF6B35
- success #10B981
- warning #F59E0B
- danger #EF4444
docs/BRANDING.md wwwroot/Areas/Admin/Content/css/swapio-admin.cssCSS variables)- Fonts: Poppins (headings)
- Inter (UI)
- Cairo (Arabic)
Areas/Admin/Views/Shared/_LayoutAuth.cshtml Areas/Website/Views/Shared/_Layout.cshtml- Logos: SVG and PNG in
docs/logos/ - favicon and app icons in
wwwroot/Areas/Admin/Content/assets/images/brand/and FlutterAPP/icons/docs/BRANDING.md - App icons: generated with flutter_launcher_icons from
icons/icon.png(FlutterAPP/flutter_launcher_icons.yaml - Flutter
APP/README.mdsection 7) - Customization guide:
docs/BRANDING.mdlists every color variable - font
- logo file and how to regenerate icons
| Language | Version | Framework | Used for | Share of code |
|---|---|---|---|---|
| Dart | — | — | Mobile app | 34.1% |
| JavaScript | — | — | Front-end | 29.7% |
| CSS | — | — | Styling | 14.5% |
| C# (Razor) | — | — | Web pages | 12.7% |
| C# | — | — | Web, API, admin | 8.1% |
| SQL | — | — | Database | 0.5% |
| HTML | — | — | Front-end | 0.2% |
| SCSS | — | — | Styling | 0.2% |
| Java | — | — | API | 0.1% |
| Shell | — | — | Scripts | 0% |
| Swift | — | — | Mobile app | 0% |
- Primary language
- C# 10 / .NET SDK 10.0
- Framework
- ASP.NET Core 10 + Flutter 3.35
- Database
- SQL Server 2019+
- Authentication
- Cookie (admin + website), JWT bearer (mobile)
- Licence
- Single-site
- Screens
- 47
- Database tables
- 33
- Supported languages
- English, Arabic (RTL)
- 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 (Docker) or Windows Server 2019+, .NET SDK 10.0, SQL Server 2019+ | Linux (Docker) or Windows Server 2019+, .NET SDK 10.0, SQL Server 2019+ |
| Est. monthly hosting | $25 | $25 |
cp .env.example .env # set MSSQL_SA_PASSWORD, APP_DB_PASSWORD, ADMIN_INITIAL_PASSWORD, JWT_KEY docker compose up -d --build # site: http://localhost:8080, admin: /admin
Install .NET SDK 10 and SQL Server 2019+, run database/schema.sql, then: cd "NET Project" && dotnet publish IraqShopping/IraqShopping.csproj -c Release -o /var/www/swapio Set the values from appsettings.example.json as environment variables and run it as a systemd service.
Create a .NET 10 web app and an Azure SQL database, run schema.sql, set the connection string and settings in App Service Configuration, then deploy the publish output as a ZIP.
cd "Flutter APP" flutter build apk --release --dart-define=SERVER_URL=https://your-domain.com/ --dart-define=GOOGLE_MAPS_API_KEY=your-key flutter build ipa --release --dart-define=SERVER_URL=https://your-domain.com/ --dart-define=GOOGLE_MAPS_API_KEY=your-key
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.
Reviewer notes (3 minor)
Weak default credentials and example files with realistic values present; multiple outdated dependencies, no critical vulnerabilities detected; significant code duplication, oversized files, and mixed concerns reduce maintainability; build reproducible with gaps: missing .net sdk version, incomplete docker setup, unclear flutter config. None of these stop the software from working; the developer has been told and improvements come in a future update.
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.