M external-rss.org.in +67 -50
@@ 4,13 4,7 @@ 
 
 
   :FEEDSTATUS:
-(("https://rollenspiel.social/@ArneBab/113905185226088211" t
-  "5e5e5efd8853e10816a39f6caca9d8a0b1279f30")
- ("https://rollenspiel.social/@ArneBab/113908150719483890" t
-  "d53a98ce8044ef1d4339ad1631a7e491c61052d8")
- ("https://rollenspiel.social/@ArneBab/113908484891556195" t
-  "3c0676c047f5ab46790896a09cc7aba415b7b3e7")
- ("https://rollenspiel.social/@ArneBab/113911947759653100" t
+(("https://rollenspiel.social/@ArneBab/113911947759653100" t
   "57fc93e5583fa969fc072b3f3511a9dd49ed066d")
  ("https://rollenspiel.social/@ArneBab/113912533748230829" t
   "26f2ca4a4b3e030f06b8b7ba311c7b6a90e4fbb6")

          
@@ 43,8 37,73 @@ 
  ("https://rollenspiel.social/@ArneBab/113928183160859160" t
   "9813ff9e6ae80902acfe144de78bbeef6028bf51")
  ("https://rollenspiel.social/@ArneBab/113928330976106989" t
-  "ba23418eab2246b7f7abfc210595602356cc5499"))
+  "ba23418eab2246b7f7abfc210595602356cc5499")
+ ("https://rollenspiel.social/@ArneBab/113931550571887082" t
+  "07cc8e2e852b7055f4ad0544134634aa116560a2")
+ ("https://rollenspiel.social/@ArneBab/113931692453075790" t
+  "4ca424fb7f7aa57a0ca11e5e74a5a205fbb88f1c")
+ ("https://rollenspiel.social/@ArneBab/113934259078944861" t
+  "565eabb649207e5a2dc4cbbd1b20a561a459d148"))
   :END:
