Flaxon 0.3.0 and Teloce-Py 0.3.0 are available on PyPI. Release instructions are maintained on this site; source links identify the framework snapshot. Check version and upgrade guidance.

Framework source · Markdown

Teloce full-stack integration: API reference

Flaxon owns HTTP, APIs and WebSockets. Teloce compiles UI components and handles browser state and navigation. MinifyJS optimizes generated production JavaScript; it does not execute requests or replace Teloce's compiler.

API reference

app.use_teloce(...)

Register once, before application startup. Returns Teloce and exposes it as app.teloce.

Argument Default Purpose
project_root Current directory Root containing every UI source
ui_dir ui Application components and pages
build_dir .flaxon/build Generated output, relative to project root
static_url /_flaxon Browser URL serving generated files
entry app.html Root component within a registered UI tree
title Application name HTML document title
options {} Overrides passed to Teloce Builder; also spa_mode/spa_base

Startup compiles sources. Missing directories, invalid components and duplicate page routes fail the build. UI directories must be within project_root.

await request.compile(entry="app.html", context=None, title=None)

Returns an HTMLResponse shell importing the root component, styles and router. Context is safely serialized as JSON and passed to mount(). This is client-side rendering, not server-rendered component HTML. A cached startup build is reused; if none exists, the integration builds lazily. Configure app.use_teloce() first. Never put secrets in context: it is visible in the browser.

app.teloce.build() and register_source(name, directory, routes=None)

build() explicitly rebuilds registered trees and returns Teloce's result. register_source() adds a source and invalidates the cached build. Names and source directories must be unique. Register before serving traffic; runtime concurrent builds are not a deployment strategy.

FlaxonModule(name, ui_dir=..., ui_routes=...)

Mounting a module registers its backend endpoints and UI source. It works before or after use_teloce(). ui_routes maps generated page filenames to client paths, for example {"ProductDetails/[id].js": "/products/:id"}. Backend mount prefixes such as /api/catalog do not automatically prefix browser page routes.

data-teloce-router-view identifies the page outlet (or use id="router-view"). data-teloce-link marks an anchor for client navigation:

<a href="/jobs" data-teloce-link>Jobs</a>
<main data-teloce-router-view></main>

The listener only intercepts ordinary same-origin HTTP(S) clicks to a matching client route. External links, modified clicks, downloads, other targets, nonmatching routes and same-page fragments retain browser behavior. Router guards can reject a matched navigation; it does not fall back to a full page load. The server still needs a catch-all route for direct visits and page refreshes.

Lesson 1: Compile your first interface

Install flaxon[standard] and a Teloce version containing its MinifyJS integration. For repository development, install Flaxon and updated Teloce from their actual local checkouts; do not copy another developer's Windows path.

Create ui/app.html:

<template><h1>{{ business }}</h1></template>
<script>export default { props: ["business"] };</script>

Create app.py:

from pathlib import Path
from flaxon import Flaxon, Request

app = Flaxon("My business", debug=True)
app.use_teloce(project_root=Path(__file__).parent, ui_dir="ui")

@app.get("/")
async def home(request: Request):
    return await request.compile("app.html", {"business": "Morgan Build & Repair"})

Run flaxon run app:app --reload and visit port 8000. The component is compiled as HTML-mode Teloce input, not served as raw HTML. .vel components are also supported by Teloce. Edit a source and refresh after the server restarts. Generated .flaxon files are excluded from the watcher; .vel files are included. This process reload is not browser HMR.

Lesson 2: Load data from Flaxon

Add an API before your catch-all route:

@app.get("/api/jobs")
async def jobs():
    return {"items": [{"id": 1, "customer": "Harbour View Bakery"}]}

A page can fetch it after mounting:

<template><p v-for="job in jobs" :key="job.id">{{ job.customer }}</p></template>
<script>
export default {
  data() { return { jobs: [] }; },
  async mounted() {
    const response = await fetch("/api/jobs");
    if (!response.ok) throw new Error("Could not load jobs");
    this.jobs = (await response.json()).items;
  }
};
</script>

The shipped SiteLedger Jobs page adds loading state, a Refresh button and a reusable JobCard. Its in-memory API is a teaching fixture: add persistence, authorization and visible loading/error states for production.

