Ready in 30 seconds

Getting Started with FyneJS

Get up and running with FyneJS in minutes. No complex setup, no build toolsβ€”just add a script tag and start building reactive UIs.

Zero Dependencies
No Build Step
11KB Gzipped

Choose Your Installation Method

Start building in seconds with your preferred setup

CDN (Recommended)

Start immediately - just add one script tag

<script src="https://cdn.jsdelivr.net/npm/fynejs@latest"></script>

NPM Package

For bundlers and modern build tools

npm install fynejs
import FyneJS from 'fynejs';
FyneJS.init();

Three Ways to Build Components

Inline Components

Use x-data directly in HTML for quick, simple components

Registered Components

Register reusable components with templates, methods, and lifecycle hooks

Component Loading

Load components from external files with lazy loading and preload strategies

<!-- Inline x-data component -->
<div x-data="{ count: 0, message: 'Hello!' }">
  <h1 x-text="message"></h1>
  <p x-text="'Count: ' + count"></p>
  <button x-on:click="count++">Click me</button>
</div>
<script>
// Register reusable component
FyneJS.registerComponent({
  name: 'counter-card',
  template: \`
    <div class="card">
      <h2 x-text="title"></h2>
      <p x-text="'Count: ' + count"></p>
      <button x-on:click="increment">+</button>
    </div>
  \`,
  data: { count: 0, title: 'Counter' },
  methods: {
    increment() { this.count++; }
  }
});
</script>

<!-- Use the component -->
<component source="counter-card"></component>
<script>
// Load components from external files
FyneJS.loadComponents([
  { path: 'components/header.js', mode: 'preload' },
  { path: 'components/sidebar.js', mode: 'defer' },
  { path: 'components/modal.js', mode: 'lazy' }
]);
</script>

<!-- Components load automatically -->
<component source="header"></component>
<component source="sidebar"></component>

Building Multi-Page Projects

Learn how to organize and structure complex FyneJS applications with multiple pages and components.

Central Setup File Pattern

Create a single setup file (like demo-loader.js or app-setup.js) that handles initialization, component loading, and routing for your entire application.

1 Create your setup file:

// demo-loader.js (or app-setup.js)
(function() {
  // List all your component files
  const componentFiles = [
    'header.js',
    'footer.js',
    'user-card.ts',        // TypeScript works too!
    'modal.js',
    'data-chart.ts'
  ];
  
  // Initialize FyneJS
  XTool.init({ 
    router: { enabled: true }
  });
  
  // Load all components
  XTool.loadComponents(
    componentFiles.map(file => ({
      path: 'components/' + file,
      mode: 'preload'  // or 'defer', 'lazy'
    }))
  );
})();

πŸ“š Full API: See the XTool.init() and loadComponents() documentation for all configuration options.

2 Include in every HTML page:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>My App - Home</title>
  
  <!-- Styles -->
  <link rel="stylesheet" href="./styles.css" />
  
  <!-- FyneJS Core -->
  <script src="../dist/x-tool.min.js" defer></script>
  
  <!-- Your Setup File (loads everything) -->
  <script src="./demo-loader.js" defer></script>
</head>
<body>
  <!-- Components are now available -->
  <component source="header"></component>
  
  <main>
    <component source="user-card"></component>
  </main>
  
  <component source="footer"></component>
</body>
</html>

Recommended Project Structure

Organize your components logically by feature, page, or UI type. Mix JavaScript and TypeScript files as needed.

my-fynejs-app/
β”œβ”€β”€ index.html
β”œβ”€β”€ about.html
β”œβ”€β”€ contact.html
β”œβ”€β”€ styles.css
β”œβ”€β”€ demo-loader.js          # Central setup file
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ page-specific/
β”‚   β”‚   β”œβ”€β”€ hero-section.ts
β”‚   β”‚   β”œβ”€β”€ pricing-table.js
β”‚   β”‚   └── testimonials.ts
β”‚   β”œβ”€β”€ features/
β”‚   β”‚   β”œβ”€β”€ user-dashboard.ts
β”‚   β”‚   β”œβ”€β”€ analytics-widget.js
β”‚   β”‚   └── notification-center.ts
β”‚   └── ui/
β”‚       β”œβ”€β”€ modal.js
β”‚       β”œβ”€β”€ tooltip.js
β”‚       └── dropdown.ts
└── shared/
    β”œβ”€β”€ navigation.js       # Shared across all pages
    └── footer.js          # Shared across all pages
Pro Tips
  • β€’ Keep shared components (nav, footer) in a shared/ directory
  • β€’ Group page-specific components together
  • β€’ Use feature folders for related component groups
  • β€’ Mix .js and .ts files freelyβ€”FyneJS handles both!

Routing & Navigation

FyneJS includes a built-in SPA router with view transitions, prefetching, and navigation hooks.

Enable routing in your setup file:

XTool.init({
  router: {
    enabled: true,
    before: (to, from, info) => {
      // Optional: auth checks, analytics, etc.
      return true;
    },
    after: (to, from, info) => {
      // Optional: scroll, update UI, etc.
    }
  }
});

Use x-link in your navigation:

<nav>
  <a href="/index.html" x-link>Home</a>
  <a href="/about.html" x-link>About</a>
  <a href="/contact.html" x-link>Contact</a>
</nav>

πŸ“š Learn more: Check out the Router documentation or Router API reference for all configuration options including view transitions, prefetching, error handlers, and more.

This Documentation Site Uses This Pattern!

The site you're reading right now follows this exact structure. Check out docs/demo-loader.js to see it in action.

βœ“ What We Do

  • β€’ Single demo-loader.js file
  • β€’ All pages include the same scripts
  • β€’ Components loaded once, shared everywhere
  • β€’ Router handles navigation smoothly
  • β€’ TypeScript components work seamlessly

⚑ Benefits

  • β€’ DRY: Don't repeat script includes
  • β€’ Consistent: Same setup everywhere
  • β€’ Fast: Components cached after first load
  • β€’ Maintainable: Change once, apply everywhere
  • β€’ Scalable: Easy to add new components

What's New

Discover the latest features added to FyneJS that make building interactive applications even easier.

HTML Component Files

Write components in native .html files with full IDE syntax highlightingβ€”no template strings needed!

<template>...</template>
<script setup>
  expose({ data, methods });
</script>

Signals API

Lightweight child β†’ parent messaging with payloads and bubbling. Perfect for component communication.

Signals.emit('saved', data);
Signals.connect('saved', handler);

x-ref & :attr Shorthand

Named element references via $refs and Vue-style :attr shorthand for cleaner attribute binding.

<input x-ref="myInput">
<img :src="url" :alt="desc">

What's Next?