--- # 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 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 Remote Procedure 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 ``` --- class: default --- # Reducing the Network to a Remote Procedure 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 --- # 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 ...