frame-master-plugin-tailwind
v2.0.0
Published
Tailwind CSS integration for Frame-Master — compile, serve, optional HTML inject, and HMR.
Maintainers
Readme
frame-master-plugin-tailwind
Tailwind CSS integration for Frame-Master v4: compile, serve, optional HTML injection, and live CSS reload.
Requires frame-master@^4.0.0-0. See QUICK_EXEMPLE.md and CONFIG_EXEMPLE.md.
Features
- Tailwind CSS v4 — works with
@tailwindcss/cliandtailwindcss≥ 4.1.18 - Auto-compilation — one-shot minify on startup;
--watchin development - Optional HTML inject — runtime and/or production build (both default on)
- HMR — WebSocket reload of
/tailwind.csswithout a full page refresh - Stable public URLs — CSS, bootstrap, and WS paths are fixed regardless of
outputFile
Installation
bun add frame-master-plugin-tailwind
# peers (if not already present)
bun add -d tailwindcss @tailwindcss/cliQuick start
// frame-master.config.ts
import type { FrameMasterConfig } from "frame-master/server/types";
import TailwindPlugin from "frame-master-plugin-tailwind";
export default {
HTTPServer: { port: 3000 },
plugins: [
TailwindPlugin({
inputFile: "static/index.css",
outputFile: "static/tailwind.css",
}),
],
} satisfies FrameMasterConfig;/* static/index.css */
@import "tailwindcss";bun devPublic URLs (contract)
| Asset | Path |
|--------|------|
| Compiled CSS | /tailwind.css |
| HMR client | /tailwind/bootstrap.js |
| WebSocket | /ws/tailwind (dev only) |
outputFile is only the on-disk compile target. Browsers always load /tailwind.css.
Configuration
type TailwindPluginProps = {
inputFile: string;
outputFile: string;
options?: {
/** Inject CSS + HMR bootstrap into HTML responses. @default true */
autoInjectInHtml?: boolean;
/** Inject CSS into HTML entrypoints on production build. @default true */
autoInjectInBuild?: boolean;
/** CLI runner: "bun" | "bunx" | "npx". @default "bun" */
runtime?: "bun" | "bunx" | "npx";
};
};Manual HTML (no auto-inject)
TailwindPlugin({
inputFile: "static/index.css",
outputFile: "static/tailwind.css",
options: {
autoInjectInHtml: false,
autoInjectInBuild: false,
},
});<link href="/tailwind.css" rel="stylesheet" id="__tailwindcss__" />
<!-- Dev HMR only -->
<script src="/tailwind/bootstrap.js" id="__tailwind_bootstrap__"></script>Keep id="__tailwindcss__" so HMR can cache-bust the stylesheet.
Runtime CLI
If bun tailwindcss fails on your machine:
options: { runtime: "bunx" } // or "npx"The plugin prefers a local @tailwindcss/cli install when present.
Behavior notes
- Dev: watches
outputFile, restarts the Tailwind CLI with backoff on crash, reconnecting HMR client (ws/wss). - Prod compile: throws a structured error on failure (does not hard-kill via
process.exitalone through Frame-Master hooks). - Config reload / dispose:
serverStopstops the file watcher and Tailwind child process (reload, testdispose(), SIGINT/SIGTERM). - HMR bootstrap: declared as the plugin-owned virtual module
@tailwind/bootstrap.js(build-only;injectRuntime: false). - WebSockets: only connections upgraded with
{ tailwind: true }are tracked.
Scripts (contributors)
bun install
bun test
bun run build-bootstrap
bun run format # BiomePublishing
Pushes to main that touch package.json run .github/workflows/publish.yml using npm Trusted Publisher (OIDC) — no NPM_TOKEN secret.
- Read
name/versionfrompackage.json - Skip if that version already exists on npm
- Otherwise run tests, build bootstrap, and
npm publishvia OIDC
One-time setup on npmjs.com: package → Settings → Trusted Publisher → GitHub Actions:
| Field | Value |
|--------|--------|
| Organization or user | shpaw415 |
| Repository | frame-master-plugin-tailwind |
| Workflow filename | publish.yml |
| Allowed actions | npm publish |
Manual re-run: Actions → Publish to npm → Run workflow.
License
MIT
