Skip to content

Tina4 JavaScript – Quick Reference

Sub-3KB reactive framework

  • Signals for state, html tagged templates for rendering, Web Components for reuse
  • Client-side routing with {param} syntax matching tina4-php/python
  • Fetch API wrapper with Bearer + formToken auth compatible with tina4 backends
  • PWA support with runtime manifest and service worker generation
  • Tree-shakeable: import only what you need

Installation

bash
npx tina4 create my-app
cd my-app
npm install
npm run dev

More details on project setup, CLI options, and PWA scaffolding.

Signals

ts
import { signal, computed, effect, batch } from 'tina4js';

const count = signal(0);
const doubled = computed(() => count.value * 2);

effect(() => console.log(`Count: ${count.value}`));

count.value = 5;        // triggers effect → "Count: 5"
console.log(doubled.value); // 10

// Batch multiple updates into one notification
batch(() => { count.value = 10; count.value = 20; });

More details on reactive state, computed values, effects, and batching.

HTML Templates

ts
import { signal, html } from 'tina4js';

const name = signal('World');

const view = html`
  <div>
    <h1>Hello, ${name}!</h1>
    <input @input=${(e: Event) => {
      name.value = (e.target as HTMLInputElement).value;
    }}>
    <button @click=${() => { name.value = 'World'; }}>Reset</button>
  </div>
`;

document.getElementById('root')!.appendChild(view);

More details on template syntax, event handlers, boolean attributes, conditionals, and lists.

Components

ts
import { Tina4Element, html, signal } from 'tina4js';

class MyCounter extends Tina4Element {
  static props = { label: String };
  static styles = `:host { display: block; }`;

  count = signal(0);

  render() {
    return html`
      <div>
        <span>${this.prop('label')}: ${this.count}</span>
        <button @click=${() => this.count.value++}>+</button>
      </div>
    `;
  }

  onMount() { console.log('Connected!'); }
  onUnmount() { console.log('Removed!'); }
}

customElements.define('my-counter', MyCounter);
html
<my-counter label="Clicks"></my-counter>

More details on props, Shadow DOM, styles, lifecycle hooks, and events.

Routing

ts
import { route, router, navigate, html } from 'tina4js';

route('/', () => html`<h1>Home</h1>`);
route('/user/{id}', ({ id }) => html`<h1>User ${id}</h1>`);
route('/admin', {
  guard: () => isLoggedIn() || '/login',
  handler: () => html`<h1>Admin</h1>`
});
route('*', () => html`<h1>404</h1>`);

router.start({ target: '#root', mode: 'history' });

// Navigate programmatically
navigate('/user/42');

More details on hash vs history mode, route params, guards, and change events.

API

ts
import { api } from 'tina4js';

api.configure({ baseUrl: '/api', auth: true });

const users = await api.get('/users');
const user  = await api.get('/users/42');
await api.post('/users', { name: 'Andre' });
await api.put('/users/42', { name: 'Updated' });
await api.delete('/users/42');

More details on configuration, authentication, token rotation, interceptors, and error handling.

PWA

ts
import { pwa } from 'tina4js';

pwa.register({
  name: 'My App',
  shortName: 'App',
  themeColor: '#1a1a2e',
  cacheStrategy: 'network-first',  // or 'cache-first', 'stale-while-revalidate'
  precache: ['/', '/css/styles.css'],
  offlineRoute: '/offline',
});

More details on manifest generation, service worker strategies, and offline support.

Backend Integration

With tina4-php

bash
npx tina4 build --target php
# Outputs JS to src/public/js/
# Generates src/templates/index.twig
env
TINA4_APP_DOCUMENT_ROOT=src/public
TINA4_APP_INDEX=../templates/index.twig

With tina4-python

bash
npx tina4 build --target python
# Outputs JS to src/public/js/
# Generates src/templates/index.twig + src/routes/spa.py

More details on embedding in tina4-php/python, auth flow, and server-side state injection.

Bundle Size

ModuleRawGzipped
Core (signals + html + component)4.6 KB1.51 KB
Router0.14 KB0.12 KB
API3.5 KB1.49 KB
PWA3.0 KB1.16 KB
WebSocket2.3 KB0.91 KB
Debug16.2 KB5.11 KB
Full framework3.3 KB1.36 KB

Tree-shakeable — import only what you need:

ts
import { signal, html } from 'tina4js/core';     // 1.51 KB gzip
import { route, router } from 'tina4js/router';   // 0.12 KB gzip
import { api } from 'tina4js/api';                 // 1.49 KB gzip
import { pwa } from 'tina4js/pwa';                 // 1.16 KB gzip
import { ws } from 'tina4js/ws';                   // 0.91 KB gzip
import 'tina4js/debug';                            // 5.11 KB gzip (dev only)