SPACEPORT DOCS

Launchpad: Server-Side Templating & Reactivity

Launchpad is Spaceport's integrated templating engine and reactive UI system. It enables you to build dynamic, interactive web applications by combining server-side HTML generation with real-time reactivity, powerful UI components, and seamless server-client communication—all without writing extensive JavaScript.

Launchpad represents a paradigm shift in web development: instead of managing complex client-side state and API calls, you write intuitive Groovy code that runs on the server and automatically keeps your UI in sync. The result is a development experience that feels like working with a modern JavaScript framework, but with the security, simplicity, and power of server-side logic.

# Core Philosophy

Launchpad is built on several key principles:

# Feature Overview

Launchpad provides four interconnected systems that work together to create dynamic, interactive user interfaces:

Templates provide server-side HTML generation with embedded Groovy code, giving you the full power of a programming language in your markup. Unlike traditional templating engines limited to simple variable interpolation, Launchpad templates can execute complex logic, interact with databases, and make decisions about what to render—all before the HTML reaches the browser.

Server Actions bridge the gap between user interactions and server-side logic by allowing you to bind Groovy closures directly to DOM events. When a user clicks a button, submits a form, or changes an input, your server-side code executes with full access to your application's business logic, authentication context, and database—no REST endpoints or API routes required.

Reactive Variables eliminate the tedious work of manually updating the DOM when data changes. By wrapping expressions in special syntax, Launchpad automatically tracks dependencies and sends targeted updates to the browser whenever the underlying data changes, creating fluid, responsive interfaces without writing DOM manipulation code.

Server Elements take component-based development to the next level by encapsulating HTML structure, CSS styling, JavaScript behavior, and server-side logic into reusable units. They feel like native HTML elements but are backed by powerful Groovy classes that can maintain state, interact with databases, and respond to events—all while being as simple to use as .

Together, these systems form a cohesive development experience that dramatically reduces the complexity of building modern web applications. Where traditional frameworks require you to maintain separate frontend and backend codebases with complex communication protocols between them, Launchpad unifies the stack under a single, intuitive paradigm.

# Getting Started

## Directory Structure

Create a launchpad/ directory in your Spaceport project root with two subdirectories:

/[SPACEPORT_ROOT]
  launchpad/
    parts/         # GHTML templates (pages and partials)
    elements/      # Server Element definitions (optional)

## Basic Setup

In your source module, initialize a Launchpad instance and define routes that use your templates:

import spaceport.computer.alerts.Alert
import spaceport.computer.alerts.results.HttpResult
import spaceport.launchpad.Launchpad

class Router {
    
    static Launchpad launchpad = new Launchpad()
    
    @Alert('on / hit')
    static void _index(HttpResult r) {
        launchpad.assemble(['header.ghtml', 'index.ghtml', 'footer.ghtml'])
                .launch(r, 'wrapper.ghtml')
    }
}

What's happening here:

The wrapper (or vessel) is optional but useful for consistent layout, shared assets, and common scripts/styles across pages. Use the tag in your wrapper to indicate where the assembled content should be inserted.

For more advanced routing patterns including regex-based dynamic routes and directory organization, see Dynamic Template Selection in the Templates in Depth section.

## Including HUD-Core

For Server Actions, Reactive Variables, and real-time updates to work, include HUD-Core in your HTML:

<script defer src='https://cdn.jsdelivr.net/gh/spaceport-dev/hud-core.js@latest/hud-core.min.js'></script>

HUD-Core is Launchpad's lightweight (~23KB minified) client-side library that handles websockets, event bindings, DOM updates, and reactivity. It's not required for basic server-rendered pages, but essential for interactivity.

# Core Features

## 1. Templates

Templates are Groovy-powered HTML files (.ghtml) that live in your launchpad/parts/ directory. They use Groovy's native templating syntax to generate dynamic HTML on the server.

Basic Example:

<!-- launchpad/parts/welcome.ghtml -->
<html>
<head>
    <title>Welcome</title>
</head>
<body>
    <h1>Hello, User ${ client.userID }!</h1>
    <p>Current time: ${ new Date() }</p>
</body>
</html>

Built-in Variables:

Every template has access to these variables:

See Template Structure for complete details.

## 2. Server Actions

Server Actions allow you to bind server-side Groovy closures directly to client-side events like click, submit, change, and more. When the event fires, your closure executes on the server with full access to your application logic, database, and session data.

Basic Example:

<button on-click=${ _{ println "Button clicked!" } }>
    Click Me
</button>

When the button is clicked, "Button clicked!" appears in your server logs—no JavaScript required.

With Incoming Transmission:

Server Actions use Spaceport's transmission system—both for receiving client state (the incoming transmission parameter, commonly t) and for sending back instructions to update the UI (the outgoing transmission).

<input type="text" on-input=${ _{ t -> 
    println "User typed: ${t.value}" 
}} />

The incoming transmission (t) provides access to the source element's properties, form data, event information (key presses, mouse position), and other browser state. This rich client context lets you make informed server-side decisions without additional requests.

Updating the UI with Outgoing Transmissions:

<button target="self" on-click=${ _{ "Button was clicked!" }}>
    Click Me
</button>

