About this software
About Padel Nation
PadelNation is an ASP.NET Core 8 platform serving four surfaces from one codebase: a public website for venue discovery, an installable PWA for mobile bookings, a REST API for member sessions, and an Admin console for operations. It handles venue/branch/court catalogues, real-time availability grids, server-priced bookings with split payments and invitations, coupon discounts, tournament registration with teams and fixtures, and member authentication with JWT sessions. The Admin area provides interactive calendar booking, cancellation, dashboard analytics, and seven report types (sales, commission, calendar, products, trainers, payment methods). SQL Server schema includes 37 entities, representative seed data, indexes, and optional reporting procedures.
Why Padel Nation
What makes it better
than the alternatives
- 01
Four surfaces from one solution
- 02
Split-payment invitations
- 03
Interactive calendar booking
- 04
Server-side price calculation
- 05
Comprehensive audit and ownership enforcement
Venue & Court Management
- Padel entity (venue) with name
- description
- logo
- banner
- address
- city
- country
- status
- PadelBranch entity (location) with branch name
- address
- coordinates
- gallery images
- facilities
- opening hours
- Court entity with name
- type
- surface
- pricing
30/60/90/120min rates) - status
- branch assignment
- BookingSchedule entity defining time slots per branch with start/end times
- active flag
- day-of-week support
- Image upload for venue logos
- branch galleries and court photos (ImageUploader
- UploadFolders.Branches
- max 5MB)
- Admin screens: Padel/Index (venue list)
- Padel/Edit (venue form)
- PadelBranch/Index (branch list with venue filter)
- PadelBranch/Edit (branch form with gallery)
- Court/Index (court list)
- Court/Edit (court form with pricing)
Booking & Availability
- Invoice entity (booking record) with readable ID
- member
- court
- date
- time
- duration
- status
Pending/Confirmed/Completed/Cancelled - grand total
- due payment
- deposit percentage
- InvoiceTimeSchedule join table linking invoices to
court/schedule/datecombinations for multi-slot bookings - BookingService.CreateBookingAsync recalculates price from court rates and duration
- applies coupon discounts
- creates pending-payment shares for invited players
- BookingService.GetAvailabilityAsync queries booked slots per court/date and returns free time windows
- BookingService.CancelBookingAsync (member-scoped) and CancelBookingAsAdminAsync (staff) soft-delete invoices and log cancellation comments
- API endpoints: POST /
api/v1/bookings(create) - GET /
api/v1/bookings(list owner's bookings) - POST /
api/v1/bookings/{id}/cancel (member cancellation) - Admin screens: Booking/Index (list with status tabs:
pending/confirmed/completed/cancelled - Booking/Details (invoice detail with players)
- Calendar/Index (interactive day-view grid)
Member Authentication & Sessions
- Member entity with phone (unique)
- full name
- password hash
- security stamp
- IsRegistered flag
- status
Active/Inactive/Suspended - city
- country
- picture
- OTP code/expiry
- AuthService.MemberRegisterAsync validates phone format and password policy
- creates member with hashed password
- issues JWT token
- AuthService.MemberLoginAsync verifies phone/password
- checks account status
- returns MemberSessionDto with token and expiry
- JwtTokenService issues bearer tokens with member ID
- phone
- security stamp claims; tokens expire after 720 hours (configurable Jwt:ExpiryHours)
- ApiControllerBase.CurrentMemberId extracts member ID from JWT claims; every API action inherits Member policy (bearer token required)
- gp-auth.js client session manager stores token in localStorage
- auto-attaches Authorization header to /api/v1 calls
- clears session on 401 and fires padelnation:signed-out event
- API endpoints: POST /
api/v1/members/register - POST /
api/v1/members/login - GET /
api/v1/members/me(token validation)
Split Payments & Invitations
- PendingPayment entity with invoice
- member
- amount
- status
- payment date
- created/updated timestamps
- BookingService.CreateBookingAsync accepts invitedPlayerIds array
- calculates per-player share (grand total ÷ player count)
- creates PendingPayment records for each invited player
- AuthService.ResolveMemberByPhoneAsync creates unregistered member stub (no password
- IsRegistered=false) if phone not found
- so invitations work before invitee registers
- AuthService.SuggestContactsAsync returns type-ahead results limited to requester's shared bookings/tournaments plus exact phone match (prevents directory browsing)
- API rate limit: member-resolve endpoint limited to 10 calls per member per hour (RateLimitPolicies.MemberResolve
- partitioned by member ID)
- Member/Details admin screen shows PendingShares list (payments owed by this member as invited player)
Coupons & Discounts
- Coupon entity with code (unique)
- title
- description
- discount type (Percentage/FixedAmount)
- discount value
- start/end dates
- usage limit
- used count
- status
- CouponService.ValidateCouponAsync checks code existence
- active status
- date range
- usage limit
- returns discount amount
- BookingService.CreateBookingAsync applies coupon discount to subtotal before calculating grand total and deposit
- Admin screens: Coupon/Index (list with tabs:
active/scheduled/expired/inactive - Coupon/Edit (form with date pickers and discount type selector)
- API endpoint: GET /
api/v1/coupons/validate?code=X returns discount details or error message
Tournaments
- Tournament entity with name
- description
- image
- start/end dates
- registration deadline
- max teams
- entry fee
- prize pool
- status
- branch assignment
- TournamentTeam entity with tournament
- team name
- captain member
- status
- registration date
- TournamentTeamMember join table linking teams to member rosters
- TournamentStage entity (groups
- knockout rounds) with stage name
- type
- order
- TournamentFixture entity with stage
- home/away teams
- match date/time
- court
- score
- status
Scheduled/InProgress/Completed/Cancelled - TournamentService.RegisterTeamAsync validates registration deadline
- team limit
- creates team and roster entries
- TournamentService.GetTournamentDetailsAsync returns tournament with stages
- fixtures
- teams and results
- Admin screens: Tournament/Index (list)
- Tournament/Edit (form with image upload)
- Tournament/Details
stages/fixtures/teams - API endpoints: GET /
api/v1/tournaments(list) - GET /
api/v1/tournaments/{id} (detail) - POST /
api/v1/tournaments/{id}/register (team registration)
Admin Console & Roles
- User entity with username
- full name
- password hash
- role
- IsAdminUser flag
- status
- Role entity with name
- permissions JSON (not enforced in code
- placeholder for future granular permissions)
- AdminArea policy requires Admin or Staff role (cookie authentication
- CookieAuthenticationDefaults.AuthenticationScheme)
- AdminOnly policy requires Admin role; applied to
User/Role/Settingcontrollers and every Delete action - AdminMutationAuditFilter logs every
POST/PUT/DELETEin Admin area to AuditLog table (user ID - action
- controller
- timestamp
- IP address)
- Admin screens: Dashboard/Index (stats cards
- recent bookings
- revenue trend
- status breakdown)
- User/Index (user list)
- User/Edit (user form)
- Role/Index (role list)
- Role/Edit (role form)
- AuthController.Login (POST with rate limit)
- AuthController.Logout (POST with anti-forgery token)
Reports & Analytics
- DashboardService.GetStatsAsync returns total bookings
- revenue
- active members
- active courts for current month
- DashboardService.GetRevenueTrendAsync returns daily revenue for last N days
- ReportService.GetSalesReportAsync (date range
- branch filter) returns bookings with invoice details
- member names
- payment status
- ReportService.GetCommissionReportAsync calculates venue/branch commission from GrandTotal and CommissionPercentage
- ReportService.GetPadelCalendarReportAsync returns bookings per court/date for calendar heatmap
- ReportService.GetProductReportAsync groups bookings by court and sums revenue
- ReportService.GetTrainerReportAsync groups bookings by trainer (if assigned) and sums sessions/revenue
- ReportService.GetPaymentMethodReportAsync groups invoices by payment method and sums totals
- Admin screens: Report/Sales
- Report/Commission
- Report/PadelCalendar
- Report/Products
- Report/Trainers
- Report/PaymentMethods (all with date/branch filters and export buttons)
Password Reset & Email
- PasswordResetService.RequestAsync generates single-use token (HMACSHA256 of account kind
- ID
- password hash
- expiry)
- sends email with reset link
- PasswordResetService.ResetConfirmedAsync validates token
- checks expiry (default 60 minutes)
- hashes new password
- updates account
- invalidates token by changing security stamp
- SmtpEmailSender sends emails via configured SMTP (host
- port
- secure flag
- user
- password
- from address in appsettings.json or environment variables)
- Three surfaces:
Admin/Auth/ForgotPassword(admin users) - Website/MemberPassword (website members)
- App password-reset screen (PWA members)
- PasswordResetAccountKind enum (Admin/Member) and PasswordResetSurface enum
Admin/Website/Appdetermine link destination - Rate limit: password-reset endpoints limited to 5 requests per IP per 15 minutes (RateLimitPolicies.PasswordReset)
- API endpoints: POST /
api/v1/members/forgot-password - GET /
api/v1/members/reset-password/validate?token=X - POST /
api/v1/members/reset-password
Progressive Web App
- manifest.webmanifest with app name
- icons (192×192
- 512×512)
- start_url=/app
- display=standalone
- theme/background colors
- Service worker (sw.js) caches app shell (HTML
- CSS
- JS
- icons) for offline access
- serves cached shell on network failure
- offline.html fallback page shown when network unavailable and requested page not cached
App/Index.cshtmlrenders mobile-first booking interface with venue search- availability grid
- booking form
- gp-auth.js session manager works identically in website and PWA (same localStorage key
- same JWT token)
- Installable on iOS (Add to Home Screen) and Android (install prompt)
| Language | Version | Framework | Used for | Share of code |
|---|---|---|---|---|
| C# | — | — | Web, API, admin | 29.6% |
| C# (Razor) | — | — | Web pages | 21% |
| SQL | — | — | Database | 18% |
| JavaScript | — | — | Front-end | 14.7% |
| CSS | — | — | Styling | 12.6% |
| HTML | — | — | Front-end | 4.1% |
- Primary language
- C# 12 (.NET 8)
- Framework
- ASP.NET Core 8.0
- Database
- SQL Server 2019
- Authentication
- Cookie (Admin), JWT Bearer (API/Member)
- Licence
- Single-site
- Screens
- 47
- Database tables
- 37
- Supported languages
- English only
- Browser support
- Modern browsers (Chrome, Firefox, Safari, Edge); PWA installable on iOS/Android
| 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 8 SDK 8.0.100+, SQL Server 2019+ or SQL Server Express | Linux/Windows with .NET 8 SDK 8.0.100+, SQL Server 2019+ or SQL Server Express |
| Est. monthly hosting | $25 | $25 |
```bash cp .env.example .env # Edit .env: set SA_PASSWORD, JWT_KEY, ADMIN_BOOTSTRAP_* (see .env.example) docker compose up --build -d # App: http://localhost:8080 Admin: http://localhost:8080/Admin ```
```bash # Install .NET 8 SDK wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh chmod +x dotnet-install.sh ./dotnet-install.sh --channel 8.0 export PATH="$HOME/.dotnet:$PATH" # Install SQL Server (Ubuntu example) wget -qO- https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/22.04/mssql-server-2022.list)" sudo apt-get update sudo apt-get install -y mssql-server sudo /opt/mssql/bin/mssql-conf setup # Choose edition, set SA password # Build and run git clone <repo> cd GoPadelPro dotnet restore GoPadelPro.sln --locked-mode dotnet build GoPadelPro.sln -c Release --no-restore # Set environment variables (or appsettings.Production.json) export ConnectionStrings__Default="Server=localhost;Database=GoPadelPro;User Id=sa;Password=<SA_PASSWORD>;TrustServerCertificate=True;MultipleActiveResultSets=True" export Jwt__Key="<32_CHAR_KEY>" export AdminBootstrap__UserName="admin" export AdminBootstrap__Email="[email protected]" export AdminBootstrap__Password="<STRONG_PASSWORD>" export App__PublicBaseUrl="https://yourdomain.com" cd src/GoPadelPro.Web dotnet run -c Release --no-build --urls "http://0.0.0.0:5000" # Reverse proxy with nginx/caddy for HTTPS ```
```bash # Create resources az group create --name padelnation-rg --location eastus az sql server create --name padelnation-sql --resource-group padelnation-rg --location eastus --admin-user sqladmin --admin-password <STRONG_PASSWORD> az sql db create --resource-group padelnation-rg --server padelnation-sql --name GoPadelPro --service-objective S1 az webapp create --resource-group padelnation-rg --plan padelnation-plan --name padelnation-app --runtime "DOTNETCORE:8.0" # Configure app settings az webapp config appsettings set --resource-group padelnation-rg --name padelnation-app --settings \ ConnectionStrings__Default="Server=padelnation-sql.database.windows.net;Database=GoPadelPro;User Id=sqladmin;Password=<PASSWORD>;" \ Jwt__Key="<32_CHAR_KEY>" \ AdminBootstrap__UserName="admin" \ AdminBootstrap__Email="[email protected]" \ AdminBootstrap__Password="<STRONG_PASSWORD>" \ App__PublicBaseUrl="https://padelnation-app.azurewebsites.net" # Deploy dotnet publish src/GoPadelPro.Web/GoPadelPro.Web.csproj -c Release -o ./publish cd publish zip -r ../app.zip . az webapp deployment source config-zip --resource-group padelnation-rg --name padelnation-app --src ../app.zip ```
```bash # Install SQL Server Express (Windows) or Docker SQL Server (Mac/Linux) # Windows: download from microsoft.com/sql-server/sql-server-downloads # Mac/Linux: docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Dev123!@#" -p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2019-latest # Clone and restore git clone <repo> cd GoPadelPro dotnet restore GoPadelPro.sln --locked-mode # Configure (create appsettings.local.json or use user-secrets) cd src/GoPadelPro.Web dotnet user-secrets set "ConnectionStrings:Default" "Server=localhost;Database=GoPadelPro;User Id=sa;Password=Dev123!@#;TrustServerCertificate=True;MultipleActiveResultSets=True" dotnet user-secrets set "Jwt:Key" "dev-key-32-characters-minimum-length-required" dotnet user-secrets set "AdminBootstrap:UserName" "admin" dotnet user-secrets set "AdminBootstrap:Email" "[email protected]" dotnet user-secrets set "AdminBootstrap:Password" "Admin123!@#" # Run dotnet run # Website: https://localhost:5001 Admin: https://localhost:5001/Admin # API: https://localhost:5001/api/v1 ```
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 (6 minor)
No real credentials found; one published dev jwt key and a weak 'sa' compose default noted; layered solution with clear projects, but large files and secrets-adjacent config sprawl hurt maintainability; build likely reproducible; digest lacks csproj/dockerfile/howtosetup contents, a few gaps remain; lockfiles present for all four projects, but contents were not visible so versions could not be verified; no injection seen in the visible excerpts, but most data-access code and the schema scripts were not reviewable; authz design looks sound, but most controllers were not provided, so coverage cannot be verified. None of these stop the software from working; the developer has been told and improvements come in a future update.
Versions & updates
Release historyCurrent version
Updates in the last 90 days
Buyers
Updates included
-
3.3.2 Version Current27 Oct 2026 ✓ Reviewed & audited
- Verification codes are now stored hashed and expire after 10 minutes, instead of being kept as readable text.
- Member search now shows only the last four digits of a phone number, so the directory can't be harvested.
- Settings, Users, Roles and Diagnostics are now restricted to administrators — staff accounts no longer see them.
- Sign-out now requires a confirmed action, closing a gap where another site could log an admin out.
- Sign-in and registration now give the same response for every failure, so they can't be used to discover who has an account.
- Resetting demo data now has to be switched on deliberately — it can no longer be triggered by accident on a live site.
- Added indexes to 13 database relationships, making bookings, payments and tournament screens faster on large datasets.
- Demo photographs moved to a separate seed folder, so a fresh install starts with a clean uploads directory.
-
1.0.0 First release 5 Oct 2026 ✓ Reviewed & audited
How updates work: versions add features and go through the full AI audit and human review. Patches are small fixes, audited and checked by a reviewer before release. Buyers get every update free for 1 year and are emailed the how-to-apply steps.
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.
- ↻No updates or supportA free download is the current version as it is. Updates and builder support come with a paid licence.