This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
stx is a fast, modern UI/templating framework that combines Laravel Blade-like syntax with Bun's performance. It's a monorepo containing multiple packages that work together to provide server-side rendering, component-based architecture, and a rich development experience.
This is a Bun workspace monorepo with packages in packages/:
packages/stx- Core framework with template processing enginepackages/bun-plugin- Bun plugin for.stxfile processingpackages/desktop- Native desktop application framework (NEW)packages/markdown- Markdown parsing with frontmatter supportpackages/sanitizer- HTML/XSS sanitizationpackages/iconify-core- Iconify integration corepackages/iconify-generator- Icon package generation CLIpackages/vscode- VS Code extension for.stxsyntaxpackages/devtools- Development toolingpackages/benchmarks- Performance benchmarks
External dependency: Craft (~/Code/craft) - Zig-based native webview framework for desktop/mobile apps
The core template processing happens in packages/stx/src/process.ts via processDirectives():
- Pre-processing: Comments removal, escaped directives
- Directive Processing: Sequential processing of directives in specific order:
- Stack directives (
@push,@prepend) - JavaScript/TypeScript execution (
@js,@ts) - Includes and layouts (
@include,@layout,@extends,@section) - Custom directives
- Components (
@component) - Conditionals (
@if,@switch,@auth,@env) - Loops (
@foreach,@for) - Expressions (
{{ }},{!! !!}) - i18n (
@translate) - Forms (
@csrf,@method,@error) - SEO directives (
@meta,@seo)
- Stack directives (
- Post-processing: Middleware, stack replacements, web component injection
Each directive type is handled by a dedicated module in packages/stx/src/.
The Bun plugin (packages/bun-plugin/src/index.ts) registers loaders for:
.stxfiles - Processed as templates and exported as JavaScript modules.mdfiles - Parsed with frontmatter and exported withcontentanddataexports
# Build all packages
bun run build
# Build individual packages
cd packages/bun-plugin && bun run build
cd packages/stx && bun run buildThe build process:
- Builds CSS assets (
packages/stx/scripts/build-css.ts) - Compiles TypeScript using custom build scripts (
build.tsin each package) - Creates compiled CLI binaries for multiple platforms
# Run all tests
bun test
# Run tests for a specific package
cd packages/stx && bun test
# Run specific test file
bun test packages/stx/test/directives/conditionals.test.ts
# Run tests with coverage
cd packages/stx && bun test --coverage
# Run tests in watch mode
cd packages/stx && bun test --watchTests use Bun's built-in test runner with Happy DOM preloaded (configured in bunfig.toml). Test files follow the pattern *.test.ts and are located in each package's test/ directory.
# Lint all code
bun run lint
# Auto-fix linting issues
bun run lint:fixUses @stacksjs/eslint-config for consistent code style.
# Serve .stx files for development
bun packages/bun-plugin/dist/serve.js pages/ --port 8888
# Or using the CLI
stx-serve pages/ --port 3000Templates execute in an isolated context. Variables are extracted from:
<script>tags - Variables can be declared with or withoutexportkeyword- Parent component/layout context
- Props passed to components
Important: The export keyword is optional in <script> tags. All variable declarations (const, let, var) and function declarations are automatically made available to the template, whether exported or not.
<script>
// Both styles work identically:
const title = 'Hello' // ✅ Works (auto-exported)
export const subtitle = 'World' // ✅ Works (explicitly exported)
function greet(name) { // ✅ Works (auto-exported)
return `Hello, ${name}!`
}
</script>
<h1>{{ title }}</h1>
<h2>{{ subtitle }}</h2>
<p>{{ greet('Alice') }}</p>See packages/stx/src/utils.ts extractVariables() and convertToCommonJS() for implementation details.
Custom directives are registered in packages/stx/src/config.ts as part of defaultConfig.customDirectives. Each directive needs:
name- without the@prefixhandler- function that processes the directivehasEndTag- whether it uses an end tag (e.g.,@directive...@enddirective)description- for documentation
Template caching is managed in packages/stx/src/caching.ts:
- Cache location:
.stx/cache(configurable viacachePath) - Cache invalidation based on file modification times and dependencies
- Disabled in development mode by default
Components in components/ are resolved via packages/stx/src/components.ts:
- Components are
.stxfiles - Can receive props and slots
- Support scoped context
- Resolved recursively to prevent circular dependencies
Web components are built from .stx templates (see packages/stx/src/web-components.ts):
- Configured in
stx.config.tsunderwebComponents - Generate custom element classes
- Support Shadow DOM, observed attributes, and lifecycle callbacks
Configuration is loaded from stx.config.ts or .config/stx.config.ts using bunfig.
Default config is in packages/stx/src/config.ts.
Important config options:
partialsDir- Directory for partial templatescomponentsDir- Directory for componentscache- Enable/disable template cachingdebug- Enable detailed error loggingcustomDirectives- Register custom directivesmiddleware- Pre/post-processing middlewarei18n- Internationalization settingswebComponents- Web component generation config
TypeScript path mappings are configured in tsconfig.json:
"paths": {
"stx": ["./packages/stx/src/index.ts"],
"@stacksjs/stx": ["./packages/stx/src/index.ts"],
"bun-plugin-stx": ["./packages/bun-plugin/src/index.ts"],
// ... other packages
}Use these imports consistently across the codebase.
# Generate changelog
bun run changelog
# Bump version and release (prompts for version)
bun run releaseThe release script:
- Generates
CHANGELOG.mdusinglogsmith - Prompts for version bump using
bumpx - Updates versions recursively across workspace packages
- Compiles binaries for all platforms
- Creates zip archives of binaries
Icons use Iconify with 200K+ icons:
# List available icon collections
bun stx iconify list
# Generate icon package
bun stx iconify generate <collection-name>Icon components are generated in packages/collections/ and used as <IconName size="24" /> in templates.
The @stacksjs/desktop package provides native desktop application support:
@stacksjs/desktop (TypeScript API)
↓
Craft (~/Code/craft - Zig webview implementation)
↓
Native APIs (WebKit/GTK/WebView2)
Note: The desktop package uses Craft for native webview rendering. Craft source lives at ~/Code/craft.
# Open native window with dev server
stx dev examples/homepage.stx --nativeThis internally calls openDevWindow() from the desktop package, which uses Craft to create a lightweight native window.
- Window Management: Create and control native windows
- System Tray: Build menubar applications
- Modals & Alerts: Native dialogs and notifications
- 35 UI Components: Documented component library
- Hot Reload: Development mode support
- 100% Test Coverage: 132 tests, 96.77% line coverage
packages/desktop/src/window.ts- Window management (fully implemented)packages/desktop/src/system-tray.ts- System tray with Craft bridge + web simulation (fully implemented)packages/desktop/src/modals.ts- Modal dialogs with native + web fallback (fully implemented)packages/desktop/src/alerts.ts- Toast notifications with native + web fallback (fully implemented)packages/desktop/src/components.ts- 35+ UI components with HTML rendering (fully implemented)packages/desktop/src/types.ts- Complete type definitionspackages/desktop/test/- Comprehensive test suitepackages/desktop/examples/- Working examples
The --native flag in stx dev is implemented in packages/stx/src/dev-server.ts:
import { openDevWindow } from '@stacksjs/desktop'
async function openNativeWindow(port: number) {
return await openDevWindow(port, {
title: 'stx Development',
width: 1400,
height: 900,
darkMode: true,
hotReload: true,
})
}Run desktop package tests:
cd packages/desktop
bun test # Run all tests
bun test --coverage # With coverage reportAll desktop functionality is fully tested. The package uses Craft (~/Code/craft) for native rendering.
The framework has robust error handling (packages/stx/src/error-handling.ts):
StxRuntimeError- Enhanced errors with file path, line/column infoerrorLogger- Structured error loggingerrorRecovery- Fallback content generation in productiondevHelpers- Development-friendly error messages
When debugging, enable debug: true in config for detailed stack traces.
Performance tracking is available via packages/stx/src/performance-utils.ts:
performanceMonitor.timeAsync()- Measure async operations- Metrics tracked: template processing, directive execution, file I/O
- Enable with performance config options
The stx CLI (packages/stx/bin/cli.ts) provides:
# Initialize new project
stx init
# Generate documentation
stx docs [--format html|markdown|json] [--output dir]
# Icon management
stx iconify list
stx iconify generate <collection>
# Serve templates
stx serve <directory> [--port 3000]-
Directive Processing Order Matters: Directives are processed sequentially. The order in
process.tsensures that includes/layouts are resolved before conditionals, which are resolved before expressions. -
Context Isolation: Each template execution gets an isolated VM context to prevent variable leakage and security issues. See
packages/stx/src/safe-evaluator.ts. -
Dependency Tracking: The build plugin tracks all template dependencies (includes, components, layouts) for proper cache invalidation.
-
Async Processing: Most directive handlers support async operations, allowing for file I/O, API calls, etc.
-
Middleware Timing: Middleware can run
beforeorafterdirective processing. Set thetimingfield appropriately. -
Component Resolution: Components are resolved relative to
componentsDirfirst, then fall back to current directory. Paths without extensions automatically append.stx.
- Use pickier for linting — never use eslint directly
- Run
bunx --bun pickier .to lint,bunx --bun pickier . --fixto auto-fix - When fixing unused variable warnings, prefer
// eslint-disable-next-linecomments over prefixing with_
- Use stx for templating — never write vanilla JS (
var,document.*,window.*) in stx templates - Use crosswind as the default CSS framework
- stx
<script>tags should only contain stx-compatible code (signals, composables, directives)
- buddy-bot handles dependency updates — not renovatebot
- better-dx provides shared dev tooling as peer dependencies — do not install its peers (e.g.,
typescript,pickier,bun-plugin-dtsx) separately ifbetter-dxis already inpackage.json - If
better-dxis inpackage.json, ensurebunfig.tomlincludeslinker = "hoisted"