Bosca / BML Read the docs

Bosca Markup Language

Pages, data,
and interactivity.
One file.

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

Markup in. Finished pages out.

01

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.

02

The compiler takes it from there

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.

03

The server renders complete HTML

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

Less to write. Less to ship.

The framework does the plumbing — rendering, data access, auth passthrough, asset serving — so a site is markup, data functions, and little else.

Server-rendered first

Every request returns complete HTML. Search engines and readers get finished pages, not loading states.

Islands, not hydration

Only regions you declare as islands get client behavior. The rest of the page ships as plain HTML with no JavaScript.

Actions without JavaScript

@click and @submit name a method on a server-side model. The server runs it and re-renders the island in place.

One data plane

All reads and writes go through the Bosca GraphQL API — a typed Kotlin client on the server, typed TypeScript stubs in the browser.

Compiled pages

Pages are typed Kotlin objects produced by a real compiler plugin, with an IntelliJ plugin for .bml editing.

Components with typed props

Reusable tags with declared props, slots, scoped styles, and per-instance state. Most built-in HTML tags can be overridden.

Client-managed auth

The browser owns the token; the server is pure passthrough. requireAuth guards a page with a redirect to sign-in.

Dev/prod parity

The GraphQL endpoint is configuration. Develop against a remote Bosca and deploy the same code unchanged.

Live state & actions

Interactive, with zero client code

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.

cart.bml
<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

From init to a running site

  1. 1

    Scaffold

    bosca bml init creates an ordinary Gradle project that lives in its own repository.

  2. 2

    Point it at Bosca

    Set the GraphQL endpoint — local or remote. Every query runs as the person viewing the page.

  3. 3

    Write and iterate

    The dev loop watches the source tree, regenerates on save, restarts the server, and live-reloads the browser.

  4. 4

    Deploy one process

    A compiled site is a single server: pages, static assets, actions, contracts, and the same-origin GraphQL proxy.

the bosca CLI
# 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"

BML ships with Bosca

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