Documentation

Owner's manual

This is the documentation every Fortesonic license ships with — read it before you buy, use it after. If it isn't answered here, email us.

1. Installation & requirements

Fortesonic is built on a minimalist, high-performance flat-file philosophy. There is no installer wizard because none is needed.

  • Zero database. No MySQL, PostgreSQL or Redis. All dynamic data comes from JSON APIs (AzuraCast, iTunes, Open-Meteo) at request time.
  • No Node.js on the server. The frontend is pure vanilla JavaScript, CSS and HTML — nothing to build, nothing to npm install.
  • Plain PHP 8+. PHP is used only for shared includes and safe server-side cURL requests (which also solves CORS for you). HTTPS and the cURL extension are the only host requirements.

Install via FTP or cPanel

1. Unzip the downloaded package on your computer.
2. Open your FTP client (FileZilla) or cPanel File Manager.
3. Connect to your hosting and open the web root (public_html / www).
4. Drag and drop all files and folders into the web root.
5. Done. The site is live — now connect your stream (next section).

Works on ordinary shared hosting — if your host runs PHP 8+ with HTTPS, you're covered.

Preview: installing Fortesonic by dragging files to public_html over FTP
Installation is a drag & drop — copy the package to public_html and the site is live.

2. Configuration

Almost everything is managed in a single file: js/app.js. You never need to edit HTML or CSS to change your stream, station name, colors or features.

Where to find your AzuraCast data

  • Now Playing API URL — log into your AzuraCast panel, open your station dashboard and look for the “Now Playing API” link. It looks like https://your-server.com/api/nowplaying/your_station.
  • Stream URLs — under Broadcasting → Mount Points, right-click the Download/Play button of a mount point and copy the link. Create multiple mount points (320/128/64 kbps) to enable the quality switcher.
const AppConfig = {
    STREAM_URL: 'https://your-server.com/listen/station/radio.mp3',
    API_URL:    'https://your-server.com/api/nowplaying/your-station',

    COLORS: {
        light: { background: '#f6f8f9', text: '#000000', /* ... */ },
        dark:  { background: '#20232e', text: '#ffffff', /* ... */ }
    },

    HISTORY_COUNT: 6,          // Recently Played count
    REFRESH_INTERVAL: 15000,   // now-playing poll, ms
    MAINTENANCE_MODE: false
};
Preview: Fortesonic main player in dark theme
The result after configuration — your player with live cover art, metadata pills and equalizer.

Feature toggles

Turn whole features on or off with booleans in the same file:

  • SHOW_MAP — the Global Reach listener map section.
  • SHOW_REQUESTS — the Request a Track block, modal and footer action.
  • SHOW_LISTEN_IN_PLAYER — downloadable player playlist links (.pls).
  • CHAT_ASSISTANT_ENABLED — the listener assistant widget.
  • SCHEDULE_CURATED_LOOKAHEAD_HOURS / RADIO_SHOW_LOOKAHEAD_HOURS — how far the Curated Selections and Radio Shows calendars look ahead (24 = today, 48 = +tomorrow).
  • HISTORY_COUNT — base Recently Played count; the list grows automatically when sidebar sections are hidden.

Full configuration reference

The toggles above are the ones most people touch. For completeness, here is the whole AppConfig object grouped by purpose — every key is documented inline in js/app.js:

const AppConfig = {

    // Player & stream
    STREAM_URL, API_URL, QUEUE_URL, LISTENERS_URL,
    DEFAULT_VOLUME, AUTOPLAY, REFRESH_INTERVAL,

    // Requests & sharing
    REQUESTS_URL, REQUEST_SUBMIT_URL, SHARE_MESSAGE,

    // Schedule & podcasts
    SCHEDULE_PLAYLISTS_URL, PODCASTS_URL,
    SCHEDULE_CURATED_LOOKAHEAD_HOURS, RADIO_SHOW_LOOKAHEAD_HOURS,
    SCHEDULE_COUNTDOWN_THRESHOLD_MINUTES, SCHEDULE_LIVE_LABEL,

    // History & section visibility
    HISTORY_COUNT, HISTORY_LAYOUT_COUNTS,
    SHOW_MAP, SHOW_REQUESTS, SHOW_LISTEN_IN_PLAYER,
    SHOW_HEADER_SECTION, SHOW_HEADER_WEATHER, SHOW_HEADER_THEME,
    SHOW_HEADER_POPUP, SHOW_HEADER_TV_MODE,

    // Styling & branding
    COLORS, QUALITY_LABELS, LOGO, COVER_PLACEHOLDER_LETTER,
    COVER, COVER_INFO_TICKER_SPEED,

    // UI & features
    ANIMATIONS, STATIC_PLAYER_LABELS, CHAT_ASSISTANT_ENABLED,
    INSTAGRAM_FOLLOW_URL, INSTAGRAM_FOLLOW_WIDGET_ENABLED,
    MAINTENANCE_MODE
};