Lesson 3: Add page navigation

Put pages in ui/pages/; Jobs.html becomes /jobs and jobs/[id].html becomes /jobs/:id. Put marked links and a router outlet in app.html. Add a server fallback after API routes:

@app.get("/")
@app.get("/<path:spa_path>")
async def page(request: Request, spa_path: str = ""):
    return await request.compile("app.html", {"business": "My business"})

The browser router mounts pages; Flaxon handles /api/... data. Directly visiting /jobs/1 returns the same shell, and the router reads the URL. SiteLedger's detail page receives id as a prop and fetches /api/jobs/${this.id}.

Lesson 4: Keep a feature in one module

from pathlib import Path
from flaxon.modules import FlaxonModule

catalog = FlaxonModule(
    "catalog", ui_dir=Path(__file__).parent / "ui",
    ui_routes={"ProductDetails/[id].js": "/products/:id"},
)

@catalog.get("/products")
async def products():
    return {"items": []}

# In the application:
app.mount_module(catalog, prefix="/api/catalog")

See the modules shop for auth, catalog, orders and chat. Catalog owns pages and product components; chat owns a WebSocket and its page. Its browser component closes the socket in beforeUnmount(). Duplicate page routes across modules fail rather than silently choosing one. The sample login/data are demonstrations, not a complete security or database implementation.

Lesson 5: Deploy with MinifyJS

Use debug=False. Flaxon requests production compilation, asset hashes and extracted CSS. Updated Teloce uses MinifyJS for component/runtime optimization; Flaxon also optimizes its separately generated router through MinifyJS. Both compression and local-name mangling are enabled for that router. No Node is needed.

Development keeps Teloce's existing pipeline and source maps. This change does not enable the experimental native development backend. Bundling is not enabled by default; it requires selecting an appropriate entry and testing all module pages/lazy imports. Do not assume the startup integration is a unified bundle.

The build directory is served with Cache-Control: no-cache in both modes, so stable aliases and router.js revalidate after deployment. The HTML shell uses no-cache in production and no-store in development. A CDN must preserve this policy; only add long immutable caching to files with verified content hashes.

Install pinned compatible versions, build in a writable location at startup, and deploy source plus dependencies (or arrange an explicit build lifecycle). Each worker currently builds on startup: avoid concurrent writes to a shared build directory by using a single builder or isolated worker output directories. Add real authentication, database storage and authorization for business data.

SiteLedger example · Modules example

Optional page-head configuration

All additions are optional; existing title-only applications continue working.

app.mount_static("/static", str(project_root / "public"))
theme_cdn = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
app.use_teloce(
    project_root=project_root, ui_dir="ui", title="Taskboard",
    favicon="/static/favicon.svg", description="Team tasks in one place.",
    lang="en", theme_color="#101827", stylesheets=[theme_cdn],
    scripts=[{"src": "/static/help.js", "defer": True}],
)
Option Default Meaning
favicon None Icon link URL; serve the file separately
description None Escaped description meta content
lang en Escaped HTML document language, not script language
theme_color None Theme-color meta content
stylesheets None Ordered strings or dictionaries containing href
scripts None Ordered strings or dictionaries containing src

Scripts support type, boolean defer/async, integrity, crossorigin, referrerpolicy. Stylesheets support rel, type, media, sizes, integrity, crossorigin, referrerpolicy. Resource URLs allow relative, HTTP and HTTPS URLs; executable/data schemes and unknown attributes are rejected. Values are escaped; arbitrary HTML/event-handler attributes are not accepted.

These settings add tags to the head; they do not download, bundle or upload CDN resources. Pin trusted dependencies. Scripts execute with page privileges. Use verified SRI hashes and crossorigin="anonymous" where supported; don't invent hashes. Async resources have no guaranteed execution order. Do not assume an external library has loaded before a component mounts: coordinate explicitly if your component depends on it. Fonts and resources may require network access and disclose requests to providers. Local copies support offline applications.

Generated component CSS precedes extra stylesheet links, allowing intentional external overrides. Deferred classic scripts retain their order with each other; module and async timing needs separate consideration. The integration still emits an inline module bootstrap; a strict CSP needs a compatible nonce/hash strategy beyond these resource attributes. A favicon does not configure native Windows icons. Manifest and arbitrary head HTML are not part of this API.

