Customisation Guide
This guide covers every way to customise Online Casino Script — from no-code branding changes through the admin panel to full code-level extension of games and payment providers.
Table of Contents
- Branding via the admin panel
- CSS variables reference
- Email template customisation
- PWA manifest and app icons
- Legal pages and content management
- Adding a custom game
- Adding a custom payment provider
- Customising the Vue frontend
- Extension points and events
1. Branding via the admin panel
All visual branding changes can be made without touching code through Admin → Settings → Theme.
Logo
- Navigate to Admin → Settings → Theme → Logo Upload.
- Drag and drop your file or click to browse.
- Recommended specs:
| Asset | Size | Format | Notes |
|---|---|---|---|
| Logo | 200 × 60 px | PNG or SVG | Use PNG/SVG for transparent backgrounds. Max 2 MB. |
| Favicon | 32 × 32 px | PNG | Shown in browser tabs |
| Home screen icon | 192 × 192 px | PNG | PWA install on mobile |
| App icon (hi-res) | 512 × 512 px | PNG | Browser install prompt |
Colours
The Theme tab exposes three primary colour controls:
| Control | CSS variable | Default | Affects |
|---|---|---|---|
| Primary colour | --accent-primary |
#00E701 |
Buttons, links, active states |
| Secondary colour | --accent-secondary |
#1475E1 |
Secondary buttons, info badges |
| Gold / VIP accent | --accent-gold |
#FFD700 |
VIP badges, jackpot highlights |
Click a colour swatch to open the colour picker, or type a hex code directly. Use the presets at the top of the Theme tab to apply a coordinated colour scheme in one click.
Available presets:
- Dark Luxe — deep navy + gold
- Neon Crypto — black + electric purple/cyan
- Classic Casino — dark green + gold
- Clean Modern — slate + bright blue
- Sports Style — dark + green
Fonts
| Selector | CSS variable | Used for |
|---|---|---|
| Body font | --font-family-primary |
All body copy, labels, navigation, inputs |
| Display / heading font | --font-family-display |
Game titles, jackpot amounts, large headings |
All listed fonts are Google Fonts loaded on demand. To add a font not in the dropdown, see Section 2 — CSS variables.
Open Graph and SEO
Go to Admin → Settings → General to set:
- Casino Name — browser title, OG title, Twitter card title
- Site Description — meta description, OG description
- OG Image — preview image on social shares (recommended: 1200 × 630 px JPG)
2. CSS variables reference
All theme values are injected as CSS custom properties on :root. You can override any variable by editing resources/css/app.css and rebuilding the frontend.
npm run build
Background colours
| Variable | Default | Where used |
|---|---|---|
--bg-primary |
#0F1923 |
Page background, header |
--bg-secondary |
#1A2C38 |
Cards, sidebars, modals |
--bg-tertiary |
#213743 |
Input fields, table rows |
--bg-sidebar |
#0B1520 |
Left navigation sidebar |
--bg-game |
#0D1B2A |
Game canvas background |
Text colours
| Variable | Default | Where used |
|---|---|---|
--text-primary |
#FFFFFF |
Headings, labels |
--text-secondary |
#B1BAD3 |
Body text, descriptions |
--text-tertiary |
#7F8FA4 |
Timestamps, captions, help text |
--text-disabled |
#4A5568 |
Disabled inputs, inactive tabs |
Accent colours
| Variable | Default | Where used |
|---|---|---|
--accent-primary |
#00E701 |
CTA buttons, links, active nav |
--accent-primary-hover |
#00CC01 |
Button hover state |
--accent-secondary |
#1475E1 |
Secondary actions, info states |
--accent-gold |
#FFD700 |
VIP tiers, premium badges |
--accent-purple |
#9B59B6 |
Bonus badges, promotions |
Status colours
| Variable | Default | Where used |
|---|---|---|
--color-success |
#00E701 |
Success toasts, balance increases |
--color-danger |
#ED4245 |
Error states, balance decreases |
--color-warning |
#FFA726 |
Pending status warnings |
--color-info |
#1475E1 |
Informational messages |
Typography
| Variable | Default | Where used |
|---|---|---|
--font-family-primary |
Inter, sans-serif |
All body text |
--font-family-display |
Russo One, sans-serif |
Game titles, large headings |
Adding a custom font
- Add the
@importat the top ofresources/css/app.css:
@import url('https://fonts.googleapis.com/css2?family=Your+Font:wght@400;600;700&display=swap');
- Override the font variable:
:root {
--font-family-primary: 'Your Font', sans-serif;
}
- Rebuild:
npm run build
3. Email template customisation
All transactional email templates are Blade files in resources/views/emails/. The shared outer wrapper is resources/views/emails/layout.blade.php.
The golden rule: Edit the Blade template to change how an email looks. Edit the Mailable class (app/Mail/) to change what data is available inside the template.
Shared layout
resources/views/emails/layout.blade.php controls:
- Background colour (
#0F1923by default) - Header logo and accent border colour
- Footer company name, address, and links
All individual templates extend this layout via:
@extends('emails.layout')
@section('content')
{{-- your email body here --}}
@endsection
Adding your logo to emails
Upload your logo to public/logo-email.png (recommended: 200 × 60 px, transparent PNG), then in layout.blade.php replace the text logo with:
<img src="{{ config('app.url') }}/logo-email.png"
alt="{{ config('app.name') }}"
width="200" height="60"
style="display: block; border: 0;" />
Always use an absolute URL (
config('app.url')) in email imagesrcattributes — relative paths are not loaded by Gmail or Outlook.
Rebranding email colours
Find and replace these default hex values across all templates in resources/views/emails/:
| Default value | Where used |
|---|---|
#0F1923 |
Email background and header |
#00E701 |
Primary accent (buttons, borders) |
#1475E1 |
Secondary accent and links |
#B1BAD3 |
Body text |
#7F8FA4 |
Footer text |
Email templates reference
| File | Trigger | Mailable class |
|---|---|---|
welcome.blade.php |
Player registration | WelcomeEmail |
verify-email.blade.php |
Email verification | VerifyEmailMail |
verification-code.blade.php |
2FA / OTP delivery | EmailVerificationCode |
password-reset.blade.php |
Password reset request | PasswordResetMail |
deposit-confirmed.blade.php |
Deposit confirmed | DepositConfirmedEmail |
withdrawal-approved.blade.php |
Withdrawal approved | WithdrawalApprovedEmail |
withdrawal-rejected.blade.php |
Withdrawal rejected | WithdrawalRejectedEmail |
bonus-awarded.blade.php |
Bonus credited | BonusAwardedEmail |
bonus-expiring.blade.php |
Bonus expiry (24h warning) | BonusExpiringEmail |
self-exclusion-confirmed.blade.php |
Self-exclusion activated | SelfExclusionConfirmedEmail |
account-suspended.blade.php |
Account suspended | AccountSuspendedEmail |
Previewing emails locally
The Docker environment includes Mailpit at http://localhost:8025. All emails sent in the local environment are captured by Mailpit rather than dispatched.
To manually trigger a specific email:
php artisan tinker
>>> $user = AppModelsUser::first();
>>> Mail::to($user->email)->send(new AppMailWelcomeEmail($user));
Changing the From address per email
Edit the envelope() method in the Mailable class:
// app/Mail/BonusAwardedEmail.php
public function envelope(): Envelope
{
return new Envelope(
from: new Address('promotions@yourcasino.com', config('app.name').' Promotions'),
subject: 'Bonus credited to your account',
);
}
4. PWA manifest and app icons
The PWA manifest controls how the casino appears when a player installs it as a home screen app.
File: public/manifest.json
{
"name": "Your Casino Name",
"short_name": "YourCasino",
"description": "Your casino tagline.",
"start_url": "/",
"display": "standalone",
"background_color": "#0F1923",
"theme_color": "#00E701",
"icons": [...]
}
| Field | Purpose |
|---|---|
name |
Full name in install prompts |
short_name |
Under icon on home screen (keep under 12 characters) |
background_color |
Splash screen background while loading |
theme_color |
Browser chrome colour on Android |
Replacing icons
Replace all icon files in public/icons/:
| File | Size | Usage |
|---|---|---|
icon-72x72.png |
72 × 72 px | Low-DPI home screen |
icon-96x96.png |
96 × 96 px | Chrome on Android |
icon-128x128.png |
128 × 128 px | Chrome Web Store |
icon-144x144.png |
144 × 144 px | Windows tiles |
icon-152x152.png |
152 × 152 px | iPad home screen |
icon-192x192.png |
192 × 192 px | Android home screen (primary) |
icon-384x384.png |
384 × 384 px | High-DPI Android |
icon-512x512.png |
512 × 512 px | PWA install prompt (required) |
Tip: Use PWABuilder or Real Favicon Generator to generate all sizes from one 512 × 512 px source image.
No rebuild is required after updating manifest.json or icon files — they are served directly from public/.
5. Legal pages and content management
Legal pages are managed through the built-in CMS. No code edits required.
- Go to Admin → Content
- Click the page to edit (Terms of Service, Privacy Policy, etc.)
- Use the rich-text editor
- Click Save — changes are live immediately
Placeholders
All templates use {{site_name}} which is automatically replaced with your casino name from Admin → Settings → General → Casino Name.
You must manually fill in:
| Placeholder | Required on |
|---|---|
| Company legal name | All pages |
| Registered address | Privacy Policy, AML Policy |
| Gambling licence number and issuing authority | Terms of Service |
| Governing law jurisdiction | Terms of Service |
| Data Protection Officer contact | Privacy Policy (GDPR) |
| Responsible gaming helpline numbers | Responsible Gaming page |
| Minimum age | Terms of Service, Acceptable Use Policy |
| Customer support email | All pages |
Legal notice: These templates are starting points. Have your legal counsel review all pages before accepting real players.
6. Adding a custom game
All games extend app/Services/Games/BaseGame.php and implement GameInterface. The provably fair RNG system is available to any game.
Step 1 — Create the game service
Create app/Services/Games/MyCustomGame.php:
<?php
namespace AppServicesGames;
use AppContractsGameInterface;
use AppServicesProvablyFairProvablyFairService;
class MyCustomGame extends BaseGame implements GameInterface
{
public function __construct(ProvablyFairService $pf)
{
parent::__construct($pf);
}
public function play(array $bet): array
{
// 1. Validate bet amount and options via $this->validateBet($bet)
// 2. Generate outcome via $this->generateOutcome($bet)
// 3. Calculate payout
// 4. Debit wallet, record game round, credit payout via BaseGame helpers
// 5. Return round result array
}
}
Step 2 — Register the game
Add an entry to config/games.php:
'my-custom-game' => [
'name' => 'My Custom Game',
'slug' => 'my-custom-game',
'class' => AppServicesGamesMyCustomGame::class,
'category' => 'instant',
'rtp' => 97.0,
'min_bet_cents' => 10,
'max_bet_cents' => 100000,
'max_payout_cents' => 10000000,
],
Step 3 — Add a migration and seeder entry
Create a migration to add the game configuration to the games table, then update database/seeders/GameSeeder.php to include the new entry.
Step 4 — Add the API route
Add the play endpoint to routes/api.php:
Route::post('/games/my-custom-game/play', [MyCustomGameController::class, 'play'])
->middleware(['auth:api', 'throttle:game-play']);
Step 5 — Create the Vue frontend component
Create resources/js/pages/games/MyCustomGame.vue. Follow the structure of an existing instant game component (e.g., DicePage.vue or KenoPage.vue) for the standard game layout and bet submission pattern.
Always use resources/js/api/client.ts for API calls — never import Axios directly.
Provably fair integration
BaseGame exposes the provably fair system via $this->pf:
// Generate outcome bytes from the current seed pair
$bytes = $this->pf->generateBytes($userId, $nonce);
// Derive a value in range [0, 1)
$float = $this->pf->bytesToFloat($bytes);
The server seed hash, client seed, and nonce are automatically included in every game round response.
7. Adding a custom payment provider
Payment providers implement the provider adapter interface. The wallet and transaction system handles everything else.
Step 1 — Create the adapter
Create app/Services/Payments/MyProviderAdapter.php:
<?php
namespace AppServicesPayments;
use AppContractsPaymentProviderInterface;
class MyProviderAdapter implements PaymentProviderInterface
{
public function initiateDeposit(array $params): array
{
// Return ['redirect_url' => '...'] or ['instructions' => '...']
}
public function processWithdrawal(array $params): array
{
// Initiate payout via provider API
// Return ['provider_reference' => '...']
}
public function verifyWebhook(array $payload, string $signature): bool
{
// Verify the provider's webhook signing secret
}
public function handleWebhook(array $payload): void
{
// Parse the webhook and dispatch the appropriate job
// (ConfirmDeposit or ConfirmWithdrawal)
}
}
Step 2 — Register the provider
Add credentials to .env:
MY_PROVIDER_API_KEY=
MY_PROVIDER_WEBHOOK_SECRET=
Register the adapter in config/payment_providers.php (or the equivalent config file used by your version):
'my-provider' => [
'name' => 'My Provider',
'class' => AppServicesPaymentsMyProviderAdapter::class,
'enabled' => env('MY_PROVIDER_ENABLED', false),
],
Step 3 — Add the webhook route
// routes/api.php
Route::post('/webhooks/payment/my-provider', [PaymentWebhookController::class, 'handle'])
->middleware('throttle:webhooks');
Step 4 — Enable in Admin
Go to Admin → Settings → Payment Methods → Add Method, select your provider, configure limits, and toggle it enabled.
8. Customising the Vue frontend
The player-facing SPA is a Vue 3 application in resources/js/.
resources/js/
├── api/ ← Axios API client — always use this, never import axios directly
├── components/ ← Shared UI components
├── pages/ ← Route-level page components
├── stores/ ← Pinia state stores
└── router/ ← Vue Router configuration
Development workflow
make dev # Docker: start with Vite hot reload
npm run dev # Manual: start Vite dev server
Changes to Vue components are reflected immediately via HMR without a page reload.
Building for production
npm run build
Vite generates content-hashed filenames in public/build/. The build manifest at public/build/manifest.json is used by Laravel to generate asset URLs.
TypeScript type checking
npm run type-check
ESLint
npm run lint
Referencing design prototypes
Static HTML prototypes are in development/online-casino-script/client/:
- Player pages →
client/pages/*.html - Admin pages →
client/admin/*.html - Game UIs →
client/games/*.html - Design tokens →
client/shared/design-system.css
Use these as pixel-perfect visual specifications when building new UI components.
9. Extension points and events
Laravel events
The application dispatches Laravel events at key points in the game and wallet lifecycle. Listen to these events in a custom EventServiceProvider to trigger side effects without modifying core code.
| Event | When dispatched | Payload |
|---|---|---|
GameRoundCompleted |
After every game round resolves | Round result, user, payout |
DepositConfirmed |
After a deposit webhook confirms | Transaction, user |
WithdrawalApproved |
After admin approves a withdrawal | Transaction, user |
WithdrawalRejected |
After admin rejects a withdrawal | Transaction, user, reason |
KycApproved |
After KYC document is approved | User |
KycRejected |
After KYC document is rejected | User, reason |
BonusAwarded |
After a bonus is credited | Bonus, user |
BonusCompleted |
After wagering requirements are met | Bonus, user |
BonusForfeited |
After a bonus is forfeited or expired | Bonus, user |
SelfExclusionActivated |
After a player self-excludes | User, period |
Example listener:
// app/Listeners/SendDepositAnalyticsEvent.php
class SendDepositAnalyticsEvent
{
public function handle(DepositConfirmed $event): void
{
// Send to your analytics platform
}
}
Register in app/Providers/EventServiceProvider.php:
protected $listen = [
DepositConfirmed::class => [
SendDepositAnalyticsEvent::class,
],
];
Service container
All core services are bound in the service container and can be overridden in AppServiceProvider or a custom service provider:
// Override the default WalletService with a custom subclass
$this->app->bind(
AppServicesWalletService::class,
AppServicesMyCustomWalletService::class
);
Configuration
Per-game configuration is loaded from config/games.php. Add custom keys to your game’s config entry and read them via:
config("games.my-custom-game.my_custom_key")
Site-wide settings are managed through the SiteSetting model and accessible at:
AppModelsSiteSetting::get('setting_key', $default)
New settings can be seeded via database/seeders/SiteSettingSeeder.php.
Branding checklist
Use this checklist to confirm all customisation steps are complete before going live:
- [ ] Logo uploaded in Admin → Settings → Theme
- [ ] Primary, secondary, and gold accent colours set
- [ ] Body font and display font selected
- [ ] Email layout updated with logo and brand colours
- [ ] Email footer updated with company name and registered address
- [ ]
public/manifest.jsonupdated with casino name andtheme_color - [ ] All PWA icon files replaced with branded versions
- [ ] Casino Name and Site Description set in Admin → Settings → General
- [ ] OG image uploaded and URL configured
- [ ] Legal page content reviewed and customised for your jurisdiction
- [ ] Test email sent from Admin → Settings → Email
For environment variable reference, see Configuration Reference. For API integration, see API Reference. For production deployment, see Deployment Guide.