2025-11-12 17:36:58 +01:00

14 KiB

theme, background, title, class, drawings, transition, mdc
theme background title class drawings transition mdc
default /galaxy.jpg Datastar text-center
persist
false
slide-left true

To The Stars with Datastar

An interstellar journey


background: /galaxy.jpg

Drake Formular

$$ {1|2|3|4|5|6|7|all} \begin{aligned} N &= R_* \cdot f_p \cdot n_e \cdot f_l \cdot f_i \cdot f_c \cdot L \ R_* &= \text{rate of star formation} \ f_p &= \text{fraction of stars with planets} \ n_e &= \text{number of habitable planets per star} \ f_l &= \text{fraction where life develops} \ f_i &= \text{fraction where intelligent life evolves} \ f_c &= \text{fraction that develops detectable technology} \ L &= \text{length of time civilizations are detectable} \end{aligned}



</div>

---
class: text-center
---

<h2 v-click class="absolute top-4 left-1/2 -translate-x-1/2">The "Drake" Formular of Webtechnologies</h2>

<div class="mt-20">

$$ {1|all}
\begin{aligned}
N_w &= D_b \cdot L_b \cdot F_b \cdot P_t \cdot F_f \cdot S_m \cdot C_{ss} \cdot C_l \cdot H_p  \\
\\
N_w &= \text{Total Possible Tech Stacks} \\
D_b &= \text{databases (PostgreSQL, MongoDB, MySQL...)} \\
L_b &= \text{backend languages (Javascript, Python, Go...)} \\
F_b &= \text{backend frameworks (Express, Django, FastAPI...)} \\
P_t &= \text{transport protocols (REST, GraphQL, gRPC...)} \\
F_f &= \text{frontend frameworks (React, Vue, Svelte...)} \\
S_m &= \text{state management (Redux, Zustand, Pinia...)} \\
C_{ss} &= \text{CSS frameworks (Tailwind, UnoCSS, Bootstrap...)} \\
C_l &= \text{component libraries (shadcn, MUI, Ant Design...)} \\
H_p &= \text{hosting platforms (Vercel, AWS, VPS...)} \\
\end{aligned}
--- class: default ---

The Space of Webtechnologies

 
\begin{aligned}
N_w &= ( D_b ,  L_b , F_b , P_t , F_f , S_m , C_{ss} , C_l , H_p )  \\
\\
\end{aligned}
  • Every website or web application is one star in this space.
  • There are many combinations that work well. While others no so much.
  • We all plot our path in this space. And have our current home there.
  • There are clusters in this space, i.e. the React-Cluster, oder Angular or Vue.
  • My current home is in the L-O-B with Go and Vue vicinity.
  • There is an old Cluster called Hypermedia. Where all Webapps once lived.
  • Hypermedia has developed a new bulge called HTMX.
  • Next to it is a new tiny blob, called Datastar.

class: text-center

My name is

Thomas Hedeler

A holistic developer


class: default transition: fade-out

How did I find Datastar? What is my motivation?

Finding my combination of web technologies for a minimal viable web application.

  • Part 1: The Database: SQLite
  • Part 2: The No-ORM ORM - A very simple Data Abstraction Layer.
  • Part 3: Developing a Web Server Application in Go.
  • Part 4: Datastar - a lightweight framework for real-time collaborative web apps.
  • Part 5: Modern HTML and modern CSS.
  • Part 6: Web components.
  • Part 7: Simple Deployments with a VPS, Nginx, Certbot and a single binary file.

class: default transition: fade-out

Part 1: SQLite:

It is fast, feature complete* and rock solid.

It is not SQ-Lite, it is SQL-ite

Since everybody knows SQLite, today just a few highlights:

  • It has JSON and JSONB as built-in data types.
  • It has 29 new functions to extract from JSON or to create JSON objects.
  • It's CTEs make SQL Turing complete.
  • The SQLite CLI can be used to execute "SQL-scripts". See demo.

* It lacks features essential for a client-server environment, primarily multi-user concurrent write access, built-in security and user management, and some advanced data types.

* from my pov and for my needs and purposes
--- class: default transition: fade-out ---

Part 2: A very simple Data Abstraction Layer:

Features:

  • Simplified Database Lifecycle Management.
  • A 'Record' Data Type for Generic Data Handling.
  • High-Level CRUD Operations.
  • Fluent Transaction API.
  • Abstraction and Safety.
  • Utility Functions.
--- class: default transition: fade-out ---

Part 3: Developing a Web Server Application in Go.

Why Go?

  • Go is a compiled language that generates native machine code.
  • Go's core strength is its built-in, lightweight concurrency model using goroutines and channels.
  • Go has a small, well-defined specification and a deliberately simple syntax.
  • The standard library is comprehensive, especially for web development.
  • Go compiles into a single, static binary with no external dependencies.
  • Go is simple, just 25 reserved words in the language.
  • Can embed the database engine (modernc/sqlite)
  • Can serve static code from embeded folders and files.
  • Can embed other resources, like sql files or template files.
  • Has a built-in templating engine.

layout: quote transition: fade-out

Part 4: Datastar

Build reactive web apps that stand the test of time

Datastar is a lightweight framework for building everything from simple sites to real-time collaborative web apps.

Quote Gillian Delany: 

The problem is Datastar is actually a backend agnostic backend framework with a 10 Kb shim. There has never been anything like it in practice. So it is hard to explain.


class: default


class: default

Reducing the Network to a Function Call

