Why ShopNest
What makes it better
than the alternatives
- 01
Multi-vendor with seller scope
Sellers manage only their own products, orders, invoices and stock; staff users are limited by per-module role permissions
- 02
Security-first API
Every endpoint requires Authorization and CustomerOwnershipFilter (44 controllers, 78 xUnit tests verify no anonymous access and no cross-customer data leaks)
- 03
Bilingual out of the box
English and Arabic with RTL layout in the website and mobile app; admin dictionary for custom translations
- 04
Flutter app with guest cart merge
Guest browsing, wishlist and cart are merged into the account at sign-in; Cubit state management, GetIt DI, secure token storage
- 05
Docker-based local setup
Docker-compose.yml starts SQL Server, applies migrations, installs procedures and loads demo data (26 categories, 24 products, 3 orders) in one command
REST API (ShopNest.Api)
- 44 controllers: authentication (sign-up
- sign-in with email/phone
- OTP
- password reset)
- customer profile
- products
- categories
- brands
- search with filters
- cart
- discount codes
- addresses
- checkout
- orders
- reorder
- wishlist
- reviews
- notifications
- CMS pages
- FAQ
- blog
- contact form
- JWT access tokens (60 min) and customer tokens (30 days) stored in device keystore by the app
- Stripe Checkout integration: creates payment session
- handles webhook
- updates invoice status
- CustomerOwnershipFilter on BaseController and every controller class: customerId in request must match X-Customer-Token
- Anonymous endpoint: POST /generate-token/{key} issues app access token from ApiAuths table
- Swagger UI at /swagger; rate limiting (300 requests/min
- 10 credentials/min)
- PBKDF2 password hashing (600k iterations
- salted
- constant-time check); OTP stored as keyed hashes with expiry and attempt limit
Admin & Seller Panel (ShopNest.Admin)
- 73 MVC controllers with Authorize on BaseController and each class (xUnit test fails if one is missing); only sign-in and password-reset are AllowAnonymous
- Dashboard: sales figures
- recent orders
- low stock alerts
- Catalogue: products (SKUs
- variants
- stock
- images
- Arabic text)
- categories (26 seeded)
- brands (6 seeded)
- attributes
- product approval workflow for sellers
- Sellers: stores (2 demo: Urban Closet
- Coastline Goods)
- seller users (Role 1)
- product approval
- payouts
- Orders: list
- details
- status changes
- invoice PDF download (Select.HtmlToPdf
- Windows only)
- Aramex shipment creation and tracking
- Delivery: methods
- Aramex rate calculation
- shipment tracking background service polls invoices with AWB
- Marketing: discount codes
- banners (hero
- CMS blocks)
- blog
- push notifications (Firebase Cloud Messaging HTTP v1)
- Content: CMS pages (About
- Shipping
- Returns
- Terms
- Privacy
- Help)
- FAQs (tags
- EN+AR)
- dictionary (translations)
- social links
- Settings: languages (EN
- AR seeded)
- currencies (AED
- USD
- EUR
- GBP seeded)
- countries/states/cities (UAE emirates and cities seeded)
- email templates
- payment gateway (Stripe keys)
- SMTP
- Aramex credentials
- base path for uploads
- Roles and modules: 2 roles seeded (Seller
- Super Admin)
- 18 modules (Dashboard
- Products
- Orders
- Customers
- Reports
- Settings
- etc.)
- RequireModule attribute checks RoleModules join table
- Seller scope helpers in BaseController: IsSellerAccount
- IsAnotherSuppliersRecord
- IsAnotherSuppliersProductAsync
- OwnSupplierIdOrNull; sellers cannot approve products or change customers/users
- Reports: sales
- orders
- products
- customers; Excel export
Storefront Website (ShopNest.Web)
- ASP.NET Core MVC; no database access
- calls API over HTTP with TokenUserKey from appsettings
- Guest browsing
- guest cart and guest wishlist merged into account at sign-in
- Sign-up and sign-in with email or phone
- OTP
- password reset
- Google and Facebook OAuth (ClientId/Secret in appsettings)
- Home: hero banner
- CMS blocks
- product rails (featured
- new
- popular
- on sale
- most viewed
- new arrivals) configured in admin ProductConfigs
- Categories
- brands
- search with filters (category
- brand
- price range)
- Product page: gallery
- variants (colour
- size)
- reviews
- related/up-sell/cross-sell products
- Cart
- discount codes
- shipping addresses
- checkout
- Stripe Checkout or cash on delivery
- Order history
- order details
- reorder
- PDF invoice download
- CMS pages
- FAQ
- blog
- contact form
- newsletter
- English and Arabic with RTL layout; light theme only
- Demo credentials box on login modal (enabled in appsettings.Development.json
- shows customer@shopnest.local / Customer@123 and admin panel link)
Flutter Mobile App
- Flutter 3.47.5
- Dart 3.13; iOS 15.0+ and Android (AGP 9.1
- Kotlin 2.4
- Gradle 9.3)
- Onboarding
- guest browsing
- guest cart and wishlist merged at sign-in
- Email/phone sign-in with OTP
- sign-up
- forgot/reset password
- Home: hero banner
- CMS banners
- product rails (featured
- just landed
- popular
- on sale
- most viewed
- new arrivals)
- Category browsing
- search with filters (category
- brand
- price range)
- Product details: gallery
- variants
- upsell and related products
- Wishlist (guest and signed-in)
- shopping bag
- discount codes
- Shipping addresses
- checkout
- Stripe hosted checkout
- invoice PDF download
- Orders history
- order details
- one-tap reorder
- In-app notifications
- push-notification preference toggle
- CMS pages (About
- Shipping
- Returns
- Terms
- Privacy
- Help)
- FAQ
- Profile editing
- account deletion flow
- Light and dark theme
- English/Arabic with RTL
- Architecture: feature folders
- Cubit (flutter_bloc)
- GetIt DI
- Dio networking
- TokenInterceptor adds Authorization and X-Customer-Token headers automatically
- Tokens stored in device keystore (flutter_secure_storage)
- not shared preferences
- Configuration via --dart-define-from-file (API_BASE_URL
- IMAGE_BASE_URL
- API_CLIENT_KEY
- SHOW_DEMO_CREDENTIALS); config/local.json and config/android-emulator.json for local dev
- config/prod.example.json template
- Build: flutter build apk/appbundle for Android (keystore in android/key.properties)
- flutter build ipa for iOS (Xcode signing)
- App icons and splash: assets/icon/ source images
- dart run flutter_launcher_icons and flutter_native_splash:create to regenerate
Database & Migrations
- SQL Server 2019+; EF Core 10 migrations in Infrastructure/Migrations/ (20 migration files)
- database/schema.sql (326 KB) and database/seed.sql (131 KB) generated from migrations and SQL sources; run with sqlcmd on any platform
- docker-compose.yml: SQL Server with schema and demo data loaded automatically (set SHOPNEST_SA_PASSWORD in .env)
- Stored procedures in SQL/ folder: GetProductMasterList
- GetProductMasterListForCustomer
- GetProductMasterListForCustomerByCategory
- GetProductMasterListForCustomerByBrand
- GetProductMasterListForCustomerBySearch
- GetProductMasterListForCustomerByProductConfig
- GetProductMasterListForCustomerByProductType
- GetProductMasterListForCustomerByProductMaster
- GetProductMasterListForCustomerByProductMasterForRelated
- GetProductMasterListForCustomerByProductMasterForUpSell
- GetProductMasterListForCustomerByProductMasterForCrossSell
- GetProductMasterListForCustomerByProductMasterForSimilar
- GetProductMasterListForCustomerByProductMasterForRecentlyViewed
- GetProductMasterListForCustomerByProductMasterForMostViewed
- GetProductMasterListForCustomerByProductMasterForNewArrivals
- GetProductMasterListForCustomerByProductMasterForFeatured
- GetProductMasterListForCustomerByProductMasterForPopular
- GetProductMasterListForCustomerByProductMasterForOnSale
- GetProductMasterListForCustomerByProductMasterForJustLanded
- Table types: ProductMasterTableType
- ProductSkuTableType
- ProductImageTableType
- ProductAttributeTableType
- ProductRelatedTableType
- ProductUpSellTableType
- ProductCrossSellTableType
- Demo seed (SQL/Seed/): 01_reference_data.sql (languages
- currencies
- countries/states/cities
- payment methods
- invoice statuses
- product configs
- product types
- attributes
- join types
- delivery methods
- FAQ tags
- settings
- API key SHOPNEST-DEV-KEY
- roles
- modules
- role modules
- admin user admin@shopnest.local / Admin@123
- seller users seller1@shopnest.local and seller2@shopnest.local / Seller@123
- module columns)
- 02_demo_catalog.sql (26 categories
- 6 brands
- 2 sellers with stores
- 24 products with SKUs
- stock
- images
- Arabic text
- home-row configs
- related/up-sell/cross-sell links)
- 03_demo_content.sql (banners
- WebHtml home blocks
- CMS pages
- FAQs
- social links
- dictionary EN+AR
- blog
- demo customer customer@shopnest.local / Customer@123 with address
- reviews
- product views
- wishlist
- 3 demo orders)
- scripts/setup-local-db.sh: idempotent script starts SQL Server
- applies migrations
- installs procedures
- generates demo images if missing
- runs seeds
- scripts/demo-seed/: Python generators for demo images (requirements.txt: Pillow==12.3.0)
- smoke-test-api.sh (fetches token
- checks ~50 endpoints and image URLs
- needs jq)
Security & Authentication
- API: Authorize and ServiceFilter(typeof(CustomerOwnershipFilter)) on BaseController and each of 44 controllers (xUnit test fails if one is missing); only POST /generate-token/{key} is anonymous
- Admin: Authorize on BaseController and each of 73 controllers (xUnit test fails if one is missing); only sign-in and 3 password-reset actions are AllowAnonymous; RequireModule checks RoleModules
- Seller scope: IsSellerAccount
- IsAnotherSuppliersRecord
- IsAnotherSuppliersProductAsync
- IsAnotherSuppliersOrderAsync
- OwnSupplierIdOrNull helpers in admin BaseController; sellers list/open/change/delete only their own products
- orders
- invoices
- stock and reports; cannot approve products or change customers/users
- Passwords: salted PBKDF2-HMAC-SHA256
- 600
- 000 iterations
- constant-time check (Service/Security/PasswordHasher.cs); CustomerPasswordMinLength 6
- AdminPasswordMinLength 8
- One-time passcodes: stored as keyed hashes
- expiry (OtpValidMinutes 10) and attempt limit (OtpMaxAttempts 5) in Service/Security/OtpGuard.cs
- No secret in any file: connection string
- Jwt__Key (32+ chars) and Security__OtpHashKey come from environment or dotnet user-secrets; in Development API creates random key once per machine
- JWT: access token (60 min)
- customer token (30 days); TokenInterceptor in app adds both headers automatically
- Rate limiting: 300 requests/min general
- 10 credentials/min for sign-in/sign-up/password-reset
- 78 xUnit security tests (ShopNest.Api.Tests): verify every endpoint needs a token
- credentials are only read from body
- a customer cannot reach another customer's records
- password and passcode rules
- no API or admin action is left without Authorize
Integrations
- Stripe Checkout: API creates payment session (POST /api/v1/stripe/create-checkout-session)
- returns sessionId and sessionUrl; app/website redirects to Stripe hosted page; webhook at /api/v1/stripe/webhook updates invoice status; StripeProductImageUrl in appsettings for product images in Stripe UI
- Aramex: rate calculation (DelivarySettings table holds credentials)
- shipment creation (admin creates shipment from invoice details
- stores AWB in Invoices.AramexAWB)
- tracking background service polls invoices with AWB and updates Invoices.AramexTrackingStatus
- SMTP: EmailSetups table (Host
- Port
- Username
- Password
- FromEmail
- FromName
- IsActive); admin sends test email; seeded with placeholder and IsActive=0 so no mail is sent by default
- Firebase Cloud Messaging: HTTP v1 API; service-account JSON uploaded in admin Settings > Firebase Setup
- saved to App_Data/firebase/<guid>.json (outside wwwroot
- never web-accessible); FirebaseSetups table stores ProjectId and JsonPath; push notifications sent from admin Marketing > Notifications; app has in-app notification list and push-notification preference toggle
- Google OAuth: website sign-in (ClientId/Secret in appsettings.json Authentication:Google section)
- Facebook OAuth: website sign-in (AppId/AppSecret in appsettings.json Authentication:Facebook section)
Content & Localization
- CMS pages: About
- Shipping & Delivery
- Online Returns
- Terms & Conditions
- Privacy Policy
- Help & Support; admin edits with TinyMCE; seeded with placeholder text
- FAQ: tags (General
- Account
- Orders
- Payments
- Shipping
- Returns seeded)
- questions and answers in EN and AR; admin manages in Content > FAQ
- Blog: posts with title
- slug
- content
- featured image
- publish date; admin manages in Marketing > Blog; website and app show list and detail
- Dictionary: key-value translations for UI strings; admin manages in Content > Dictionary; seeded with EN and AR for common labels (Home
- Shop
- Cart
- Checkout
- My Orders
- Profile
- etc.)
- Languages: LanguageSetups table (Name
- Code
- IsActive
- IsRTL); EN and AR seeded; website and app switch language with dropdown; RTL layout for Arabic
- Social links: admin manages in Content > Social Links; website footer shows icons
- Banners: hero banner (home page top)
- CMS banners (home page blocks); admin uploads images and sets links in Marketing > Banners
- Product rails: admin configures in Settings > Product Configs (Featured
- New Arrivals
- Popular
- On Sale
- Most Viewed
- Just Landed); home page shows rails with GetProductMasterListForCustomerByProductConfig stored procedure
Reports & Analytics
- Dashboard: sales figures (total sales
- orders
- customers)
- recent orders
- low stock alerts
- Sales report: filter by date range
- seller
- category
- brand; shows revenue
- order count
- average order value; Excel export
- Orders report: filter by date range
- status
- seller; shows order details
- customer
- total; Excel export
- Products report: filter by category
- brand
- seller; shows product name
- SKU
- stock
- sales; Excel export
- Customers report: filter by date range
- country; shows customer name
- phone
- orders
- total spent; Excel export
- Product views tracking: ProductViews table stores CustomerId
- ProductMasterId
- ViewedAt; Most Viewed rail uses this data
- Seller reports: sellers see only their own data (IsSellerAccount check in BaseController)
Developer Tools & Testing
- 78 xUnit security tests in ShopNest.Api.Tests: use EF Core InMemory provider
- no SQL Server needed; run with dotnet test; verify Authorize on every controller
- CustomerOwnershipFilter on every endpoint
- password rules
- OTP rules
- no anonymous access except /generate-token
- Flutter tests: flutter test runs widget tests and unit tests (search_cubit_test.dart
- demo_credentials_box_test.dart)
- Swagger UI: http://localhost:5039/swagger; try-it-out for every endpoint; shows request/response schemas
- scripts/dev-secrets.sh: puts connection string into dotnet user-secrets for ShopNest.Api and ShopNest.Admin (one-time setup)
- scripts/demo-seed/smoke-test-api.sh: fetches token
- checks ~50 endpoints and image URLs; needs jq
- CLAUDE.md and AGENTS.md: architecture
- folder map
- conventions
- how to run tests; guide for AI coding tools and new developers
- DEVELOPER-GUIDE.md: long version with every detail
- appsettings.example.json in each web project: describes every setting
- docker-compose.yml: SQL Server 2019 with schema and demo data loaded automatically; set SHOPNEST_SA_PASSWORD in .env (copy from .env.example)
- database/schema.sql and database/seed.sql: generated from migrations and SQL sources; run with sqlcmd on any platform (no Visual Studio or Windows needed)
| Language | Version | Framework | Used for | Share of code |
|---|---|---|---|---|
| C# | — | — | Web, API, admin | 63.8% |
| JavaScript | — | — | Front-end | 15.8% |
| CSS | — | — | Styling | 6% |
| C# (Razor) | — | — | Web pages | 4.8% |
| Dart | — | — | Mobile app | 4.2% |
| SQL | — | — | Database | 2.1% |
| SCSS | — | — | Styling | 2% |
| HTML | — | — | Front-end | 1% |
| Python | — | — | Web, API | 0.2% |
| Shell | — | — | Scripts | 0% |
| Java | — | — | API | 0% |
| PowerShell | — | — | Scripts | 0% |
| Swift | — | — | Mobile app | 0% |
| Kotlin | — | — | Mobile app | 0% |
- Primary language
- C# 12 (.NET 10)
- Framework
- ASP.NET Core 10 MVC + Web API
- Database
- SQL Server 2019
- Authentication
- JWT (API), Cookie (Admin/Website), OAuth2 (Google, Facebook)
- Licence
- Single-site
- Screens
- 147
- Database tables
- 89
- 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 SSD | 8 GB RAM / 40 GB SSD |
| OS | Linux/Windows with .NET 10 SDK, SQL Server 2019+, Docker 20+ | Linux/Windows with .NET 10 SDK, SQL Server 2019+, Docker 20+ |
| Est. monthly hosting | $35 | $35 |
```bash cp .env.example .env # Edit .env: set SHOPNEST_SA_PASSWORD docker compose up -d cd "NET Project/shopnest-admin" scripts/dev-secrets.sh dotnet run --project ShopNest.Api dotnet run --project ShopNest.Admin cd ../shopnest-website dotnet run --project ShopNest.Web --urls http://localhost:5080 ```
```bash sudo apt update && sudo apt install -y dotnet-sdk-10.0 mssql-server sudo /opt/mssql/bin/mssql-conf setup sqlcmd -S localhost -U sa -i database/schema.sql sqlcmd -S localhost -U sa -i database/seed.sql cd "NET Project/shopnest-admin" dotnet publish ShopNest.Api -c Release -o /var/www/api dotnet publish ShopNest.Admin -c Release -o /var/www/admin cd ../shopnest-website dotnet publish ShopNest.Web -c Release -o /var/www/web sudo systemctl enable shopnest-api shopnest-admin shopnest-web sudo systemctl start shopnest-api shopnest-admin shopnest-web ```
```bash az login az sql server create --name shopnest-sql --resource-group shopnest-rg --location eastus --admin-user sqladmin --admin-password <password> az sql db create --resource-group shopnest-rg --server shopnest-sql --name shopnest az webapp create --name shopnest-api --resource-group shopnest-rg --plan shopnest-plan --runtime "DOTNETCORE:10.0" az webapp create --name shopnest-admin --resource-group shopnest-rg --plan shopnest-plan --runtime "DOTNETCORE:10.0" az webapp create --name shopnest-web --resource-group shopnest-rg --plan shopnest-plan --runtime "DOTNETCORE:10.0" cd "NET Project/shopnest-admin" dotnet publish ShopNest.Api -c Release az webapp deployment source config-zip --resource-group shopnest-rg --name shopnest-api --src ShopNest.Api/bin/Release/net10.0/publish.zip ```
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.
89/ 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: flutter lockfile present, .net projects lack explicit lock; some outdated packages; weak default jwt key and demo credentials in config; no real secrets found; moderate code duplication and oversized files; some business logic in controllers; build reproducible with gaps: missing stored procedures deployment, unclear firebase setup, docker compose references nonexistent files. 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.