---
# try also 'default' to start simple
theme: default
# random image from a curated Unsplash collection by Anthony
# like them? see https://unsplash.com/collections/94734566/slidev
background: assets/galaxy.jpg
# some information about your slides (markdown enabled)
title: Datastar
# apply UnoCSS classes to the current slide
class: text-center
# https://sli.dev/features/drawing
drawings:
persist: false
# slide transition: https://sli.dev/guide/animations.html#slide-transitions
transition: slide-left
# enable MDC Syntax: https://sli.dev/features/mdc
mdc: true
---
# To The Stars with Datastar
An interstellar journey
---
background: assets/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}
$$
---
class: text-center
---
The "Drake" Formular of Webtechnologies
$$ {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.
* 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.
- 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
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
---
# Term-Soup:
ADR, core+plugins, Signals, Ideomorph, Core-Engine, Plug-ins, SSE,
You have to control the backend, Templating, HTMX, Hypermedia, Hateoas,
Locality of behaviour,
Declarative vs. Imperative, DS conforms strictly to the web's specs.
---
class: default
---
# Reducing the Network to a Function Call
```js
{
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) {
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
#
```mermaid { scale: 0.6}
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
#
```mermaid { scale: 0.6}
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: two-cols
layoutClass: gap-2
---
```mermaid { scale: 0.4}
graph TD
Start([Client Starts]) --> GetProducts[GET /products]
GetProducts --> ProductResp["Response: Product List
links:
add-to-cart: /cart/items
self: /products"]
ProductResp --> AddCart[POST /cart/items]
AddCart --> CartResp["Response: Cart Updated
links:
self: /cart
update-item: /cart/items/id
remove-item: /cart/items/id
checkout: /checkout"]
CartResp --> Decision1{Client Action}
Decision1 -->|Continue Shopping| GetProducts
Decision1 -->|Proceed| Checkout[POST /checkout]
Checkout --> CheckoutResp["Response: Checkout Session
links:
payment: /payment
cancel: /cart"]
```
::right::
```mermaid { scale: 0.4}
graph TD
CheckoutResp["Response: Checkout Session
links:
payment: /payment
cancel: /cart"] --> Payment[POST /payment]
Payment --> PaymentResp["Response: Payment Success
links:
order: /orders/id
track: /orders/id/tracking
invoice: /orders/id/invoice"]
PaymentResp --> GetOrder[GET /orders/id]
GetOrder --> OrderState{Order State}
OrderState -->|Pending| PendingResp["Response: Order Pending
links:
self: /orders/id
cancel: /orders/id/cancel
track: /orders/id/tracking"]
OrderState -->|Shipped| ShippedResp["Response: Order Shipped
links:
self: /orders/id
track: /orders/id/tracking
return: /orders/id/return"]
OrderState -->|Delivered| DeliveredResp["Response: Order Delivered
links:
self: /orders/id
return: /orders/id/return
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” | `Edit` |
---
layout: image
image: assets/mariner.png
transition: slide-up
level: 2
---
# to be continued ...