Colors, quality labels and logo sizing are objects with their own sub-keys — open js/app.js to see the full shape and defaults.

3. Integrations & APIs

Everything below works out of the box — no paid API keys required.

  • AzuraCast Now Playing — the core data source, polled every 15 seconds for track, artwork, listeners and stream metadata.
  • iTunes + Song.link (Odesli) — resolves universal listen links (Spotify, Apple Music, YouTube Music, Deezer…) per track. Results are cached in the browser to respect API limits.
  • Schedule & podcasts — the local API proxy exposes AzuraCast playlist schedules and podcast episodes; the frontend renders Curated Selections with live countdowns and the latest Radio Show episode.
  • GetSongBPM / Key (optional) — server-side enrichment for tempo and musical key pills; falls back to your stream metadata when unset.
  • Open-Meteo — privacy-first local weather widget, no tracking.
  • Flagpedia — country flags for the listener map.
Preview: Fortesonic broadcast history page
Broadcast History — the 24-hour archive with artwork and universal platform links per track.

Not a developer? Let AI configure it

Copy this prompt into ChatGPT, Claude or Gemini together with your station details, and paste the result into js/app.js:

"I purchased the Fortesonic radio platform. Help me configure js/app.js.

My station details:
- AzuraCast Now Playing JSON URL: [YOUR JSON API URL]
- High quality (320kbps) stream URL: [YOUR 320kbps URL]
- Low quality (64kbps) stream URL: [YOUR 64kbps URL]

Generate the exact AppConfig object to replace in js/app.js.
No explanation needed - just the finalized object to copy-paste."

Guided setup with an AI agent

Working in an AI coding agent instead (Claude Code, Cursor, Windsurf…) with the unzipped package open? Paste this — the agent will interview you step by step and apply your answers for you:

"You are my setup assistant for the Fortesonic radio platform I purchased.
The package is unzipped in this project folder. Guide me through the setup
step by step - one question at a time, and never invent values for me.

1. Check the install: confirm the files are in the web root and the host
   runs PHP 8+ with HTTPS. If not, walk me through the FTP/cPanel upload.
2. Connect my station: ask me for my AzuraCast Now Playing API URL and my
   stream mount URLs (320/128/64 kbps), then put them into js/app.js.
3. Optional extras: ask if I have a GetSongBPM key and whether I want the
   listener assistant (chatbot) enabled.
4. Walk me through every true/false toggle in the AppConfig object in
   js/app.js one by one: explain in one sentence what it shows, ask me
   yes or no, and set it accordingly (SHOW_MAP, SHOW_REQUESTS,
   SHOW_LISTEN_IN_PLAYER, the SHOW_HEADER_* toggles, AUTOPLAY,
   ANIMATIONS, CHAT_ASSISTANT_ENABLED...).
5. Only edit js/app.js (and .env for the chatbot switch). Show me every
   change before you save it. Anything beyond that - design, CSS, server
   config - point me to the documentation instead of changing it."

The agent configures — you decide. It installs the basics, adds your own URLs and keys, and switches features on or off exactly as you answer.

4. Player features

Beyond play/stop, the player ships a set of listener-facing extras. Each one is either on by default or gated behind a single AppConfig toggle, so you decide what your audience sees.

TV mode

A full-screen “lounge” display — giant cover art, live status and Up Next, nothing else. Perfect for a screen in a bar, studio or waiting room. Toggled with SHOW_HEADER_TV_MODE; listeners enter from the header button and leave with Esc.

Sleep timer

A countdown dropdown — 15, 30 or 45 minutes, or 1 hour (plus Off to cancel) — that gently fades the volume down over the final stretch and then stops the stream, so listeners can fall asleep to the radio without it running all night. When it stops, a dismissible notice confirms it (“Good night”) and the fade-start volume is restored, so the next play never begins silent. The countdown is remembered in the browser, so it keeps running even if the listener reloads the page or moves around the app shell. On by default; no configuration needed.

