This guide shows how to install and use the bun-plugin-stx plugin to work with .stx files in Bun, similar to how JSX works.
bun add bun-plugin-stxCreate a build script:
import stxPlugin from 'bun-plugin-stx'
await Bun.build({
entrypoints: ['./src/index.stx', './src/about.stx'],
outdir: './dist',
plugins: [stxPlugin()],
})Add to your bunfig.toml:
preload = ["bun-plugin-stx"]Then import .stx files directly in your TypeScript/JavaScript:
import homeContent from './pages/home.stx'
// homeContent is now compiled HTML string
console.log(homeContent)import stxPlugin from 'bun-plugin-stx'
// Build your .stx files
await Bun.build({
entrypoints: ['./pages/home.stx'],
outdir: './dist',
plugins: [stxPlugin()],
})
// Serve them
Bun.serve({
port: 3000,
async fetch(req) {
const html = await Bun.file('./dist/home.html').text()
return new Response(html, {
headers: { 'Content-Type': 'text/html' },
})
},
}).stx files use Blade-like syntax:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<script>
// Use ESM exports
export const title = "Hello World";
export const items = ["Apple", "Banana", "Cherry"];
export const showFooter = true;
</script>
</head>
<body>
<h1>{{ title }}</h1>
<ul>
@foreach (items as item)
<li>{{ item }}</li>
@endforeach
</ul>
@if (showFooter)
<footer>Copyright 2024</footer>
@endif
</body>
</html>✅ Build System Integration
- Works with Bun.build()
- Processes multiple .stx files in one build
- Generates proper HTML output
✅ Template Processing
- Variable interpolation:
{{ variable }} - Loops:
@foreach (array as item) ... @endforeach - Conditionals:
@if (condition) ... @endif - Raw HTML:
{!! rawHtml !!} - Components:
@include('Component')
✅ ESM Support
- Use
export constin script tags - Access exported variables in templates
- Async data fetching with
export const data = await fetchData()
✅ SEO Enhancement
- Automatic injection of SEO meta tags
- Open Graph tags
- Twitter Card tags
✅ Server Integration
- Works with Bun.serve()
- Supports multiple routes
- Can serve entire folders of .stx files
my-app/
├── pages/
│ ├── home.stx
│ ├── about.stx
│ └── contact.stx
├── components/
│ ├── Header.stx
│ └── Footer.stx
├── build.ts # Build script
└── serve.ts # Dev server
build.ts:
import stxPlugin from 'bun-plugin-stx'
import { Glob } from 'bun'
// Auto-discover all .stx files
const glob = new Glob('pages/**/*.stx')
const entrypoints = await Array.fromAsync(glob.scan('.'))
await Bun.build({
entrypoints,
outdir: './dist',
plugins: [stxPlugin()],
})serve.ts:
import { readdirSync } from 'fs'
// Map routes to HTML files
const routes = new Map()
const files = readdirSync('./dist')
for (const file of files) {
if (file.endsWith('.html')) {
const route = file.replace('.html', '')
routes.set(route, await Bun.file(`./dist/${file}`).text())
}
}
Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url)
const route = url.pathname.slice(1) || 'home'
if (routes.has(route)) {
return new Response(routes.get(route), {
headers: { 'Content-Type': 'text/html' },
})
}
return new Response('404 Not Found', { status: 404 })
},
})Run the included tests:
cd packages/bun-plugin
bun testTry the examples:
# Single file server
bun test/examples/serve-single.ts
# Multiple files server
bun test/examples/serve-multiple.tsimport stxPlugin from 'bun-plugin-stx'
await Bun.build({
entrypoints: ['./pages/*.stx'],
outdir: './dist',
plugins: [
stxPlugin({
// Enable caching
cache: true,
cachePath: './.stx-cache',
// Debug mode
debug: true,
// Web components
webComponents: {
enabled: true,
outputDir: './dist/components',
components: [
{
name: 'MyButton',
tag: 'my-button',
file: 'components/Button.stx',
attributes: ['type', 'text']
}
]
},
// i18n support
i18n: {
locale: 'en',
translationsDir: './translations',
}
})
],
})The plugin is fully functional and ready to use for:
- ✅ Building .stx files like JSX
- ✅ Serving static sites from .stx files
- ✅ Hot reloading in development
- ✅ Production builds with optimization
- ✅ Multiple pages and routing
- ✅ Component-based architecture
All tests pass (44/44) and the plugin works seamlessly with Bun's build system!