Documentation Developer Guide Customisation Guide

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

  1. Branding via the admin panel
  2. CSS variables reference
  3. Email template customisation
  4. PWA manifest and app icons
  5. Legal pages and content management
  6. Adding a custom game
  7. Adding a custom payment provider
  8. Customising the Vue frontend
  9. Extension points and events

1. Branding via the admin panel

All visual branding changes can be made without touching code through Admin → Settings → Theme.

  1. Navigate to Admin → Settings → Theme → Logo Upload.
  2. Drag and drop your file or click to browse.
  3. 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

  1. Add the @import at the top of resources/css/app.css:
@import url('https://fonts.googleapis.com/css2?family=Your+Font:wght@400;600;700&display=swap');
  1. Override the font variable:
:root {
  --font-family-primary: 'Your Font', sans-serif;
}
  1. 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 (#0F1923 by 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 image src attributes — 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/.


Legal pages are managed through the built-in CMS. No code edits required.

  1. Go to Admin → Content
  2. Click the page to edit (Terms of Service, Privacy Policy, etc.)
  3. Use the rich-text editor
  4. 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.json updated with casino name and theme_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.