How Themes Work
Section titled “How Themes Work”FOSSBilling uses Twig for templating. Themes work by overriding the templates shipped by modules:
- Module provides a default template (
modules/Example/templates/client/mod_example_index.html.twig) - Your theme provides an override with the same filename (
themes/mytheme/html/mod_example_index.html.twig) - FOSSBilling uses your theme's version
Template Priority Order
Section titled “Template Priority Order”FOSSBilling loads templates in this order (highest priority first):
themes/mytheme/html_custom/— User customizationsthemes/mytheme/html/— Your theme filesmodules/Example/templates/client/ormodules/Example/templates/admin/— Module defaults for the current area
Theme Structure
Section titled “Theme Structure”themes/mytheme/├── assets/ # CSS, JS, images│ ├── css/│ ├── js/│ └── img/├── config/│ └── settings.html.twig # Theme settings UI (optional)├── html/ # Your templates│ ├── layout_default.html.twig # Base layout│ ├── layout_public.html.twig # Public pages layout│ ├── partial_menu.html.twig # Shared partial│ └── mod_index_dashboard.html.twig # Optional module override├── html_custom/ # For user customizations (leave empty)└── manifest.json # Theme metadataManifest File
Section titled “Manifest File”{ "name": "My Theme", "description": "A custom FOSSBilling theme", "version": "1.0.0", "author": "Your Name", "author_url": "https://example.com", "icon": "icon.png"}API URLs and CSRF
Section titled “API URLs and CSRF”Use api_url to build browser API URLs and fb_api_form or fb_api_link to let the JavaScript API wrapper handle submissions.
<form action="{{ 'profile/update'|api_url }}" {{ fb_api_form({ message: 'Profile updated'|trans }) }}> <input type="text" name="first_name" value="{{ profile.first_name }}"> <button type="submit">{{ 'Save'|trans }}</button></form>For links that trigger API actions:
<a href="{{ 'client/group_delete'|api_url(query: { id: group.id }, role: 'admin') }}" {{ fb_api_link({ modal: { type: 'confirm', title: 'Are you sure?'|trans }, reload: true }) }}> {{ 'Delete'|trans }}</a>Session-authenticated client and admin browser API calls require CSRF protection. The JavaScript API wrapper reads the csrf_token cookie and sends the token automatically.
Use role: 'guest' for public actions such as login, signup, and password reset:
<form action="{{ 'client/login'|api_url(role: 'guest') }}" {{ fb_api_form({ redirect: '/'|url }) }}> <input type="email" name="email" required> <input type="password" name="password" required> <button type="submit">{{ 'Login'|trans }}</button></form>Server-Side API Globals
Section titled “Server-Side API Globals”The guest, client, and admin Twig globals call FOSSBilling APIs during server-side template rendering. They are not browser HTTP requests and do not use CSRF tokens.
Guest API (always available)
Section titled “Guest API (always available)”{{ guest.currency_get_pairs }}{{ guest.system_version }}Client API (when logged in)
Section titled “Client API (when logged in)”{{ client.invoice_get_list({ 'per_page': 10 }) }}Admin API (when logged in)
Section titled “Admin API (when logged in)”{{ admin.staff_group_get_pairs }}{{ admin.extension_config_get({ 'ext': 'mod_seo' }) }}Twig Filters and Functions
Section titled “Twig Filters and Functions”FOSSBilling provides custom filters for themes:
{{ price | format_currency(currency.code) }} {# Format currency #}{{ 'client/manage' | url(area: 'admin') }} {# Admin panel link #}{{ 'css/theme.css' | asset_url }} {# Theme asset URL #}{{ date | timeago }} {# "2 hours ago" #}{{ content | markdown_to_html }} {# Parse Markdown #}Security Best Practices
Section titled “Security Best Practices”- Use
htmlspecialcharswhen outputting user data - Validate all inputs
- Use
fb_api_formandfb_api_linkfor browser API actions - Include CSRF tokens manually for raw requests that do not use the wrapper
- See the security docs for more
Testing Your Theme
Section titled “Testing Your Theme”- Place your theme in
/themes/mytheme/ - Go to Settings → Themes in the admin panel
- Select and activate your theme
- Check both client and admin areas
- Test on different screen sizes