For TypeScript, use <script lang="ts"> and import .ts helpers with a compatible Teloce version. Output is JavaScript; transpilation does not replace type checking. See the tested example and 10 full-stack lessons.

SSR and metadata options

await request.compile(entry, public_props, ssr=True, meta={...}) renders a manifest-linked AST program and hydrates the same public snapshot. meta supports title, description, canonical, Open Graph title/description/image/url/type, and twitter:card; values are escaped and resource URLs are validated.

Use options={"ssr": "opt-in", "ssr_entries": ["app.html"]} for selected pages. ssr_fallback defaults to "error"; "client" explicitly allows render-error fallback. ssr_cache_size enables bounded rendering cache; default is zero. Read SSR and browser debugging for the supported syntax, public-data rules, diagnostics, and production boundaries.

Build the generated starter for production

python management.py build

This command forces a production Teloce build with MinifyJS bundling and minification, extracted scoped CSS, hashed assets, and no development source maps or debugger client. It includes the UI contributed by mounted modules. Compilation errors exit unsuccessfully so deployment stops.

In app.py, call app.use_teloce(...) after mounting modules and before the if app.is_management: return app guard. Keep database connections and Admin store initialization after that guard. build does not run startup hooks or apply migrations. Backend-only projects do not need this command.

Automatic development rebuilds

Run python management.py runserver with DEBUG=True. Saved .html, .vel, .ts, .tsx, .js, .jsx, .css, and .json changes inside registered application and module UI folders are detected by the development browser every two seconds. Flaxon rebuilds the UI once and refreshes open pages after a successful build. Compilation failures show a notice linking to the debugger; another saved edit retries.

This is automatic rebuilding and full-page reload, not state-preserving component HMR. Unsaved editor changes are not visible; enable your editor's Auto Save if desired. Python changes still use the development server's Python reload. Imported files outside registered UI roots are not watched. Production registers no reload endpoint or client.

Optional first-party modules

Configure these in app.use_teloce(plugins={...}):

app.use_teloce(ui_dir="ui", plugins={
    "forms": True,
    "i18n": {"locale": "en", "messages": {"en": {"welcome": "Welcome"}}},
    "accessibility": True,
    "head": {"title": "Tasks", "pages": {"/projects": {"title": "Projects"}}},
    "pwa": {"name": "Tasks", "scope": "/", "icons": [
        {"src": "/static/icon-192.png", "sizes": "192x192", "type": "image/png"},
        {"src": "/static/icon-512.png", "sizes": "512x512", "type": "image/png"},
    ]},
})

Serve the icon files yourself. Browser APIs become available through globalThis.telocePlugins: forms.createForm, i18n.t, accessibility.openDialog, head.set and the asynchronous pwa registration result. Use False or {"enabled": False} to disable a module. Only enabled assets are emitted. The matching new Teloce version is required.

Forms offer touched/errors/submission state and map server field errors; validation and CSRF/authentication remain server responsibilities. Subscriptions must be cleaned up. Translations use named placeholders and Intl plural/number/date formatting. Accessibility uses native dialogs, focus restoration and navigation announcements. Head defaults appear in server HTML; request.compile(meta=...) overrides them. SPA navigation uses head.pages, or call head.set for dynamic pages.

PWA registration is disabled in debug mode. In production, Flaxon serves /teloce-sw.js with the configured allowed scope and injects the manifest link. HTTPS or localhost and valid icons are needed for browser installation eligibility. The worker caches only generated JS/CSS plus a generic offline fallback. It does not cache API, Admin or private user responses, and it does not implement offline editing. PWA registration failures never block mounting. Listen for teloce:pwa-update and teloce:pwa-error; activate updates only after the user has saved their work. Configuration is sent to the browser: never put secrets in plugin options.

The full API and framework-neutral setup are documented in Teloce's docs/first-party-plugins.md. These are optional modules inside teloce-py, not separate pip packages.

Type checking

python management.py typecheck checks all registered UI sources through Teloce's optional PyTSCheck adapter. See the type-checking guide for installation, JSON output, CI exit codes, and current limits.