Write markup
Pages, components, and islands live in .bml files — HTML-like markup with embedded server Kotlin and, where needed, client TypeScript in the same file.
Bosca Markup Language
BML is a server-rendered web framework for building sites on Bosca. Write HTML-like markup with embedded server Kotlin; the compiler turns each file into a page that ships complete HTML — and only as much JavaScript as you declared.
How it works
Pages, components, and islands live in .bml files — HTML-like markup with embedded server Kotlin and, where needed, client TypeScript in the same file.
A Kotlin K2 compiler plugin turns each file into a typed, compiled page object and bundles client scripts into browser modules. Diagnostics point at the .bml line you wrote.
One server process registers every page route, renders finished HTML on each request, and serves assets in three tiers so a page loads only what it uses.
What makes it powerful
The framework does the plumbing — rendering, data access, auth passthrough, asset serving — so a site is markup, data functions, and little else.
Every request returns complete HTML. Search engines and readers get finished pages, not loading states.
Only regions you declare as islands get client behavior. The rest of the page ships as plain HTML with no JavaScript.
@click and @submit name a method on a server-side model. The server runs it and re-renders the island in place.
All reads and writes go through the Bosca GraphQL API — a typed Kotlin client on the server, typed TypeScript stubs in the browser.
Pages are typed Kotlin objects produced by a real compiler plugin, with an IntelliJ plugin for .bml editing.
Reusable tags with declared props, slots, scoped styles, and per-instance state. Most built-in HTML tags can be overridden.
The browser owns the token; the server is pure passthrough. requireAuth guards a page with a redirect to sign-in.
The GraphQL endpoint is configuration. Develop against a remote Bosca and deploy the same code unchanged.
Live state & actions
A page declares a server-side model, an island renders it, and @click names a method on it. When the event fires, the server runs the method, persists the new state, re-renders the island, and the runtime swaps it in place. This cart never required a line of JavaScript.
With scope="server" the model lives in a server-side session — the client only ever holds an opaque session cookie, so the cart's contents never reach the browser.
<page route="/cart" title="Cart">
<script server provides="cart" scope="server">
shop.Cart()
</script>
<island name="cart-view">
<p>{ cart.itemCount } item(s) in your cart</p>
</island>
<button @click="cart.addItem">Add item</button>
<button @click="cart.clear">Clear</button>
</page>Get started
bosca bml init creates an ordinary Gradle project that lives in its own repository.
Set the GraphQL endpoint — local or remote. Every query runs as the person viewing the page.
The dev loop watches the source tree, regenerates on save, restarts the server, and live-reloads the browser.
A compiled site is a single server: pages, static assets, actions, contracts, and the same-origin GraphQL proxy.
# scaffold a project
bosca bml init my-site
# generate Kotlin once
bosca bml compile my-site
# watch, regenerate, restart, live-reload
bosca bml dev my-site --run "./gradlew run"Go deeper
A BML site queries the same GraphQL API Studio writes to — Studio manages the content, BML renders it. The docs cover the language, the live-state model, and deployment end to end.
Read the docs