Skip to main content

simple_module_branding

Customisable application branding for simple_module_python apps.

An administrator can set the application name, logo (plus an optional dark-background variant), favicon and primary brand colour from the admin UI (/branding), and those values are applied everywhere the framework would otherwise show the default identity — the sidebar/header logo and name, the browser tab title, the favicon, and the primary accent colour.

Screenshots

The admin page at /branding, and the same app rebranded as "Acme Analytics" (custom logo + name + primary colour) across the sidebar and dashboard:

Admin page Branding applied Across the app
Branding admin Branding applied Branded dashboard

Install

The module ships with the default app. To add it to a custom host, declare it as a dependency and let entry-point discovery pick it up:

# host/pyproject.toml
dependencies = ["simple_module_branding"]

[tool.uv.sources]
simple_module_branding = { workspace = true }

Then uv sync --all-packages. It requires the Settings and FileStorage modules to be installed too.

Usage

  1. Sign in as an admin and open Branding in the sidebar (or visit /branding).
  2. Set the application name, pick a primary colour, and upload a logo and/or favicon. Changes apply immediately across the app.

Programmatically, the current branding is available on every page through the branding Inertia shared prop (appName, primaryColor, designPack, logoUrl, logoDarkUrl, faviconUrl, banner). banner is null when unconfigured, which makes the frontend render nothing. Footer content is owned by the framework site layouts rather than branding. For a dark surface use darkSurfaceLogo(branding) from @simple-module-py/ui/lib/brand, which applies the logoDarkUrl → logoUrl fallback in one place.

How it works

  • Storage. The four values are persisted via the settings module's store (SYSTEM scope) — there is no branding database table. They hydrate into app.state.branding.settings at boot and hot-swap on save.
  • Images. Logo and favicon uploads are stored through the file_storage module (referenced by UUID). Branding serves them back from its own anonymous routes, GET /api/branding/logo and GET /api/branding/favicon — file_storage's download endpoint requires file-storage.download, which no logged-out visitor has, and the sign-in page is exactly where the logo must appear. Only the two ids currently held in branding settings are served, so this is not a way to read arbitrary files. Uploading and clearing on those same paths stay behind branding.manage (the exemption is GET-only).
  • Caching. The published URL carries ?v=<file id>; a replaced image is a new file_storage id, so the URL is content-addressed. Versioned requests are served public, max-age=31536000, immutable; a request without a usable version gets public, max-age=3600 so it self-corrects, and a 404 is never cached.
  • Announcement banner. A message plus a severity (info / warning / danger) rendered above every shell — app, public and auth — because an outage notice is most useful to people who cannot sign in. An empty message hides it. Severity colours are semantic, not brand-tinted: a warning wearing the deployment's accent colour stops reading as a warning.
  • Presets. One-click looks (POST /api/branding/presets/{key}), applied through the ordinary update path so every validator still runs. A preset only ever sets appearance (PRESET_FIELDS — primary colour, design pack); it can never overwrite the app name, an uploaded logo or a live banner, and BrandingPreset rejects any other field at construction.
  • Dark-background logo. The sidebar and mobile bar sit on a near-black surface in every theme, while the sign-in card and public page are light — so a single logo cannot read on both. Uploading a Logo (dark backgrounds) variant swaps it in on those surfaces only. It is optional: with none set the shared prop reports logoDarkUrl: null and the frontend falls back to logoUrl, so single-logo deployments look exactly as they did.
  • Lifecycle. Replacing or clearing an image deletes the file it stopped referencing, so repeated logo tweaks don't leave orphans in file_storage. Cleanup is best effort: the setting change has already been persisted, so a storage fault is logged rather than failing an otherwise-successful rebrand.
  • Upload validation. PNG, JPEG, WEBP, GIF and ICO up to 2 MB. The declared content-type is caller-controlled, so the first bytes are also checked against each format's magic number — a payload renamed logo.png is rejected. SVG is excluded on purpose: it is an XML document that can carry <script>, so serving one from the app's origin would be stored XSS.
  • Delivery. A registered Inertia shared-props provider injects a branding block into every page's shared props (authenticated and guest), which the frontend reads for the name, logo, favicon and colour.

Permissions

  • branding.view — view the branding admin page.
  • branding.manage — change branding (name, colour, logo, favicon).

The logo and favicon GET routes are anonymous by design (registered through the register_public_routes hook); everything else requires a permission.

Dependencies

Depends on the Settings and FileStorage modules.

Notes

  • Branding is currently SYSTEM-scoped (one identity per deployment). The settings store already supports tenant/user scope, leaving room for per-tenant branding later.
  • The primary colour overrides the --primary / --sidebar-primary CSS variables from a single hex; the full OKLCH colour scale is not regenerated.

License: MIT

Metadata

Release files for simple-module-branding 0.0.35

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for simple-module-branding 0.0.35
File Size Uploaded Provenance
simple_module_branding-0.0.35.tar.gz 46.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for simple-module-branding 0.0.35
File Interpreter ABI Platform
simple_module_branding-0.0.35-py3-none-any.whl Python 3 none any Details

Total release size: 90.7 kB

Release files / simple_module_branding-0.0.35.tar.gz

Download URL simple_module_branding-0.0.35.tar.gz
Size 46.4 kB
Tags Source
SHA-256 checksum
How to use checksums
2c52f6a6c038ac5165d2e176dc3c28cedfe2c30c4694242c4c25d32aa060d158
BLAKE2b-256 checksum
How to use checksums
52d36d622599fedaadddec66cf8e5b01c51895a7caae8b91bc657ae3f5cbe38a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / simple_module_branding-0.0.35-py3-none-any.whl

Download URL simple_module_branding-0.0.35-py3-none-any.whl
Size 44.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8f9404b792b49911511a56e7a88ac3e47a277a7291479b635432a04389dcf003
BLAKE2b-256 checksum
How to use checksums
a6e8c9a81373b88dbf92f2363d0fb96d6ff91a524e6439af157dcdfec5252576
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Security for simple-module-branding 0.0.35

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for simple_module_branding-0.0.35.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page