Site Hosting w/ Separate Assets

Give hosted sites their own independent web module, layouts, components, and asset pipeline. This separates the hosted site experience from the main admin app so they can have completely different CSS, JavaScript, and UI components.

v1.8.3
Level: Medium
17
422
36

Asset build tasks

The assets.build and assets.deploy aliases are extended to compile both my_app and hosted profiles. The deploy alias minifies both CSS and JS bundles before running phx.digest .

Hosted CSS

A separate Tailwind entry point for hosted sites. Uses source(none) to disable automatic content detection, then explicitly sources from assets/css , assets/js , and lib/my_app_hosted_web — so it only includes classes actually used by hosted site code. No daisyUI plugin is included.

Hosted JavaScript

A minimal LiveSocket setup for hosted sites. Includes only the essentials: Phoenix HTML, LiveSocket with CSRF and long-poll fallback, and topbar for loading indicators. No admin-specific hooks, uploaders, or JavaScript are included.

Build configuration

Adds a hosted profile to both esbuild and tailwind configurations. The esbuild config bundles js/hosted.js into priv/static/assets/js/hosted.js . The tailwind config compiles assets/css/hosted.css into priv/static/assets/css/hosted.css . Both run alongside the existing my_app profiles.

Dev watchers

Adds esbuild_hosted and tailwind_hosted watchers so hosted assets rebuild on change during development. Also adds a live reload pattern for lib/my_app_hosted_web so changes to hosted components, controllers, and LiveViews trigger browser reloads.

MyAppHostedWeb module

The MyAppHostedWeb module mirrors the structure of MyAppWeb but is completely independent. It defines its own controller , live_view , live_component , html , and router macros, all wired to MyAppHostedWeb -specific components and layouts.

Key differences from MyAppWeb :

This separation means hosted sites won't inherit any admin-specific UI (daisyUI, admin nav, etc.) and can be styled completely independently.

Core components

A minimal set of UI components for hosted sites using plain Tailwind CSS (no daisyUI). Includes only what's needed: flash/1 for notifications, icon/1 for Heroicons, show/2 and hide/2 JS commands, and error translation helpers.

This is intentionally bare — hosted sites start with a clean slate and you add components as needed, rather than inheriting the full admin component library.

Layouts

The hosted layouts module provides a simple app/1 layout with a centered content area and flash message group. The flash_group/1 component handles info/error flashes plus client-error and server-error reconnection states.

Root layout

The root HTML template loads hosted.css and hosted.js instead of the admin's app.css and app.js . This is what makes the asset separation work — hosted sites get their own CSS and JS bundles with no admin code included.

Error HTML

A standalone error handler for hosted sites that returns plain status messages. Hosted sites get their own error rendering so they don't accidentally show admin error pages.

Page controller and templates

A simple page controller that renders the hosted site landing page. It passes the current_site assign (set by the ServeHostedSite plug) to the template, which displays the site name. This is the starting point — replace this with whatever your hosted sites should render.

Hosted router

The hosted router replaces the previous MyAppWeb.HostedRouter that lived inside the main app. It uses MyAppHostedWeb instead of MyAppWeb , giving it a clean browser pipeline without fetch_current_scope_for_user or any admin auth plugs. The root layout points to MyAppHostedWeb.Layouts instead of the admin layouts.

Currently has a single route: GET / renders the site's landing page via PageController .

Endpoint update

The ServeHostedSite plug now dispatches to MyAppHostedWeb.Router instead of MyAppWeb.HostedRouter . This is the only change needed in the endpoint — the plug already handles intercepting hosted requests before they reach the main router.