Iwf Guide
Assets and Styling
Iwf vendors the framework assets used by the default shell and exposes helpers for app assets. Basecoat is the default styling target, while unstyled rendering is available when an app owns all markup and CSS.
1. Framework Assets
runApp mounts default framework assets under:
/__iwf/assets
The default shell uses fingerprinted versions of:
- htmx
- morphdom-swap support
- Basecoat CSS/JS
- Iwf client script
Generated apps do not rely on production CDNs for the default shell.
2. App Static Assets
Use embedded static assets:
appCss : StaticAsset
appCss =
stylesheet "app.css" "body { font-family: sans-serif; }"
appWithAssetRoutes : Routes
appWithAssetRoutes =
staticRoutes "/assets" [appCss] ++ appRoutes
Plain asset paths use revalidation cache headers and ETag.
Use fingerprinted assets for immutable caching:
cssHref : String
cssHref =
fingerprintedAssetHref "/assets" appCss
assetRoutes : Routes
assetRoutes =
fingerprintedStaticRoutes "/assets" [appCss]
3. Development Refresh
Add asset refresh during local development:
devLayout : PageLayout
devLayout context page =
{ pageHead := page.pageHead ++ [devAssetRefreshScript] } page
devPage : Html
devPage =
fragment
[ <title>Development</title>
, <main id="main-content">
<h1>Development</h1>
</main>
]
The browser polls the asset version endpoint and reloads when the served asset bundle changes.
For browser reloads during local work, use:
devLiveReloadScriptdevLiveReloadRoutes
4. Basecoat
Basecoat-oriented defaults are used by:
- generated direct HTML starter
- form helpers
- submit buttons
- flash messages
- pagination
- breadcrumbs
- job dashboard
Use the app build to run Basecoat IDRX checking:
iwf build
For fully custom styling, return direct page HTML with render and configure shared shell attributes once with withPageLayout:
unstyledFormInputunstyledFormErrorsunstyledSubmitButton
5. Tailwind and NPM
Iwf does not provide a first-class NPM/Yarn workflow. The canonical example has a Tailwind watcher because that app chooses to use it, not because the framework requires it. App-specific frontend tooling can live beside Iwf without becoming part of the framework contract.