{
    const { data, error } = await to(fetch("https://api.example.com/api/board"));
    if (error) {
      // handle error
      return;
    }
    // handle data
}
{
    const { data, error } = await to(fetch("https://api.example.com/api/users/12"));
    if (error) {
      // handle error
      return;
    }
    // handle data
}

// the function that "unwraps" the promise:
export function to(promise: Promise<Response>) {
  return promise
    .then((response) => response.json())
    .then((data) => ({ data, error: null }))
    .catch((error) => ({ data: null, error }));
}


class: default

HTTP - Protocol

POST https://api.example.com/api/users/search?page=2&limit=10 HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Cookie: sessionId=abc123; theme=dark
Content-Length: 89
{
body: data for the search request
}

class: default

SSE - Server-Sent Events

GET https://api.example.com/api/events/stream HTTP/1.1
Host: api.example.com
Accept: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Response:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
event: message
data: {"user": "Alice", "action": "joined"}
event: update
data: {"count": 42}
data: Multi-line
data: message example

layout: two-cols layoutClass: gap-16

HTTP Communication

sequenceDiagram
    participant Browser
    participant Backend
    
    Note over Browser,Backend: Traditional HTTP (Polling)
    Browser->>Backend: GET /api/data
    Backend-->>Browser: Response with data
    Note over Browser: Wait...
    Browser->>Backend: GET /api/data
    Backend-->>Browser: Response with data
    Note over Browser: Wait...
    Browser->>Backend: GET /api/data
    Backend-->>Browser: Response with data

::right::

SSE Communication

sequenceDiagram
    participant Browser
    participant Backend
    
    Note over Browser,Backend: Server-Sent Events (SSE)
    Browser->>Backend: GET /api/events (Accept: text/event-stream)
    Backend-->>Browser: 200 OK (Connection open)
    Note over Backend,Browser: Connection stays open
    Backend-->>Browser: event: updatedata: {...}
    Backend-->>Browser: event: updatedata: {...}
    Backend-->>Browser: event: updatedata: {...}
    Note over Browser,Backend: Real-time updates without new requests

layout: default transition: fade-out

Hypermedia

  • The Representation is the Data: The representation (e.g., the HTML document) delivered from the server to the client contains all the data needed for that specific application state.

  • Presentation and Links are Embedded: Crucially, not only is the raw data embedded, but also the presentation instructions (via CSS or HTML structure) and, most importantly for the workflow, the hypermedia controls (links and forms) that define the next possible state transitions.

  • Hypermedia as the Engine of Application State (HATEOAS): This is the central feature of the workflow. The representations sent from the server must include hyperlinks and/or forms that indicate the valid next state transitions (the available actions) the client can take. The client does not use pre-compiled knowledge of the workflow; it is driven by the links provided in the current document.


layout: two-cols layoutClass: gap-2

graph TD
    Start([Client Starts]) --> GetProducts[GET /products]
    
    GetProducts --> ProductResp["Response: Product List<br/>links:<br/>add-to-cart: /cart/items<br/>self: /products"]
    
    ProductResp --> AddCart[POST /cart/items]
    
    AddCart --> CartResp["Response: Cart Updated<br/>links:<br/>self: /cart<br/>update-item: /cart/items/id<br/>remove-item: /cart/items/id<br/>checkout: /checkout"]
    
    CartResp --> Decision1{Client Action}
    Decision1 -->|Continue Shopping| GetProducts
    Decision1 -->|Proceed| Checkout[POST /checkout]
    
    Checkout --> CheckoutResp["Response: Checkout Session<br/>links:<br/>payment: /payment<br/>cancel: /cart"]

    

::right::

graph TD
    CheckoutResp["Response: Checkout Session<br/>links:<br/>payment: /payment<br/>cancel: /cart"] --> Payment[POST /payment]
    
    Payment --> PaymentResp["Response: Payment Success<br/>links:<br/>order: /orders/id<br/>track: /orders/id/tracking<br/>invoice: /orders/id/invoice"]
    
    PaymentResp --> GetOrder[GET /orders/id]
    
    GetOrder --> OrderState{Order State}
    
    OrderState -->|Pending| PendingResp["Response: Order Pending<br/>links:<br/>self: /orders/id<br/>cancel: /orders/id/cancel<br/>track: /orders/id/tracking"]
    
    OrderState -->|Shipped| ShippedResp["Response: Order Shipped<br/>links:<br/>self: /orders/id<br/>track: /orders/id/tracking<br/>return: /orders/id/return"]
    
    OrderState -->|Delivered| DeliveredResp["Response: Order Delivered<br/>links:<br/>self: /orders/id<br/>return: /orders/id/return<br/>review: /orders/id/review"]
    
    PendingResp --> End([Workflow Complete])
    ShippedResp --> End
    DeliveredResp --> End

    

class: default

Learn Some Templating System:

Concept Example Meaning
Interpolation {{ name }} Insert value of name
Loop {% for item in items %}...{% endfor %} Repeat block for each item
Condition {% if logged_in %}Welcome{% endif %} Conditional rendering
Include {% include 'header.html' %} Reuse a subtemplate
Escaping {{{ raw_html }}} or {{& raw_html}} Control HTML escaping

class: default

Templating and Hypermedia:

Templating Hypermedia as the Engine of Application State
Input Data Data + available transitions
Output Document (HTML) Document representing a state with actions
Function Bind data to structure Bind state transitions to structure
Goal Present information Drive navigation and state evolution
Mechanism Placeholder substitution Link/form embedding
Example {{.Title}} → “Article” <a href="{{.Links.Edit}}">Edit</a>

layout: image image: /mariner.png transition: slide-up level: 2

to be continued ...