Installation & Admin Guide
Complete reference for installing and configuring the radio directory. No terminal commands required.
1 — Requirements
- Web server: Apache or Nginx
- PHP: 8.2 or higher
- MySQL or MariaDB database
- Required PHP extensions: bcmath, ctype, fileinfo, json, mbstring, openssl, PDO, pdo_mysql, tokenizer, xml, curl, gd
- Hosting panel access (cPanel, Plesk, or similar) for file upload and database import
2 — Installation Steps
- Upload all project files to your hosting account (public_html or a subdirectory).
- Create a new, empty MySQL database and a database user from your hosting panel. Note the host, database name, username, and password.
- Import the provided database.sql backup file into that database using phpMyAdmin or your hosting panel's import tool.
- Open the .env file in a text editor and fill in the database and mail settings (see Section 3).
- Make sure your domain or subdomain points to the correct folder.
- Visit your domain — the homepage should load. Then open the admin login URL to confirm the panel is accessible.
Application Folder Location (lapp folder)
The main index.php in the root supports a configurable application path via $lapp_folder. Default value is /lapp.
| Option | Description |
|---|---|
| Run from web root (default) | Application folder is under public root (example: public_html/lapp) and root index.php points to it. |
| Run from one level above web root | Keep only public files in web root and place the Laravel app folder outside public root (if your hosting/server allows this). |
How to Run One Level Above Web Root
- Find your active web root in the hosting panel (for example: public_html, httpdocs, www, or domain root).
- Move the Laravel application folder (lapp) to the parent directory of the web root.
Example structure: /home/account/lapp and /home/account/public_html. - In web root index.php, update $lapp_folder to point one level up.
Example: $lapp_folder = '../lapp'; - If your host blocks access to parent folders (open_basedir or similar restrictions), ask hosting support to allow this structure or provide an alternative secure deployment method.
Required Security Check (.env)
After deployment, manually test whether the environment file is publicly reachable.
- Open https://yourdomain.com/lapp/.env in a browser (adjust the path if you changed folder names).
- This URL must not expose file contents. Expected result is 403, 404, or access denied.
- If the file content is visible, treat it as a critical security issue and contact your hosting provider to block direct access to dotfiles immediately.
3 — Required .env Values
Open the .env file at the root of the project in a plain text editor and set the values below.
Database
Mail (SMTP)
Admin Panel URLs (Security)
These two values control where the admin login page and panel are located. Change them from the defaults to reduce exposure to automated bots.
Application Key & Debug Mode
To generate a new key: log in to the admin panel and visit https://yourdomain.com/[ADMIN_URL]/regenerate_app_key (replace [ADMIN_URL] with the value you set in .env). The page will display a new key — copy it and paste it as the value of APP_KEY= in your .env file manually.
Note: After saving the new key, all active sessions (including yours) will be invalidated and everyone will need to log in again. Make sure you know your admin credentials before saving.
4 — First Login & Security
The default admin account shipped with the SQL backup has well-known credentials. Change them immediately after installation.
Default Admin Credentials
- Username (Email): [email protected]
- Password: admin123456
What to Change
| What to change | Where | Why |
|---|---|---|
| Admin password (default: admin123456) | Admin Panel → Account Settings | Bots and scanners try this password automatically |
| Admin email (default: [email protected]) | Admin Panel → Account Settings | Placeholder email — replace with a real address |
| Admin email in General Settings | Admin Panel → Settings → General → admin_email | Contact form messages are delivered to this address |
After changing credentials
- Go to Admin Panel → System Health.
- Confirm the security checks for password and email are green.
- Confirm APP_DEBUG is set to false (also shown in System Health).
5 — Admin Panel Access
The admin login URL is determined by the ADMIN_LOGIN_URL value in your .env file.
- If you set ADMIN_LOGIN_URL=secure-admin, the login page is at https://yourdomain.com/secure-admin.
- After logging in you will be redirected to the admin panel at the path set by ADMIN_URL.
- Bookmarks that worked before will stop working if you change these values — update any saved bookmarks after a change.
6 — General Settings
Location: Admin Panel → Settings → General
Site Identity
| Setting | Description |
|---|---|
| Site Language | Default language for the front-end interface |
| Theme | Color theme for the front-end |
| Meta Theme Color | Browser toolbar color on mobile devices |
| Site Title | Used in page titles and browser tab |
| Site Description | Default meta description for the homepage |
| Admin Email | Required for the contact form. Contact messages are sent to this address. |
Social Links
| Setting | What to enter |
|---|---|
| Twitter Account | Twitter/X username (without @) |
| Facebook Page | Full Facebook page URL |
| Telegram Page | Full Telegram channel URL |
Purchase Code
The purchase code is required for the API screen and related license checks. Add it in Admin Panel → Settings → General and use the Check Purchase Code & Sync button to validate it.
| Setting | What to enter |
|---|---|
| Purchase Code | Your license purchase code from Foxart |
Images
Upload images at the exact dimensions listed to avoid cropping or stretching.
| Image | Required Size |
|---|---|
| Logo | 600 × 148 px |
| Favicon | 192 × 192 px |
| Default Share Image | 600 × 315 px |
| Default Station Image | 300 × 300 px |
| Default Genre Image | 516 × 258 px |
Google reCAPTCHA
Protects the contact form and radio submission form from spam bots.
- Create a reCAPTCHA v2 site at google.com/recaptcha/admin.
- Copy the Site Key and Secret Key into the corresponding fields.
- Enable the toggle.
Other Toggles
| Toggle | Effect when enabled |
|---|---|
| Show Cookie Bar | Displays a cookie consent notification at the bottom of the page |
| Enable FAQ | Shows the FAQ section on the site; disable if unused |
| Radio Submission | Allows visitors to submit new radio stations; disable if you manage stations manually |
HTML Code Injection
Paste analytics scripts, ad codes, or custom HTML into these fields:
- Before </head> tag — analytics, tag manager head snippet
- After <head> tag — early-loading scripts or meta tags
- Before </body> tag — analytics body snippet, chat widgets
Pagination
| Setting | Description |
|---|---|
| Genres on Home Page | Number of genre cards shown on the homepage |
| Records per Page | Number of items per page in listings |
| Sitemap Records per Page | Stations per sitemap page (keep below 5 000) |
7 — Mail & Contact Form
The contact form requires two correctly set things to deliver messages:
| # | Where | What to set |
|---|---|---|
| 1 | .env file | MAIL_MAILER, MAIL_HOST, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD, MAIL_ENCRYPTION, MAIL_FROM_ADDRESS |
| 2 | Admin Panel → Settings → General | Admin Email field — messages are delivered to this address |
Testing Mail
- Go to Admin Panel → System Health.
- Find the Mail Health section — it shows your current SMTP settings.
- Click Send Test Mail and check the inbox of the admin email address.
- If the test mail arrives, contact form delivery is working.
Common SMTP Ports
| Port | Encryption | When to use |
|---|---|---|
| 587 | tls | Standard — recommended for most providers |
| 465 | ssl | Legacy SSL — use if your provider requires it |
| 25 | (none) | Unencrypted — not recommended, often blocked |
8 — Cron Job & Stream Check
Two background tasks keep the site updated automatically.
| Task | What it does |
|---|---|
| Cron Job | Runs scheduled application tasks (cache refresh, sitemap update, etc.) |
| Stream Check | Periodically checks each station's stream URL and marks unreachable stations |
Setup (No Terminal)
- Go to Admin Panel → Settings → General.
- Copy the Cron Job URL (read-only field).
- In your hosting panel, open the Cron Jobs section and add a new cron that calls this URL once per day (e.g., at midnight). Most cPanel hosts have a URL-based cron option that does not require SSH. Enter the frequency as:
0 0 * * *(daily at midnight). - Copy the Stream Check URL from the same page.
- Add a second cron job that calls the stream check URL at your preferred interval (e.g., once per hour). Enter:
0 * * * *(hourly). - The Stream Check Batch Size setting controls how many stations are checked per run — lower it if you have many stations to avoid timeouts.
Regenerating the Cron URL
A "Generate New Link" button is available next to the Cron Job URL field. Use this if you suspect the URL has been discovered by unauthorized users — existing cron jobs will need to be updated with the new URL.
Understanding Stream Checker Results
The stream checker makes a server-side HTTP request to each station URL and records whether it responded. This is not the same as a browser playing the stream, and the two can disagree for several reasons.
Why a working station may be marked as down:
| Cause | Explanation |
|---|---|
| Hosting firewall blocks outbound connections | Some shared hosts restrict what external IPs the server can reach. The checker's own request never leaves the server. |
| Station blocks the server's IP or country | The radio server may geo-block or IP-ban certain ranges. The checker gets rejected even though end-users can connect normally. |
| Missing User-Agent or Referer header | Some stream servers require a browser-like User-Agent or a specific Referer header. The checker sends a plain PHP request, which can be refused. |
| Transient outage during check | If the station dropped for a few seconds exactly when the checker ran, it gets marked down even though it came back immediately. |
| PHP timeout mid-batch | If max_execution_time or memory_limit is too low, the checker process is killed mid-batch and remaining stations never receive a result. |
| Expired or self-signed SSL certificate | PHP's curl rejects HTTPS streams whose certificate is invalid, so a live station with a bad cert is reported as unreachable. |
Why a station marked as working may not play in the browser:
| Cause | Explanation |
|---|---|
| CORS not allowed | The radio server does not send an Access-Control-Allow-Origin header. Browsers block the cross-origin audio request — the server-side checker is unaffected. |
| HTTP stream on an HTTPS site (Mixed Content) | Browsers refuse to load http:// media on a page served over https://. The checker does not enforce this rule. |
| Maximum listener limit reached | The radio server is full. It still responds to the checker's quick probe but refuses the actual audio stream connection. |
| Geo or IP restriction for end users | The checker may run from a different country or IP range that is not blocked, while the listener's country is. |
| Unsupported codec | The stream uses a codec the visitor's browser does not support (e.g., certain AAC profiles, Ogg Vorbis in some browsers). The URL is valid but the audio cannot be decoded. |
| Browser autoplay policy | Browsers can block audio that starts without a user gesture. This is a browser-side rule; the stream itself is fine. |
| Ad blocker or browser extension | The stream domain may appear on a blocklist used by an ad-blocker or privacy extension installed by the visitor. |
| Network or ISP filtering | The visitor's network (corporate firewall, ISP, or country-level block) may block the stream port (e.g., 8000, 8080) or domain entirely. |
9 — SEO & URL Structure
Location: Admin Panel → Settings → SEO
URL Base Paths
These values define the path segment in every URL on the site. For example, setting station_base to radio makes station URLs look like /radio/station-name.
| Setting Name | URL Path | Affects |
|---|---|---|
| station_base | e.g. /radio/station-name | Individual station pages |
| genre_base | e.g. /genres/rock | Genre listing pages |
| country_base | e.g. /countries/usa | Country listing pages |
| language_base | e.g. /languages/english | Language listing pages |
| page_base | e.g. /pages/about | Static pages (About, Terms, etc.) |
| post_base | e.g. /news/article-title | Blog posts |
| latest_stations_base | e.g. /new-stations | Latest stations page |
| browse_genres_base | e.g. /browse-by-genre | Browse all genres page |
| browse_countries_base | e.g. /browse-by-country | Browse all countries page |
| browse_languages_base | e.g. /browse-by-language | Browse all languages page |
| history_base | e.g. /my-history | Recently played history page |
| favorites_base | e.g. /my-favorites | Favorites/bookmarked stations page |
| blog_slug | e.g. /blog | Blog index/list page |
| contact_slug | e.g. /contact | Contact/feedback form page |
| faq_slug | e.g. /faq | FAQ (Frequently Asked Questions) page |
| submission_slug | e.g. /submit-station | Radio station submission page |
Meta Title / Description Templates
Each page type has its own title and description template. These templates support shortcodes (e.g., {station_name}, {genre_name}) that are replaced automatically when the page is rendered. Edit them to match your site's branding and target keywords.
No-Index Options
- No-Index History Page — prevents search engines from indexing the recently-played page (recommended, as the content changes constantly)
- No-Index Favorites Page — prevents indexing of the favorites page (recommended, as it is user-specific)
10 — PWA Settings
Location: Admin Panel → Settings → PWA
Progressive Web App (PWA) allows visitors to install the site as an app on their mobile device or desktop.
Enabling PWA
- Toggle Enable PWA to on.
- Fill in all required fields before enabling — an incomplete PWA configuration can trigger browser warnings.
Required Fields
| Field | Description |
|---|---|
| PWA Name | Full app name shown during installation and in app lists |
| PWA Short Name | Short name (≤12 characters) shown on home screens |
| PWA Description | Description of the app |
| Theme Color | Hex color for the browser UI elements when the app is open |
| Background Color | Hex color shown on the splash screen during app launch |
Icons (Required Sizes)
| Icon | Size | Used for |
|---|---|---|
| App Icon (large) | 512 × 512 px | App stores, high-res displays |
| App Icon (medium) | 192 × 192 px | Home screen shortcut |
| App Icon (small) | 48 × 48 px | Task switcher |
| App Icon (tiny) | 24 × 24 px | Notification tray |
| Screenshot | 1080 × 1920 px | Install prompt preview |
Installation Behavior
PWA installation is handled by the browser and is not guaranteed to appear as a popup or message.
- Installation options are usually available through the browser menu or toolbar when the site is eligible.
- On Android, the install option may appear in the browser menu.
- On iOS, installation is only available via Safari using “Add to Home Screen”.
- On desktop browsers, installation availability depends on browser support and user state.
The install option is not shown as a fixed UI element and may vary depending on browser, device, and user context.
11 — Content Management Order
Add content in the order below to avoid missing dropdown values when creating stations.
-
Countries — Admin Panel → Countries
Add all countries that your stations will be associated with. -
Languages — Admin Panel → Languages
Add broadcast languages before creating stations. -
Genres — Admin Panel → Genres
Create genres so stations can be categorized correctly. -
Stations — Admin Panel → Stations
Add stations with stream URL, country, language, and genre assigned. -
Static Pages & FAQ — Admin Panel → Pages / FAQs
Create About, Privacy Policy, Terms pages, and any FAQ entries. -
Blog Posts — Admin Panel → Blog
Optional. Add articles or news related to your stations. -
Ads — Admin Panel → Ads
Set up advertisement zones after content is live.
12 — Extra Features
Embed Shortcodes (Cross-Content Blocks)
You can embed radio stations and blog posts inside other content areas by using shortcodes. The system converts these shortcodes into a styled preview card (image + title + link) on the frontend.
| Shortcode | Embeds | Example |
|---|---|---|
r(ID) | A radio station by ID | r(125) |
b(ID) | A blog post by ID | b(42) |
Where It Works
- Stations → Details field
- Blog → Content field
- Pages → Content field
Usage Examples
You can place shortcodes inline with text or on their own line:
| Input in Editor | Result on Site |
|---|---|
Check this station: r(125) | Inline station embed card appears at that position |
Related article: b(42) | Inline blog embed card appears at that position |
r(125) b(42) | Both cards are rendered in order |
Important Rules
- Use normal parentheses and only numeric IDs:
r(10),b(99). - The referenced content must exist and be published (status = 1).
- If an ID does not exist or is not published, the shortcode is left unchanged as plain text.
- URLs in embeds follow your SEO base settings: station_base and post_base.
- If no image is set, default fallback images are used automatically.
13 — Moderation
Submissions
Location: Admin Panel → Submissions
When the Radio Submission toggle is enabled in General Settings, visitors can submit new stations. Submitted stations appear here for review. You can approve, edit, or delete each submission before it becomes visible on the site.
Comments
Location: Admin Panel → Comments
Visitor comments on stations and blog posts appear here. Review and approve or remove comments as needed.
Reports
Location: Admin Panel → Reports
Visitors can flag a station as having a broken stream or incorrect information. Reports appear here so you can investigate and update the station or dismiss the report.
14 — System Health
Location: Admin Panel → System Health
This page provides a real-time overview of the application's configuration and environment. Check it after installation and after any major configuration change.
| Check | What it verifies |
|---|---|
| Outbound HTTPS | The server can reach external URLs (needed for stream checks and API calls) |
| Default Password | Red if the admin password is still admin123456 |
| Default Email | Red if the admin email is still [email protected] |
| APP_DEBUG | Red if debug mode is on in production |
| Mail Health | Shows current SMTP settings and provides a test mail button |
| PHP Extensions | Lists all required extensions with pass/fail status |
| Cron Last Run | Timestamp of the last successful cron job execution |
| Stream Check Last Run | Timestamp of the last stream health check |
| PHP Limits | memory_limit, max_execution_time, upload_max_filesize, post_max_size |
15 — Troubleshooting
| Problem | Likely Cause | Fix |
|---|---|---|
| Website does not open | Wrong document root or domain not pointed | Check domain DNS and hosting document root setting |
| Admin panel or links do not work | Missing .htaccess in the main domain root, or invalid rewrite rules inside it | Upload the root .htaccess file and verify its contents match the package default. If needed, ask your hosting provider to enable rewrite rules (Apache mod_rewrite) |
| Database connection error | Wrong DB_HOST, DB_DATABASE, DB_USERNAME, or DB_PASSWORD | Re-check these four values in .env; confirm the user has access to the database |
| Contact form not sending | Wrong SMTP settings or missing admin_email | Fix MAIL_* in .env, set admin_email in General Settings, use test mail in System Health |
| Radio does not play | Invalid stream URL, server firewall, or CORS issue | Test the stream URL directly in a browser; check if your server allows outbound connections on the stream port |
| Cron "Never Run" in System Health | Cron job not added or URL incorrect | Re-copy the cron URL from General Settings and re-add the cron job in your hosting panel |
| Stream Check "Never Run" | Stream check cron job not set up | Add a separate cron job for the stream check URL (also from General Settings) |
| Red security warning in System Health | Default credentials still active | Change admin password and admin email in Account Settings immediately |
| Images not uploading | PHP upload_max_filesize or post_max_size too low | Increase these limits in your hosting PHP settings (System Health shows current values) |
| Blank white page | APP_DEBUG=false hides errors | Temporarily set APP_DEBUG=true (on a local copy only), reproduce the error, then set it back to false |
Information to Include in a Support Request
- Domain name and PHP version
- What you were doing when the issue occurred
- Screenshot of any error message
- List of problematic items from the System Health page (red/warning entries)