After trying and struggling with the Twine engine, and after having immediate success (and a lot of fun) building my fusion rocket simulator I have decided to set out and adapt my Clay web framework into something that can generate static content.

The idea is that this would work like Twine works, you build an app at a time in markup language. But unlike twine, I'm not targeting a beginner programmer and deciding too early on a domain specific language. This is a tool that includes developing one's OWN domain specific language for the application. I will use Tcl as the build language for the application, with an sqlite backend maintaining the soup of data that maintains references. The application itself, and all of the interactives, will be in pure Javascript. And rather than try to get Javascript to play live with the data, the application will be mainly working with snapshots of data captured in JSON, and packages with the static HTML and images.

I haven't really used the server-side features of etoyoc.com's engine since the folk festival moved their registration system off. And with javascript, interactives can be delivered on a completely static platform. For eBooks and mobile, most distribution venues don't even want to look at installing an executable if it can be avoided.

So how will the "clayground" work? I am assembling a toolkit of software that ships inside of a self-contained executable, or could be loaded by a resident Tcl application installed on the local operating system. As... most of the people I know in the world use Windows, and Windows doesn't ship with one... did I mention the self-contained executable?

This executable the user will point at a series of mark-up files (read those Tcl scripts) which can be edited in your friendly neighborhood copy of notepad. Inside is a language that first describes what your application is, and then what it does. And because I'm building on top of an existing scripting language with a coherent package system, if someone develops a framework useful across a pattern of applications, that entire bundle of tools can be packaged into a plugin.

Currently my fusion rocket simulator looks like this:

Basically it's a virtual file system. The writeup is a cross between a MIME document and a TCL script. At the top are easy to read headers for a Tcl based indexer:

Title: {Design A Starship for the Sublight Universe}
Class: {blog}
Date: {Wed May 26 13:54:15 EDT 2021}
Content-Type: {html}
Format: {clay}
date: {Wed May 26 13:54:15 EDT 2021}
owner: 619eb03b-0f7d-490f-a2ac-9eb72e4c789d
uuid: 57750880-cd29-477d-8498-5f6b79723d30

The content is a script for my ClayHttpd engine.

The magic of this arrangment is that I can embed define new commands mid-script. But this script is running inside of an object that I can ask for help, and that object is itself in contact with the local operating system, and part of a larger application that is aware of the website as a whole. I have a few creature comfort commands to handle common tasks. For instance bolding text, or adding hyperlinks, or calling up Another entry. But for complex things like tables, I can use the object interface.

