A quick reference cheat sheet to getting started with InfrontJS — creating an App, adding States, rendering Vi.
<!-- UMD build (global IF) -->
<script src="https://unpkg.com/infrontjs/dist/IF.js"></script>
Use this for the fastest “drop in and run” setup.
<script type="module">
import * as IF from "https://unpkg.com/infrontjs@latest/dist/infrontjs.esm.js";
</script>
Use this if you want modern ES modules in the browser.
npm install infrontjs
// bundler setup
import * as IF from "infrontjs";
<div id="app"></div>
<script type="module">
import * as IF from "https://unpkg.com/infrontjs@latest/dist/infrontjs.esm.js";
// Create app with a container
const app = new IF.App(document.querySelector("#app"));
// Start lifecycle (router/state/view init, initial state, ...)
app.run();
</script>
Creates an App instance and starts it via app.run().
import * as IF from "https://unpkg.com/infrontjs@latest/dist/infrontjs.esm.js";
const app = new IF.App(document.querySelector("#app"), {
router: { mode: "hash" } // "url" (pushState) or "hash"
});
app.run();
Use hash mode if you don’t control server rewrites (GitHub Pages, many CDNs, etc.).
The logical “core unit” of an InfrontJS application. Owns router, stateManager, view, i18n, etc.
const app = new IF.App(containerEl, {
app: {
id: "my-app",
title: "My App",
sayHello: true
},
router: {
isEnabled: true,
mode: "url", // or "hash"
basePath: null
},
l18n: {
defaultLanguage: "en"
}
});
A State represents a route-driven unit of logic / lifecycle. Typically: fetch data → render a view → bind events → cleanup on exit.
class MyState extends IF.State {
static ROUTE = "my-state";
async enter() {
console.log("Hello from MyState");
}
}
Template rendering uses EJS templates and provides localization helpers.
app.view.render(app.container, `
<h1>Welcome <%= username %></h1>
<p><%= _lcs("greeting") %></p>
`, { username: "John" });
Precompile templates for reuse:
const tpl = app.view.compile(`<h1><%= title %></h1>`);
const html = tpl({ title: "Page 1" });
this.app.view.setWindowTitle("My App - Dashboard");
class GreetingState extends IF.State {
static ROUTE = "";
async enter() {
this.app.view.render(this.app.container, "<h1>Hello InfrontJS World</h1>");
}
}
const app = new IF.App(document.querySelector("#app"), {
router: { mode: "hash" }
});
app.stateManager.add(GreetingState);
app.run();
class CounterState extends IF.State {
static ROUTE = "counter";
async enter() {
this.count = 0;
this.app.view.render(this.app.container, `
<div>
<h1>Counter</h1>
<p>Value: <span id="v"><%= count %></span></p>
<button id="inc">Increment</button>
</div>
`, { count: this.count });
const v = this.app.container.querySelector("#v");
const btn = this.app.container.querySelector("#inc");
this.addEventListener(btn, "click", () => {
this.count++;
v.textContent = String(this.count);
});
}
}
The State base class offers helpers like addEventListener(...) to track cleanup.
router.mode = "url" — Uses history.pushState URLs (needs server rewrite)
router.mode = "hash" — Uses #/path URLs (works on static hosting)
router.isEnabled = false — Disable routing entirely
canEnter() — Before entering a state
enter() — Main entry hook
canExit() — Before leaving state
exit() — Cleanup hook
class LiveState extends IF.State {
ROUTE = "live";
async onEnter() {
this.addEventListener(window, "resize", () => this.render());
this.setInterval(() => this.tick(), 1000);
this.setTimeout(() => console.log("ready"), 200);
this.render();
}
render() {
this.app.view.render(this.app.container, "<h1>Live</h1>");
}
}
new IF.App(container?, config?) — Create app
IF.App.get(uid?) — Get app instance
app.run(route?) — Start lifecycle
await app.destroy() — Dispose app
app.view.render(el, tpl, data?) — Render template
app.view.compile(tpl) — Compile template