+** [2025-02-02 So 12:20]
+  Simple endpoint definition with #Wisp:
+
+
+https://www.draketo.de/software/wisp-snippets#simple-endpoint
+
+
+Enabling endpoint definition as with Java Spring or Python Flask in
+just 64 lines of Scheme.
+
+
+Click the "See Sexp/Scheme Version" toggle to get it in vanilla
+Scheme.
+
+
+#webdev programming
+
+  [[https://rollenspiel.social/@ArneBab/113934259078944861]]
+
+
+** [2025-02-02 So 01:27]
+  @spritely @cwebber And yes: it includes Hoot as practical deployment
+method ☺
+
+🦉
+
+  [[https://rollenspiel.social/@ArneBab/113931692453075790]]
+
+
+** [2025-02-02 So 00:51]
+  @spritely @cwebber My conversion of #Wisp in 64 pages to pure #Scheme
+is now done:
+
+https://www.draketo.de/software/programming-scheme
+
+⇒ print: https://www.draketo.de/software/programming-scheme.pdf
+
+
+Naming and Logic:
+
+#programming essentials with Scheme
+
+
+And still in time for the minimalist and #FOSDEM declarative languages
+devroom ☺:
+
+
+64 pages (that work on A6 paper) to go from the first define to
+packaging and deploying your project.
+
+
+Licensed cc by-sa and written in #Emacs #orgmode
+
+
+I need to get a printing proof, then this will actually be a book.
+
+  [[https://rollenspiel.social/@ArneBab/113931550571887082]]
+
+
 ** [2025-02-01 Sa 11:12]
   Die Bild erzählt jetzt Dolchstoßlegenden.
 

          
@@ 351,48 410,6 @@ Und es gibt Leute, die ihn als Bundeskan
   [[https://rollenspiel.social/@ArneBab/113911947759653100]]
 
 
-** [2025-01-28 Di 23:05]
-  Grundantriebe Miniskizzen, 3/18:
-
-
-„Ich bin bescheiden“
-
-
-#pnpde
-
-  [[https://rollenspiel.social/@ArneBab/113908484891556195]]
-
-
-** [2025-01-28 Di 21:40]
-  politik
-
-
-----------------------------------------------------------------------------
-
-Lösungen, nicht nur Signale:
-
-https://www.draketo.de/politik/kommentare#loesungen-nicht-nur-signale
-
-
-#habeck btw25
-
-  [[https://rollenspiel.social/@ArneBab/113908150719483890]]
-
-
-** [2025-01-28 Di 09:06]
-  Während wir alle über den geplanten Verrat der CDU an der Demokratie
-reden: sollte es diese Woche nicht eigentlich eine Debatte über ein
-AfD-Verbot geben?
-
-
-Habt ihr davon was gehört?
-
-
-Oder versucht die CDU das Thema unter den Tisch zu kehren?
-
-  [[https://rollenspiel.social/@ArneBab/113905185226088211]]
-
-
 
 * Gute Neuigkeiten
 

          
M politik/kommentare.org +15 -0
@@ 32,6 32,21 @@ Genug der Vorrede.
 
 #+toc: headlines 2
 
+* Ein Kopf eine Stimme
+  :PROPERTIES:
+  :CUSTOM_ID: eine-stimme
+  :END:
+
+Arme Leute haben eigentlich genau so viele Stimmen bei der Wahl wie
+Reiche. Dass sie keine Lobby haben, ist daher ein Kommunikations-,
+Informations- und Organisationsproblem.
+
+Was nicht heißen soll, dass es ein kleines Problem ist. Im Gegenteil:
+[[file:herausforderungen-technisch-sozial][soziale Probleme sind oft die härtesten]]. Das zu lösen ist aber ein
+wichtiger Punkt, um unsere Demokratie resilient zu erhalten.
+
+[2025-02-02 So]
+
 * Danke Antje Tillmann
   :PROPERTIES:
   :CUSTOM_ID: tillmann-gegen-faschismus

          
M software.org +2 -2
@@ 15,7 15,7 @@ 
 
 
 #+BEGIN_SRC sh :eval yes :exports results :results output raw
-    for i in $(ls software | grep \\.org$ | grep "^guix-work.org\\|^guix-config.org\\|^wisp.org\\|^guile-10x.org\\|^guile-snippets.org\\|^guile-capture-stdout-stderr.org\\|^guile-fast.org\\|^zen-for-scheme.org\\|^wisp-code-katas.org\\|^wisp-snippets.org\\|^advent-of-wisp-code-2021.org\\|^programming-with-wisp.org\\|^install-on-guix.org\\|^package-guix.org\\|^programming-basics-wisp.org" | sort -h); do echo '- [[file:software/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "software/$i" | sed 's/#+title: *//'); done
+    for i in $(ls software | grep \\.org$ | grep "^guix-work.org\\|^guix-config.org\\|^wisp.org\\|^guile-10x.org\\|^guile-snippets.org\\|^guile-capture-stdout-stderr.org\\|^guile-fast.org\\|^zen-for-scheme.org\\|^wisp-code-katas.org\\|^wisp-snippets.org\\|^advent-of-wisp-code-2021.org\\|^programming-with-wisp.org\\|^programming-scheme.org\\|^install-on-guix.org\\|^package-guix.org\\|^programming-basics-wisp.org" | sort -h); do echo '- [[file:software/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "software/$i" | sed 's/#+title: *//'); done
 #+END_SRC
 
 

          
@@ 70,7 70,7 @@ 
 
 
 #+BEGIN_SRC sh :eval yes :exports results :results output raw
-   for i in $(ls software | grep \\.org$ | grep -v "^vorlesung-verteilte-systeme.org\\|^vorlesung-netztechnik.org\\|^p2p-talk.org\\|^decentralized-moderation.org\\|^kontaktinfos-mit-gnupg.org\\|^freenet-hidden-channel.org\\|^guix-work.org\\|guix-config.org\\|letterblock-diceware.org\\|^wisp.org\\|^guile-10x.org\\|^guile-snippets.org\\|^guile-capture-stdout-stderr.org\\|^guile-fast.org\\|^zen-for-scheme.org\\|^shell-tricks\\|^mercurial-branching-strategy\\|^emacs-javascript.org\\|^wisp-code-katas.org\\|^wisp-snippets.org\\|^advent-of-wisp-code-2021.org\\|^org-mode-tipps\\|^emacs-tipps\\|^package-guix.org\\|^programming-with-wisp.org\\|^programming-basics-wisp.org\\|^putins-kriegsrede.org\\|^install-on-guix.org\\|^package-guix.org\\|^org-mode.org\\|^emacs-daytime.org\\|^emacs-javascript.org\\|^intellij-emacs.org\\|^mercurial-ediff3-emacs.org\\|^orgmode-markdown.org\\|^ferienplan.org\\|^latex-awesome.org\\|^latex-list-of-links.org\\|^stundenplan-wochenplan-latex.org\\|^privacy-embed.org\\|^stream-over-freenet\\|^video-channel-hyphanet.org\\|^m3u-player.org\\|^find-dorktower.org\\|^ffmpeg-compression-vp9-av1.org\\|^comment-your-code.org\\|^gpl-or-later.org\\|^langsame-simple-werkzeuge.org\\|^slow-simple-tools.org\\|^optimize-for-firefox.org\\|^programs-you-can-still-hack-when-dumb.org\\|^tinkering-stability.org\\|^volatile-infrastructure.org\\|^typescript-risks.org\\|^hurd-authorization-translator.org\\|^keyboard-layout-evolution.org" | sort -h); do echo '- [[file:software/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "software/$i" | sed 's/#+title: *//'); done
+   for i in $(ls software | grep \\.org$ | grep -v "^vorlesung-verteilte-systeme.org\\|^vorlesung-netztechnik.org\\|^p2p-talk.org\\|^decentralized-moderation.org\\|^kontaktinfos-mit-gnupg.org\\|^freenet-hidden-channel.org\\|^guix-work.org\\|guix-config.org\\|letterblock-diceware.org\\|^wisp.org\\|^guile-10x.org\\|^guile-snippets.org\\|^guile-capture-stdout-stderr.org\\|^guile-fast.org\\|^zen-for-scheme.org\\|^shell-tricks\\|^mercurial-branching-strategy\\|^emacs-javascript.org\\|^wisp-code-katas.org\\|^wisp-snippets.org\\|^advent-of-wisp-code-2021.org\\|^org-mode-tipps\\|^emacs-tipps\\|^package-guix.org\\|^programming-with-wisp.org\\|^programming-scheme.org\\|^programming-basics-wisp.org\\|^putins-kriegsrede.org\\|^install-on-guix.org\\|^package-guix.org\\|^org-mode.org\\|^emacs-daytime.org\\|^emacs-javascript.org\\|^intellij-emacs.org\\|^mercurial-ediff3-emacs.org\\|^orgmode-markdown.org\\|^ferienplan.org\\|^latex-awesome.org\\|^latex-list-of-links.org\\|^stundenplan-wochenplan-latex.org\\|^privacy-embed.org\\|^stream-over-freenet\\|^video-channel-hyphanet.org\\|^m3u-player.org\\|^find-dorktower.org\\|^ffmpeg-compression-vp9-av1.org\\|^comment-your-code.org\\|^gpl-or-later.org\\|^langsame-simple-werkzeuge.org\\|^slow-simple-tools.org\\|^optimize-for-firefox.org\\|^programs-you-can-still-hack-when-dumb.org\\|^tinkering-stability.org\\|^volatile-infrastructure.org\\|^typescript-risks.org\\|^hurd-authorization-translator.org\\|^keyboard-layout-evolution.org" | sort -h); do echo '- [[file:software/'$i']['$(basename $i .org)']]' - $(grep '#+title:' "software/$i" | sed 's/#+title: *//'); done
 #+END_SRC
 
 

          
M software/guile-snippets.org +0 -1
@@ 574,4 574,3 @@ to [[https://docs.python.org/2/tutorial/datastructures.html#list-comprehensions][Python’s list-comprehensions]].
 #+end_src
 
 [2025-01-17 Fr]
-

          
M software/naming-and-logic-map-of-scheme--with-border.png +0 -0

        
M software/programming-basics-wisp.org +1 -0
@@ 2576,6 2576,7 @@ to take on challenges by code.
 # override template options:
 #+options: toc:nil H:2 ^:t
 #+latex_class_options: [a5paper]
+
 #+MACRO: if-latex-else (eval (if (org-export-derived-backend-p org-export-current-backend 'latex) "#+OPTIONS: num:t" "#+OPTIONS: num:nil"))
 {{{if-latex-else}}}
 # Newline macro {{{NEWLINE}}} - does not start a new paragraph, so both lines stay on the same page

          
M software/programming-scheme.org +14 -41
@@ 1,10 1,10 @@ 
 #+INCLUDE: ../org-templates/level-1.org
-#+title: Naming and Logic@@html: (Scheme)@@
+#+title: Naming and Logic (Scheme)
 #+subtitle: programming essentials with Scheme
-# #+DATE: <2025-01-31 Fr>
+#+DATE: <2025-01-31 Fr>
 # for book export only, undo and switch back to the above after export
 #+latex_header: \usepackage{ccicons}
-#+DATE: @@latex:\texorpdfstring{\ccbysa}{cc by-sa}@@ @@html:@@
+# #+DATE: @@latex:\texorpdfstring{\ccbysa}{cc by-sa}@@ @@html:@@
 #+LANGUAGE: en
 
 

          
@@ 25,7 25,8 @@ is currently being built by the folks at
 # Tooling for website and book
 #+begin_src bash :exports none :results output
 # create thumbnail
-gs -dNOPAUSE -dBATCH -sDEVICE=png16m -r200 -dDownScaleFactor=8 -dFirstPage=1 -dLastPage=1 -sOutputFile=programming-basics-wisp--no-border.png programming-basics-wisp.pdf
+gs -dNOPAUSE -dBATCH -sDEVICE=png16m -r200 -dDownScaleFactor=8 -dFirstPage=1 -dLastPage=1 -sOutputFile=programming-basics-wisp--no-border.png programming-scheme.pdf
+# gs -dNOPAUSE -dBATCH -sDEVICE=png16m -r600 -dDownScaleFactor=8 -dFirstPage=1 -dLastPage=1 -sOutputFile=programming-basics-wisp--no-border2.png programming-scheme.pdf
 # then add the colored border with gimp
 # add a border around the map of scheme for the title (so it is not cut off)
 convert -bordercolor white -border 60 naming-and-logic-map-of-scheme.png naming-and-logic-map-of-scheme--with-border.png

          
@@ 37,15 38,6 @@ pdfjam programming-basics-wisp.pdf 67 -o
 # https://unix.stackexchange.com/a/701584/34896
 #+end_src
 
-#+RESULTS:
-: GPL Ghostscript 9.56.1 (2022-04-04)
-: Copyright (C) 2022 Artifex Software, Inc.  All rights reserved.
-: This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
-: see the file COPYING for details.
-: Unknown .defaultpapersize: (A4).
-: Processing pages 1 through 1.
-: Page 1
-
 # textblock does not work.
 # #+latex_header: \usepackage[absolute]{textpos}
 

          
@@ 143,7 135,7 @@ nil
 # #+latex: Yellow entries are already written.
 
 #+latex: \iffalse
-#+begin_src plantuml :noweb no-export :noweb-ref map-of-scheme-diagram :file naming-and-logic-map-of-scheme-guile.png
+#+begin_src plantuml :noweb no-export :noweb-ref map-of-scheme-diagram :file naming-and-logic-map-of-scheme-guile.png :exports none
 ' title A Map of Scheme: programming basics
 ' scale dpi to fit the width of the page, otherwise the imagemap below is broken
 skinparam dpi 46

          
@@ 323,7 315,6 @@ epilogue --> package
 #+end_src
 
 #+attr_html: :style width:unset;max-width:unset :usemap #plantuml_map :title MapOfScheme
-#+RESULTS:
 [[file:naming-and-logic-map-of-scheme-guile.png]]
 
 

          
@@ 1312,7 1303,7 @@ ice-9 is the name for the core extensions of Guile. It’s a play on
 
 SRFI’s are Scheme Requests For Implementation, portable libraries
 built in collaboration between different Scheme implementations. The
-ones available in Guile can be found [[https://www.gnu.org/software/guile/manual/html_node/SRFI-Support.html][in the Guile reference manual]].
+ones available in Guile can be found [[https://www.gnu.org/software/guile/manual/html_node/SRFI-Support.html][in the Guile Reference manual]].
 More can be found on [[https://srfi.schemers.org/][srfi.schemers.org]]. They are imported by number
 (=:1=) and can have a third component with a name, but that’s not
 required.

          
@@ 2247,6 2238,7 @@ And for the sake of this example, a simp
 #+end_src
 
 
+#+latex: \clearpage
 ** Init a project with =hall=
 :PROPERTIES:
 :CUSTOM_ID: hall

          
@@ 2258,7 2250,9 @@ Hall) as described in the manual under [
 create a new project:
 
 #+begin_src bash
-hall init hello -a "My Name" -e "myName@example.com" --execute
+hall init hello -a "My Name" \
+                -e "myName@example.com" \
+                --execute
 cd hello && hall build --execute
 #+end_src
 

          
@@ 2281,6 2275,7 @@ Then add the rule
 #+end_src
 
 
+#+latex: \clearpage
 * Deploy a project to users
 :PROPERTIES:
 :CUSTOM_ID: deploy

          
@@ 2489,42 2484,20 @@ Guile programs is getting easier. Lilypo
 
 #+latex: \clearpage
 #+begin_export latex
-\emph{»I tend to use [Wisp] as a \textbf{Scheme primer} for colleagues used\\
-\phantom{»}to Python who want to explore the realms of functional programming.\\
-\phantom{»}It makes Scheme way more “approachable”«}\\
-\phantom{»}--- \href{https://emacs.ch/@thees}{Wilko}
-
+\LARGE
 Get the gist of Lisp in practical steps.
 
-\emph{»The more time passes, the more I admire Wisp!«}\\
-\phantom{»}--- Christine Lemmer-Webber from Spritely Institute.
-
 This book guides you into \textbf{the heart of programming} with Scheme,
-using the approachable equivalent syntax of \textit{Wisp}
-to smooth the start of your journey into one of the oldest
+to give you a smooth start into one of the oldest
 standardized and thriving languages.
 
-\emph{»Wisp allows people to see code how Lispers perceive it.\\
-\phantom{»}Its structure becomes apparent.«}\\
-\phantom{»}--- Ricardo Wurmus about reproducible science \href{https://www.guixwl.org/manual/gwl.html}{with GWL}.
-
 We are the namegivers,\\
 the dreamers who build tools of sand and logic\\
 to \textbf{surpass the limits of our minds}.
 
-\emph{»I expected Wisp to be more of a fun toy\\
-\phantom{»}to play around with and kind of just discard,\\
-\phantom{»}but I have actually found it insanely useful\\
-\phantom{»}to getting stuff done.«}\\
-\phantom{»}--- \href{https://tech.lgbt/@donkeyblam}{kb}
-
 Choose your path\\
 through \textbf{a map of building blocks}\\
 to take on challenges by code.
-
-\emph{»I love the syntax of Python, but crave\\
-\phantom{»}the simplicity and power of Lisp.«}\\
-\phantom{»}--- Arne Babenhauserheide
 #+end_export
 
 #+latex: \thispagestyle{empty}

          
M software/wisp-snippets.org +221 -0
@@ 498,6 498,7 @@ pretty-print
 
 #+html: </div></div>
 
+#+attr_html: :style font-size:x-small
 #+begin_example
 GNU Guile 3.0.8
 Copyright (C) 1995-2021 Free Software Foundation, Inc.

          
@@ 584,6 585,223 @@ apply map list '((1 2) (1 3))
 [2023-07-05 Mi]
 
 
+* Simple endpoint definition
+  :PROPERTIES:
+  :CUSTOM_ID: simple-endpoint
+  :END:
+
+If you want simple top-level endpoint definition in your backend as
+you’re used to from annotations in Spring or Python (or ...)
+frameworks like the following, you can do that in under 64 lines.
+
+#+begin_src wisp
+define-handler 'GET "/health" : get-health-handler request body
+   ...
+#+end_src
+
+Just define your handlers and add a simple syntax rule that selects from them:
+
+#+html: <div class="toggled"><input id="q2" type="checkbox">
+#+html: <div class="scheme"><p><strong>Sexp/Scheme-Version</strong>. <label for="q2">See Wisp Version</label></p>
+
+#+latex_header: \usepackage{comment}
+#+latex: \begin{comment}Sext/Scheme-version
+
+#+begin_src scheme
+;; an alist of handlers: path-prefix . procedure
+(define put-handlers '())
+(define get-handlers '())
+(define post-handlers '())
+(define patch-handlers '())
+(define delete-handlers '())
+;; adding a handler
+(define (register-handler method path-prefix proc)
+    (cond
+        ((equal? method 'GET)
+         (set! get-handlers (cons (cons path-prefix proc) get-handlers)))
+        ((equal? method 'PUT)
+         (set! put-handlers (cons (cons path-prefix proc) put-handlers)))
+        ((equal? method 'POST)
+         (set! post-handlers (cons (cons path-prefix proc) post-handlers)))
+        ((equal? method 'PATCH)
+         (set! patch-handlers (cons (cons path-prefix proc) patch-handlers)))
+        ((equal? method 'DELETE)
+         (set! delete-handlers (cons (cons path-prefix proc) delete-handlers)))
+        (else #f)))
+;; finding a matching handler
+(define (find-handler method path)
+    (cond
+        ((equal? method 'GET)
+         (and=>
+            (find (λ(x) (string-prefix? (car x) path))
+                 get-handlers)
+            cdr))
+        ((equal? method 'PUT)
+         (and=>
+            (find (λ(x) (string-prefix? (car x) path))
+                 put-handlers)
+            cdr))
+        ((equal? method 'POST)
+         (and=>
+            (find (λ(x) (string-prefix? (car x) path))
+                 post-handlers)
+            cdr))
+        ((equal? method 'PATCH)
+         (and=>
+            (find (λ(x) (string-prefix? (car x) path))
+                 patch-handlers)
+            cdr))
+        ((equal? method 'DELETE)
+         (and=>
+            (find (λ(x) (string-prefix? (car x) path))
+                 delete-handlers)
+            cdr))
+        (else #f)))
+;; define-handler provides syntactic sugar for the handler definition sugar
+(define-syntax-rule (define-handler method path-prefix (name request body) rest ...)
+  (begin
+      (define (name request body) rest ...)
+      (register-handler method path-prefix name)
+      name))
+
+;; endpoint definitions with define-handler
+#+end_src
+
+
+#+latex: \end{comment}
+#+html: </div><div class="wisp"><p><strong>Wisp-Version</strong>. <label for="q2">See Sexp/Scheme Version</label></p>
+
+#+begin_src wisp
+;; an alist of handlers: path-prefix . procedure
+define put-handlers '()
+define get-handlers '()
+define post-handlers '()
+define patch-handlers '()
+define delete-handlers '()
+;; adding a handler
+define : register-handler method path-prefix proc
+    cond
+        : equal? method 'GET
+          set! get-handlers : cons (cons path-prefix proc) get-handlers
+        : equal? method 'PUT
+          set! put-handlers : cons (cons path-prefix proc) put-handlers
+        : equal? method 'POST
+          set! post-handlers : cons (cons path-prefix proc) post-handlers
+        : equal? method 'PATCH
+          set! patch-handlers : cons (cons path-prefix proc) patch-handlers
+        : equal? method 'DELETE
+          set! delete-handlers : cons (cons path-prefix proc) delete-handlers
+        else #f
+;; finding a matching handler
+define : find-handler method path
+    cond
+        : equal? method 'GET
+          and=>
+            find : λ(x) : string-prefix? (car x) path
+                 . get-handlers
+            . cdr
+        : equal? method 'PUT
+          and=>
+            find : λ(x) : string-prefix? (car x) path
+                 . put-handlers
+            . cdr
+        : equal? method 'POST
+          and=>
+            find : λ(x) : string-prefix? (car x) path
+                 . post-handlers
+            . cdr
+        : equal? method 'PATCH
+          and=>
+            find : λ(x) : string-prefix? (car x) path
+                 . patch-handlers
+            . cdr
+        : equal? method 'DELETE
+          and=>
+            find : λ(x) : string-prefix? (car x) path
+                 . delete-handlers
+            . cdr
+        else #f
+;; define-handler provides syntactic sugar for the handler definition sugar
+define-syntax-rule : define-handler method path-prefix (name request body) rest ...
+  begin
+      define (name request body) rest ...
+      register-handler method path-prefix name
+      . name
+
+;; endpoint definitions with define-handler
+#+end_src
+
+#+html: </div></div>
+
+
+You can now write your endpoints very naturally. For example the standard =/health= endpoint that Docker looks for:
+
+
+#+begin_src wisp
+define-handler 'GET "/health" : get-health-handler request body
+        . "Health check.
+
+        Endpoint: /health
+
+        Example: GET /health
+                 => OK"
+        values
+            build-response
+                . #:headers `((content-type . (text/plain)))
+            . "OK"
+#+end_src
+
+
+Then just use find-handler where you start the server, for example like this:
+
+#+begin_src wisp
+define : run-ipv4-server handler-with-path ip port
+    run-server handler-with-path 'http `(#:host "localhost"
+                                         #:family ,AF_INET
+                                         #:addr ,INADDR_ANY
+                                         #:port ,port)
+
+define : run-ipv6-server handler-with-path ip port
+    define s
+        let : : s : socket AF_INET6 SOCK_STREAM 0
+            setsockopt s SOL_SOCKET SO_REUSEADDR 1
+            bind s AF_INET6 (inet-pton AF_INET6 ip) port
+            . s
+    run-server handler-with-path 'http `(#:family ,AF_INET6
+                                         #:addr (inet-pton AF_INET6 ip)
+                                         #:port ,port
+                                         #:socket ,s)
+
+define : run-server ip port
+    define : handler-with-path request body
+        define method : request-method request
+        define path : uri-path : request-uri request
+        define handler : find-handler method path
+        if handler
+            let-values : : (headers body) : handler request body wotstate
+                values headers body
+            values
+                build-response
+                  . #:headers `((content-type . (text/plain)))
+                  . #:code 404
+                . "404 not found"
+
+    define ipv6 : string-contains ip ":"
+    format : current-error-port
+           if ipv6
+               . "Started server on http://[~a]:~d\n"
+               . "Started server on http://~a:~d\n"
+           . ip port
+    if ipv6
+         run-ipv6-server handler-with-path ip port
+         run-ipv4-server handler-with-path ip port
+    . #f
+#+end_src
+
+
+[2025-02-02 So]
+
+
 #+setupfile: ../org-templates/level-1-software.org
 # Local Variables:
 # org-confirm-babel-evaluate: nil

          
@@ 594,3 812,6 @@ apply map list '((1 2) (1 3))
 # End:
 # override template options:
 #+options: toc:nil H:1 num:nil ^:nil
+
+#+MACRO: if-latex-else (eval (if (org-export-derived-backend-p org-export-current-backend 'latex) "#+OPTIONS: num:t" "#+OPTIONS: num:nil"))
+{{{if-latex-else}}}