π Why This Is Revolutionary
FyneJS is the first reactive framework that lets you run TypeScript component files directly in the browser without any compilation or bundling step.
While other frameworks require complex build setups (Webpack, Vite, Rollup, tsc, etc.) and watch processes to use TypeScript, FyneJS strips types instantly in the browserβas fast as the browser can parse JavaScript.
β Traditional Approach
- β’ Install TypeScript compiler
- β’ Configure tsconfig.json
- β’ Set up build tool (Webpack/Vite)
- β’ Watch mode for development
- β’ Wait for compilation on each change
- β’ Deal with source maps
β FyneJS Approach
- β’ Write .ts files
- β’ Load with FyneJS.loadComponents()
- β’ That's it!
- β’ Types stripped instantly
- β’ Reload page to see changes
- β’ No build step ever
How It Works
FyneJS uses a high-performance token-based scanner that strips TypeScript types while preserving runtime behavior and code structure.
1 Write TypeScript Components
Create your component files with full TypeScript supportβinterfaces, types, generics, everything.
// components/user-card.ts
import { XTool, html } from 'fynejs';
interface User {
name: string;
email: string;
role: 'admin' | 'user';
}
XTool.registerComponent({
name: 'user-card',
template: html`
<div class="card">
<h2 x-text="user.name"></h2>
<p x-text="user.email"></p>
<span x-text="user.role"></span>
</div>
`,
data: {
user: { name: 'John', email: 'john@example.com', role: 'admin' } as User
}
});
2 Load with FyneJS
Use loadComponents() to load your .ts files.
FyneJS automatically detects the TypeScript extension and strips types on the fly.
// In your main HTML or setup file
XTool.loadComponents([
{ path: 'components/user-card.ts', mode: 'preload' },
{ path: 'components/dashboard.ts', mode: 'defer' },
{ path: 'components/modal.ts', mode: 'lazy' }
]);
// Or load a single component dynamically
await XTool.loadComponent('components/user-card.ts');
3 Instant Execution
Types are stripped using a single-pass tokenizer with linked token tracking for context awareness. The JavaScript is executed immediatelyβno compilation, no waiting, no build process.
<!-- Use the component immediately -->
<component source="user-card"></component>
<!-- Dynamic loading example -->
<component x:source="'user-card'"></component>
Complete Setup Guide
Follow this pattern for organizing your multi-page FyneJS projects with TypeScript.
Step 1: Create Setup File
Create a central demo-loader.js or
app-setup.js file that initializes FyneJS,
loads all components, and handles routing.
// demo-loader.js or app-setup.js
(function() {
// List of component files (mix .ts and .js)
const componentFiles = [
'interactive-showcase.ts', // TypeScript component
'user-dashboard.ts', // TypeScript component
'data-chart.ts', // TypeScript component
'shopping-cart.js', // JavaScript component
'modal.js' // JavaScript component
];
const basePath = 'components/';
// Initialize FyneJS
XTool.init({
container: 'body',
debug: false,
router: {
enabled: true,
before: (to, from, info) => {
console.log(`Navigating from ${from} to ${to}`);
return true; // Allow navigation
},
after: (to, from, info) => {
console.log(`Navigated to: ${to}`);
}
}
});
// Load all components
XTool.loadComponents(
componentFiles.map(file => ({
path: basePath + file,
mode: 'preload' // or 'defer' or 'lazy'
}))
);
// Optional: Add code block enhancement
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('pre > code').forEach(block => {
// Add line numbers, syntax highlighting, etc.
});
});
})();
Step 2: Include in HTML Pages
Every HTML page that uses FyneJS should include the framework script and your setup file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>My FyneJS App</title>
<!-- Styles -->
<link rel="stylesheet" href="./styles.css" />
<!-- FyneJS Framework -->
<script src="../dist/x-tool.min.js" defer></script>
<!-- Shared Components -->
<script src="./shared/navigation.js" defer></script>
<script src="./shared/footer.js" defer></script>
<!-- Your Setup File (loads TypeScript components) -->
<script src="./demo-loader.js" defer></script>
</head>
<body>
<!-- Navigation component -->
<component source="docs-nav" x-prop="{ page: 'home' }"></component>
<!-- Page content -->
<main>
<!-- TypeScript component loaded automatically -->
<component source="interactive-showcase"></component>
</main>
<!-- Footer component -->
<component source="docs-footer"></component>
</body>
</html>
Step 3: Organize Components
Structure your components logically. Mix TypeScript and JavaScript files as needed.
Recommended Structure:
project/
βββ index.html
βββ about.html
βββ contact.html
βββ demo-loader.js # Central setup
βββ components/
β βββ page-specific/
β β βββ hero-section.ts # TypeScript
β β βββ pricing-table.ts # TypeScript
β β βββ testimonials.js # JavaScript
β βββ features/
β β βββ user-dashboard.ts
β β βββ analytics-widget.ts
β β βββ notification-center.ts
β βββ ui/
β βββ modal.js
β βββ tooltip.js
β βββ dropdown.ts
βββ shared/
βββ navigation.js # Shared across all pages
βββ footer.js # Shared across all pages
β‘ Performance
Single-pass tokenization with optimized character testing delivers exceptional performance.
interactive-showcase.ts component
Benchmark Details:
- β’ File: 983 lines of TypeScript with interfaces, types, and complex generics
- β’ Average Time: ~34ms (including file read, tokenization, and stripping)
- β’ Implementation: Token-based scanner with linked token tracking
- β’ Memory: Efficient string handling with incremental concatenation
- β’ Note: Timing varies based on system load, but consistently fast
Performance Note
Type stripping happens once when the component is loaded. After that, the component runs as pure JavaScript with zero overhead. The stripping time includes file I/O and is far faster than traditional compilation workflows that take seconds or minutes.
Usage Considerations
Understanding the type stripping implementation and its characteristics.
Best Suited for Well-Formed Code
The stripper works best with well-formed TypeScript code. It does not perform full TypeScript parsing but focuses on type syntax removal while preserving runtime behavior and code structure.
Handles Most TypeScript Patterns
The implementation handles most common TypeScript patterns reliably and tries to handle very complex type constructs. The simpler the types, the better the results.
What Gets Removed:
- β’ Type annotations (variables, parameters, return types)
- β’ Interface, namespace, declare, and type alias declarations
- β’ Generics in functions and classes
- β’ Import/export declarations (including regular ones, not just type-only)
- β’ Non-null assertion operators (!)
- β’ Access modifiers (public, private, protected)
- β’ Function overload signatures
- β’ Type assertions ('as' syntax)
- β’ Enum declarations
- β’ implements clauses in class declarations
No Type Checking or Runtime Type Info
This is not suitable for runtime type information preservationβtypes are completely removed. No type checking is performed; use an IDE with TypeScript support (VS Code, WebStorm) for type checking during development.
Consider File Size
While the stripper is fast, consider file size when processing large codebases. Browser environments work best with reasonably-sized component files. You decide what's appropriate for your use case.
Framework Comparison
No other reactive framework offers this capability.
| Framework | TypeScript Support | Build Required | Browser-Native .ts |
|---|---|---|---|
| FyneJS | β | β | β |
| Alpine.js | β οΈ | β | β |
| Vue | β | β | β |
| React | β | β | β |
| Svelte | β | β | β |
Ready to Try It?
Start writing TypeScript components without any build setup today.