APP_NAME=Laravel APP_ENV=production APP_KEY=[[key]] APP_DEBUG=false APP_TIMEZONE=UTC APP_URL="[[softurl]]/public" REPORT_ERRORS=false APP_LOCALE=en APP_FALLBACK_LOCALE=en APP_FAKER_LOCALE=en_US APP_MAINTENANCE_DRIVER=file # APP_MAINTENANCE_STORE=database BCRYPT_ROUNDS=12 LOG_CHANNEL=stack LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null # Use "debug" for development; use "warning" or "error" in production LOG_LEVEL=warning DB_CONNECTION=mysql DB_HOST="[[softdbhost]]" DB_PORT=3306 DB_DATABASE="[[softdb]]" DB_USERNAME="[[softdbuser]]" DB_PASSWORD="[[softdbpass]]" SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=true SESSION_PATH=/ # In hosted mode (IS_HOSTED=true) set to your base domain with a leading dot # (e.g. .yourdomain.com) so sessions span subdomains. If left unset, hosted # mode defaults it to the APP_URL base domain automatically. SESSION_DOMAIN=null # Set to false for local development without HTTPS SESSION_SECURE_COOKIE=true BROADCAST_CONNECTION=log FILESYSTEM_DISK=local QUEUE_CONNECTION=sync CACHE_STORE=file CACHE_PREFIX= MEMCACHED_HOST=127.0.0.1 REDIS_CLIENT=phpredis REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_MAILER=log MAIL_HOST=127.0.0.1 MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS="hello@example.com" MAIL_FROM_NAME="${APP_NAME}" AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false VITE_APP_NAME="${APP_NAME}" GEMINI_API_KEY= OPENAI_API_KEY= # AI provider selection (gemini or openai) AI_TEXT_PROVIDER=gemini AI_IMAGE_PROVIDER=openai # AI model selection (optional) # Translation models are used for batch translation tasks # Content models are used for interactive features (event parsing, AI details, style generation, blog posts) GEMINI_TRANSLATION_MODEL= GEMINI_CONTENT_MODEL= GEMINI_IMAGE_MODEL= OPENAI_TRANSLATION_MODEL= OPENAI_CONTENT_MODEL= OPENAI_IMAGE_MODEL= # Stripe Platform # Used for subscription billing (hosted mode) AND direct ticket payments (self-hosted mode) # In self-hosted mode, STRIPE_PLATFORM_KEY and STRIPE_PLATFORM_SECRET enable Stripe payments for ticket sales STRIPE_PLATFORM_KEY= STRIPE_PLATFORM_SECRET= STRIPE_PLATFORM_WEBHOOK_SECRET= STRIPE_PRICE_MONTHLY= STRIPE_PRICE_YEARLY= STRIPE_ENTERPRISE_PRICE_MONTHLY= STRIPE_ENTERPRISE_PRICE_YEARLY= # Displayed plan prices. These must match the amounts on the Stripe Price objects above: # nothing reconciles them, so a mismatch means the site advertises one number and charges # another. Defaults live in config/services.php (9 / 90 / 29 / 290). # # A super-admin can override all four at /admin/settings without touching this file or # re-running config:cache. That override is display only, exactly as these are. Keep these set # anyway: revenue reporting (ARR, MRR) and renewal emails deliberately read the values here, so # that a marketing change cannot restate revenue that was already booked. STRIPE_PRICE_MONTHLY_AMOUNT= STRIPE_PRICE_YEARLY_AMOUNT= STRIPE_ENTERPRISE_PRICE_MONTHLY_AMOUNT= STRIPE_ENTERPRISE_PRICE_YEARLY_AMOUNT= # The currency those amounts are shown in, everywhere the app quotes its OWN price: the # marketing pages, the Plan tab, upgrade prompts and the JSON-LD offers. Also the fallback # currency for a new event whose schedule has no country set. # # A label, like the amounts above - what a customer is charged comes from the Stripe Price. # A super-admin can change it at /admin/settings, which overrides this. Defaults to USD. # PLATFORM_CURRENCY=USD # Retired price IDs, comma-separated. Stripe Prices are immutable, so changing a price means # creating a new one and pointing the four vars above at it. List the OLD ids here so # subscribers still billing on them keep the tier and term they pay for. Leave empty until # you have actually retired a price. STRIPE_LEGACY_PRICE_MONTHLY= STRIPE_LEGACY_PRICE_YEARLY= STRIPE_LEGACY_ENTERPRISE_PRICE_MONTHLY= STRIPE_LEGACY_ENTERPRISE_PRICE_YEARLY= # What the retired prices charge, as price_id:amount pairs, e.g. "price_abc:9,price_def:90". # Used for revenue reporting and renewal emails so grandfathered subscribers are not counted # at $0 or quoted the new price they are not paying. # # Env only, by design. This records what existing customers are actually being charged, keyed by # opaque Stripe ids, so it is never editable from the admin panel. STRIPE_LEGACY_PRICE_AMOUNTS= # Payfast Platform # Payfast is the dominant gateway in South Africa, where Stripe is not available. Setting all # three values below enables Payfast for ticket sales across every schedule on a selfhosted # install, the same way STRIPE_PLATFORM_KEY and STRIPE_PLATFORM_SECRET do for Stripe. # # These are a DEFAULT, never an override: a schedule owner who connects their own Payfast # account in Settings > Payment Methods keeps using it, and their money keeps reaching them. # Ignored in hosted mode, where each owner must connect their own account. # # The passphrase is optional at Payfast but required here - without one, the payment # notification signature is a plain MD5 that anyone could reproduce. PAYFAST_MERCHANT_ID= PAYFAST_MERCHANT_KEY= PAYFAST_PASSPHRASE= # Use Payfast's sandbox instead of live. Test payments look completely normal, so leave this # false unless you are testing. PAYFAST_SANDBOX=false # Restrict the checkout to ONE payment type, e.g. "ef" for Instant EFT. Leave empty to let # Payfast offer everything. Codes: cc dc ef cp ap sp gp mc mt ss zp mu nd pf rc ab sc mp PAYFAST_PAYMENT_TYPES= # What a new event's payment method starts on. Defaults to cash. Set this to the gateway your # install actually uses - e.g. payfast - so owners are not picking it by hand every time. It # only applies when the gateway is genuinely usable for that event (connected, and able to # settle the event's currency); anything else falls back to cash. DEFAULT_PAYMENT_METHOD= # White-label settings IS_HOSTED=false # Selfhosted installs are single user by default: the first account created is the # instance admin, and further sign-ups are blocked. Set to true to let anyone register. # Registered users can create their own schedules, so only enable this on a trusted # network. For real multi-tenant hosting use IS_HOSTED=true (self-hosted SaaS) instead. ALLOW_REGISTRATION=false APP_LOGO_DARK=/images/dark_logo.png APP_LOGO_LIGHT=/images/light_logo.png APP_MARKETING_URL=https://eventschedule.com SUPPORT_EMAIL=contact@eventschedule.com # The upstream Event Schedule app this install talks to: where shared translation # improvements are sent, and where federated events are published. Defaults to # eventschedule.com, so it only needs setting to point at a different network. #NEXUS_URL=https://eventschedule.com TRIAL_DAYS=365 # Custom dashboard links (optional) - up to 3 links shown in the admin sidebar # for all admins. A link only appears when BOTH its title and URL are set. # Works in both selfhosted and hosted (SaaS) deployments. CUSTOM_LINK_1_TITLE= CUSTOM_LINK_1_URL= CUSTOM_LINK_2_TITLE= CUSTOM_LINK_2_URL= CUSTOM_LINK_3_TITLE= CUSTOM_LINK_3_URL= # Exclude events/schedules from a country in marketing search (2-letter ISO code, e.g. "us"). Blank = no filter. SEARCH_EXCLUDE_COUNTRY= # Secret token for cron job endpoints (/release_tickets, /translate_data) APP_CRON_SECRET= # Trusted proxies - required when running behind a reverse proxy (Nginx/Apache/Cloudflare) # to avoid infinite HTTPS redirect loops. Set to * to trust all proxies, or a # comma-separated list of proxy IPs/CIDRs (e.g. 10.0.0.0/8,192.168.1.1). TRUSTED_PROXIES= # Twilio SMS (optional phone verification) TWILIO_SID= TWILIO_AUTH_TOKEN= TWILIO_FROM_NUMBER= # OneSignal push notifications (optional). When set, the app and visitors' # browsers communicate with OneSignal's servers and load OneSignal's SDK from # their CDN. Leave blank to disable push entirely (no SDK is loaded and no # external calls are made). Get these from the OneSignal dashboard. ONESIGNAL_APP_ID= ONESIGNAL_REST_API_KEY= # ONESIGNAL_SAFARI_WEB_ID= # only needed for legacy macOS Safari web push # Cookie consent banner. Normally shown only when something on the page actually needs # consent (Google Analytics via ANALYTICS_ID, ADS_ENABLED, STAY22_ENABLED). Set this to true # to show it anyway, which is what enables the 30-day UTM attribution cookies # (utm_params, utm_referrer_url, utm_landing_page) used to credit a signup or sale to the # link that brought the visitor. Those are written only after a visitor clicks Allow. # Left false, a bare install shows no banner and sets no non-essential cookies: attribution # still works within a single session, it just does not survive across sessions. COOKIE_CONSENT_BANNER=false # Monetization (optional, multi-tenant hosted installs only). Off by default. # When enabled, free-tier schedules' public pages can carry Google AdSense and/or paid # promotions bought by other schedules; paid schedules never show either. ADS_ENABLED is a # deploy-time gate that cannot be overridden from the admin panel - leave it false and the # feature does not exist. See https://eventschedule.com/docs/saas/monetization for the # consent and AdSense policy obligations this places on you as the operator. # # Turning promotions OFF at /admin/settings is safe at any time: campaigns stop serving and # the scheduled promo:sync keeps settling and refunding what is already paid for. Setting # ADS_ENABLED back to false, however, also stops promo:sync, so leave it true until any # outstanding campaigns have completed and refunded. ADS_ENABLED=false # The settings below are editable at /admin/settings once the feature is on; the values here # only supply the starting defaults. # ADSENSE_ENABLED=true # ADSENSE_PUBLISHER_ID=ca-pub-XXXXXXXXXXXXXXXX # ADSENSE_EVENT_SLOT_ID=XXXXXXXXXX # ADSENSE_PERSONALIZED=false # true opts into personalized ads; see the consent obligations # PROMOTIONS_ENGINE_ENABLED=true # NATIVE_PROMO_PRIORITY_OVER_PROGRAMMATIC=true # PROMOTIONS_NETWORK_CPM=2.00 # PROMOTIONS_NETWORK_CPC=0.25 # These have no admin-panel equivalent - they can only be set here. # # PROMOTIONS_CURRENCY is deliberately NOT tied to the platform currency picked at # /admin/settings: a promotion purchase is a live Stripe charge, and re-denominating one from a # dropdown documented as display-only is not something an admin should be able to do by accident. # PROMOTIONS_CURRENCY=USD # PROMOTIONS_MIN_BUDGET=5.00 # PROMOTIONS_MAX_BUDGET=1000.00 # a schedule's own trust limit can still be lower # PROMOTIONS_MAX_CONCURRENT=2 # live promotions per schedule # PROMOTIONS_FREQUENCY_CAP=3 # times a visitor sees the same promotion per day # PROMOTIONS_AUTO_APPROVE_AFTER=3 # approved campaigns before an advertiser skips review # PROMOTIONS_MIN_CTR=0.0002 # CPC campaigns below this are paused # PROMOTIONS_MIN_CTR_IMPRESSIONS=5000 # ...but only once they have this many impressions # PROMOTIONS_CACHE_TTL=300 # seconds the servable-campaign list is cached # PROMOTIONS_STATS_RETENTION_DAYS=400 # Stay22 accommodation map (optional). Independent of ADS_ENABLED: it applies to paid schedules # too, and each schedule may supply its own affiliate ID and keep the commission itself. # # STAY22_ENABLED is a deploy-time gate that cannot be overridden from the admin panel, because the # Content-Security-Policy is built from it on every request. Leave it false and the feature does not # exist: no frame host is allow-listed, and the per-schedule toggle is not even rendered. Changing it # requires regenerating the config cache (php artisan config:cache). # # The map never loads until a visitor either has accepted cookies or explicitly clicks to show it. # See https://eventschedule.com/docs/saas/monetization for the disclosure obligations this places on # you as the operator. STAY22_ENABLED=false # Fallback affiliate ID, used for schedules that enabled the map but did not add their own. Editable # at /admin/settings once the feature is on; the value here only supplies the starting default. # Never used on a customer's own custom domain. # STAY22_AID= # STAY22_MAX_NIGHTS=30 # upper bound on the derived stay length # Tickets # How many options the guest quantity dropdown offers for a ticket with no "Max Per Order" # of its own. Clamped to 1-100. Not a purchase limit: checkout enforces only the ticket's # own max per order and its remaining stock. # MAX_TICKETS_PER_ORDER=20 # DigitalOcean App Platform (optional custom domain provisioning) DO_API_TOKEN= DO_APP_ID= DO_APP_HOSTNAME= # Cloudflare Turnstile (optional bot protection) TURNSTILE_SITE_KEY= TURNSTILE_SECRET_KEY= # Web accessibility (optional overrides; see config/accessibility.php) # ACCESSIBILITY_CONTACT_EMAIL=accessibility@example.com # ACCESSIBILITY_WCAG_TARGET_LABEL="WCAG 2.1 Level AA" # ACCESSIBILITY_REFERENCE_IS_5568=true # ACCESSIBILITY_RESPONSE_SLA_BUSINESS_DAYS=10 # ACCESSIBILITY_LAST_REVIEWED=2026-05-03