para {The magic of this arrangment is that I can embed define new commands mid-script. But
this script is running inside of an object that I can ask for help, and that object is itself
in contact with the local operating system, and part of a larger application that is aware
of the website as a whole. I have a few creature comfort commands to handle common tasks.
For instance [bold {bolding text}], or adding [link https://en.wikipedia.org/wiki/Hyperlink hyperlinks],
or calling up [wiki 57750880-cd29-477d-8498-5f6b79723d30 {Another entry}].
But for complex things like tables, I can use the object interface.}

Each page object also gets a pile of data from the build system/live web server that it can read at runtime.

set T [my tag table]
dict for {field value} [my clay get content] {
  set row [$T row]
  $row column $field
  if {$field in {body}} {
    $row column ...
  } else {
    $row column $value
  }
}

title Clay-Ground - An new interactive framework
class blog
date Tue Jun 01 15:20:35 EDT 2021
content-type html
format clay
owner ed44b6ff-12b4-4158-b7ca-03873dd57e42
uuid 416ce7c7-c4f1-4045-b630-eda44642f365
body ...
mtime 1622649287
set T [my tag table]
dict for {field value} [my request dump] {
  set row [$T row]
  $row column $field
  if {$field in {body}} {
    $row column ...
  } else {
    $row column $value
  }
}

That code returns a pretty large result so I've placed it here

A table I can call up as an object, and then add and remove objects under it for the rows and columns. Here is a complex example that builds a live table of data, and delivers it as HTML: table.txt. And I can easily run that same script live in this document:

Point A Point B Distance AU 1 Day DeltaV 7 Day DeltaV 14 Day DeltaV 28 Day DeltaV 60 Day DeltaV
Main Belt Asteroids Mars nearest 0.28 484808 69258 34629 17314 8080
Earth Mars nearest 0.4 692582 98940 49470 24735 11543
Main Belt Asteroids Earth nearest 0.68 1177390 168198 84099 42049 19623
Main Belt Asteroids Venus nearest 0.942 1631032 233004 116502 58251 27183
Main Belt Asteroids Mercury nearest 1.353 2342661 334665 167332 83666 39044
Earth Venus farthest 1.828 3165103 452157 226078 113039 52751
Main Belt Asteroids Jupiter nearest 3.29 5696494 813784 406892 203446 94941
Earth Jupiter nearest 3.97 6873884 981983 490991 245495 114564
Main Belt Asteroids Mercury farthest 5.416 9377572 1339653 669826 334913 156292
Main Belt Asteroids Earth farthest 6.05 10475315 1496473 748236 374118 174588
Main Belt Asteroids Mars farthest 6.61 11444931 1634990 817495 408747 190748
Earth Saturn nearest 8.07 13972859 1996122 998061 499030 232880
Main Belt Asteroids Jupiter farthest 10.41 18024469 2574924 1287462 643731 300407
Earth Saturn farthest 11.22 19426949 2775278 1387639 693819 323782
Main Belt Asteroids Saturn farthest 15.07 26093059 3727579 1863789 931894 434884
Main Belt Asteroids Uranus nearest 16.74 28984593 4140656 2070328 1035164 483076
Earth Uranus farthest 21.2 36706892 5243841 2621920 1310960 611781
Main Belt Asteroids Uranus farthest 25.05 43373002 6196143 3098071 1549035 722883
Main Belt Asteroids Pluto nearest 28.04 48550059 6935722 3467861 1733930 809167
Earth Pluto nearest 28.72 49727450 7103921 3551960 1775980 828790
Earth Neptune farthest 31.5 54540901 7791557 3895778 1947889 909015
Main Belt Asteroids Neptune farthest 35.35 61207011 8743858 4371929 2185964 1020116
Earth Pluto farthest 50.4 87265441 12466491 6233245 3116622 1454424
Main Belt Asteroids Pluto farthest 54.25 93931551 13418793 6709396 3354698 1565525

Now I recognize that some complex interfaces require dynamically building HTML from live data. But I don't think that is the best use of a domain specific language. Pretty much if it's not backed in already, you can use the DOM manipulation tools built into Javascript. Which, as my fusion program shows, can get you really, really far.

My next step is a request from a friend to put together a life D&D character sheet that does all of the calculations so people can spend more time adventuring. I see three basic applications there: One is an interactive character builder for the players. The second is a campaign design/running tool for the DM. And the third is a "collaborative event" module that lets the documents created in the campaign creator and character editor all interact on a battlefield or other scenario. The real fuel for all of that will be that JSON import/export function I added to the fusion rocket tool.

JSON is a just a handy notation for luggable static data. It can be nested, or flat, or nested flat data. But it's per-object. So for the battlefield manager, I would create an object for each of the players, and the monsters the DM has pitted them against, and each object would get a blob of JSON data uploaded to the app. The rules are all implemented in the javascript of the App, and with a few UI tools to allow players to enter their own dice rolls in, we get a nice replacement for the roll-out mat and pile of nebulous tokens. And we can throw this map up on the big-screen in the living room for everyone to enjoy.

On player operates a home computer that uses an HDMI input to the screen (or apple Airplay from a laptop). The other players just lug along their character sheets, or email them to the DM. The DM can email back a transcript of the game's events, and the loot they picked up, for the characters to put back together at home.

When I'm ready to step up my game I can even add graphics.

The idea of the App as the VFS for a website plays well with distributing these tools as eBooks on a Javascript savvy reader. (Though the JSON exchange is probably not going to work.) The fact you are reading this in a browser tells you that clay renders down to static HTML pretty easily too.

What I'm most excited about is porting all of the encyclopedia and world building tools I've developed for the Sublight universe into something I can parse as a website of an eBook. I have a half-assed index and database I build with Microsoft Excel and Graphviz. But the results, because I can only really edit the data in Excel, can look a little wonky. I am working on moving the writeup for each topic to a clay file, and then indexing them ex-post-facto. In that way I can world build bottom up style, like Wikipedia.