By returning a value (the outgoing transmission) and using target="self", the button's text updates to "Button was clicked!" when clicked. Outgoing transmissions can be simple strings, maps with multiple DOM updates, or complex instruction sets—all sent to HUD-Core for efficient client-side application.

See Server Actions in Depth for comprehensive coverage of both incoming and outgoing transmissions.

## 3. Reactive Variables

Reactive Variables automatically update the UI when server-side data changes. Launchpad provides two approaches for reactive variables: Reactive Literals and Document Data.

Reactive Literals use ${{ }} syntax, where Launchpad tracks dependencies, detects changes, and updates only the affected DOM regions:

<p>Counter: ${{ dock.counter.getDefaulted(0) }}</p>
<button on-click=${ _{ dock.counter.inc() }}>Increment</button>

When the button is clicked, the counter increments and the

tag updates automatically. No manual DOM updates, no state synchronization code—it just works.

Document Data uses the .cdata() method combined with the bind attribute for client-side data binding. This approach is particularly useful for hydrating forms, passing configuration objects, or synchronizing multiple elements with a single data source:

<%
    out << ['username': 'alice', 'status': 'active'].cdata()
%>
<input bind="username" />
<div bind="status"></div>

Both reactive approaches can work together—you can even combine them by using .cdata() inside a ${{ }} block for powerful data synchronization patterns.

See Reactive Variables in Depth for comprehensive coverage of Reactive Literals, and explore the Advanced Topics section for Document Data patterns.

## 4. Server Elements

Server Elements are reusable, full-stack components defined as Groovy classes. They encapsulate HTML structure, CSS styling, JavaScript behavior, and server-side logic into single, composable units that feel like native HTML elements.

Basic Usage:

<g:star-rating value="4" on-change=${ _{ t -> 
    dock.ratings.put('product-123', t.value) 
}}></g:star-rating>

But Server Elements are far more powerful than simple custom tags. They can:

Maintain Internal State: Each element instance can track its own state separately from the global dock, making them truly encapsulated and reusable across the page without conflicts.

Process Server-Side Logic: Before rendering, Server Elements can query databases, call services, perform calculations, or make decisionsâ€"the HTML they generate is the result of full server-side computation.

Self-Contain Styling and Scripts: Include scoped CSS and JavaScript directly in the element definition, ensuring styles don't leak and behavior is bundled with structure.

Expose Client and Server Functions: Server Elements can define both client-side JavaScript functions and server-side Groovy functions that are callable from your front-end code. This bridges the client-server divide elegantly—you can invoke server logic directly from JavaScript without writing API endpoints, while also providing rich client-side interactivity. Both function types are available in your normal JavaScript, making Server Elements feel like native, full-featured components with seamless server communication.

Server Elements deserve their own deep dive. See the Server Elements documentation for complete details on creating custom elements, handling lifecycle events, and advanced composition patterns.

# Templates in Depth

Launchpad templates are HTML-first—you write standard HTML, CSS, and JavaScript, then enhance it with Groovy where needed. This section covers the built-in variables available in every template, how to compose templates together, working with vanilla web technologies, and the Groovy syntax you'll use to create dynamic content.

## Escaping Dollar Signs

Since Groovy uses $ for expressions, every literal dollar sign must be escaped with a backslash (\$) in your templates—regardless of whether it appears in HTML, CSS, or JavaScript embedded in the template.

This only applies to code embedded directly in .ghtml files. External JavaScript and CSS files linked via - Check that you're modifying the Cargo object (.set(), .inc(), etc.), not replacing it - Verify the websocket connection is active (check browser console)

<!-- Wrong: Doesn't trigger reactivity -->
<button on-click=${ _{ dock.counter = 5 }}>Set</button>

<!-- Right: Triggers reactivity -->
<button on-click=${ _{ dock.counter.set(5) }}>Set</button>

## Server Actions Not Firing

Problem: Clicking elements doesn't trigger Server Actions

Solutions: - Check browser console for JavaScript errors - Verify HUD-Core is loaded - Ensure the on-* attribute is properly formatted: on-click=${ _{ ... }} - Check that the Server Action closure is syntactically correct

## Template Compilation Errors

Problem: Templates fail to compile

Solutions: - Check for unbalanced <% %> or ${ } tags - Verify Groovy syntax is correct inside scriptlets - Look at the server logs for detailed error messages - Enable debug mode for more verbose output

## Session Loss

Problem: dock data disappears between requests

Solutions: - Verify session management is configured correctly - Check that cookies are enabled in the browser - Ensure the dock is being used properly in Server Actions - Consider using Cargo mirrored to Documents for persistent storage beyond sessions

# Next Steps

Now that you understand Launchpad's core concepts, explore these advanced topics:

For a hands-on introduction, try the Tic-Tac-Toe Tutorial, which demonstrates Launchpad's capabilities in a simple, complete application.

# Summary

Launchpad is Spaceport's answer to modern UI development challenges. It provides:

By keeping logic on the server and minimizing JavaScript, Launchpad enables you to build sophisticated, interactive web applications with less code, better security, and faster development cycles. The result is a development experience that combines the best aspects of server-side and client-side frameworks without the complexity of either.

Welcome to the future of web development. Welcome to Launchpad.