Quality switcher

A dropdown fed by your AzuraCast mount points (320 / 128 / 64 kbps and anything else you create). QUALITY_LABELS sets the human-readable text per bitrate, and the listener's choice is remembered in the browser between visits.

Lock-screen & hardware controls (MediaSession)

Using the browser MediaSession API, the current cover art, title and artist appear on the phone lock screen and in the OS media panel, and the hardware play/pause and media keys control the stream. No configuration required — it works wherever the browser supports it.

Pop-out player

Gated behind SHOW_HEADER_POPUP: opens the player in a small dedicated window (about 450×700) that keeps playing while the listener browses other sites. The header button spawns it; closing the window stops that instance.

Listener map & weather

  • Global Reach map (SHOW_MAP) — country flags with live listener counts pulled from AzuraCast. Listener coordinates are rounded before display, so the map shows reach without pinpointing anyone.
  • Local weather (SHOW_HEADER_WEATHER) — a privacy-first widget powered by Open-Meteo with no tracking and no API key.

5. Listener assistant

The chatbot ships as an isolated plugin under ai/chatbot/, loaded through one include line in inc/footer.php. It answers from a local knowledge base on your server — no OpenAI account, no API keys, no per-message costs. Unknown questions get a controlled fallback instead of an invented answer.

Enable / disable

  • CHAT_ASSISTANT_ENABLED: false in js/app.js — hides the widget.
  • RADIO_CHAT_ENABLED=false in .env — disables the widget and the endpoint.
  • Remove the include line from inc/footer.php — removes it completely.

Edit ai/chatbot/knowledge.php to teach it about your station: shows, hosts, how to request songs, contact info.

Preview: Fortesonic listener assistant chat widget
The listener assistant — a floating chat widget answering from your local knowledge base.

6. App Shell & PWA

Fortesonic keeps the live stream alive while listeners move between internal pages: eligible links swap only the content region, so the audio engine is never destroyed by a reload. A compact mini player appears on subpages and follows the same play/stop state as the main player.

Preview playback rules

  • Recently Played and Broadcast History rows offer 30–60s previews.
  • If the live stream is playing, a preview pauses it and resumes it afterwards.
  • Up Next never renders preview controls (you can't preview the future).
Preview: Fortesonic on a phone with PWA install prompt
Installed as a PWA on the phone home screen.
Preview: Fortesonic TV mode full-screen display
TV mode — the full-screen lounge display.

PWA cache versioning

When you customize cached JS/CSS assets, bump CACHE_NAME in assets/pwa/service-worker.js (convention: radio-vNN) so installed apps pick up your changes.

7. Mobile UX & popups

The mobile layout is tuned separately: 50/50 Quality and Sleep dropdowns below the play controls, centered request button, and touch targets sized for thumbs.

Popup sequence

1. Visitor lands on the page.
2. Cookie consent banner slides up after 1 second.
3. On "Got it!" (or after 6s) the consent cookie is saved for 365 days.
4. 3 seconds later, phones see the Data Saver banner:
   the player switched to 64 kbps to save bandwidth.
   It auto-hides after 12s; the choice is remembered for 30 days.
Preview: cookie consent and data saver banners on a phone
The polite popup sequence on phones — cookie consent first, then the data-saver notice.

8. Security & server config

  • XSS prevention — all API strings (artist, title) are sanitized before touching the DOM.
  • Rate limiting + CSRF — song requests and the assistant endpoint are rate-limited per client (by IP address and per endpoint scope) inside a rolling time window, returning a 429 when the limit is exceeded. Every write is checked for a matching origin/referer before it runs.
  • Fail-safes — if the stream API goes offline, the UI switches to a clean offline state instead of spamming errors.

The included .htaccess handles

  • Force HTTPS + HSTS (AutoSSL validation paths excluded).
  • www → non-www redirect against duplicate indexing.
  • Clean URLs — /impressum loads impressum.php.
  • GZIP/deflate compression and 1–12 month browser caching for static assets.
  • Custom 404 routing to the styled 404.php template.
Preview: Fortesonic security layer — HTTPS, HSTS and hardened headers
The security layer ships configured — HTTPS, HSTS, clean URLs and hardened headers out of the box.

Ready to put your station on air?

One license, live in minutes. Installation (49 €) and CDN setup are add-ons on the order form.

Order Fortesonic — from 99 €

Questions? maestro@fortesonic.com