studio status report: 2025-07
month 07 of 2025 was about readying the Studio WebAssembly assets for the new b-roll player API
Month 07 of 2025 was about readying the Studio WebAssembly assets for the new b-roll player API released last month. In so doing, the following NuGet packages were updated:
The Obsidian graph view sees seven days spent on Songhay.Modules.Bolero
:
…only two days were taken for Songhay.Modules.Publications
:
…and the graph view sees nothing for Songhay.Modules
; however, GitHub itself (#15) shows one day devoted. We have a total of nine days of Studio-work moments which is a four day increase over last month. Selected notes below should provide some color for the work done this month:
.NET (F♯): List.choose
vs. List.find
The docs show quite clearly that List.find
throws an exception while List.choose
returns an empty list when the item in the list is not found.
I have written a unit test for myself so that I do not forget a few things:
- Lines 18 and 25: auto-generated
.Is*
properties (new in F♯ 9) [📖 docs ] might help to make the syntax understandable for beginners - Lines 32 and 39: a reminder of the
function
shorthand (see “F#: function keyword”) - Line 43 is the
actual
start of the test 😐
When I am feeling spiffy and fastidious, I should move lines 15 through 41 to a Jupyter Notebook #to-do
.NET AI: the Intent Integrity Chain 😐⛓
Using AI with TDD (to make something better than SpecFlow and Cucumber) promises to make machine-generated code far more reliable within the guide rails of a formal specification:
Songhay Modules Publications (F♯): the PresentationDocument
identifies all possible client-side facing document formats used in this Studio 😐🧠💡
It looks like this now:
From the Studio-centric perspective, the only format ‘missing’ above is LaTeX and SGML 😐 This PresentationDocument
needs to be used in the PresentationPart
type:
Staring at PresentationPart
might lead to a question like:
[!question] Do the concepts behind
Pages
andPlaylist
clash/overlap thePresentationDocument
concept?
The short answer is no.
One part of a Presentation
can be a PresentationDocument
of type Html
that loads from the server—and then the client will transform that Html
into Pages
or a Playlist
before rendering for display. A Playlist
can be in many different PresentationDocument
formats and pagination can be applied to many different PresentationDocument
formats.
Alternatively, a part of a Presentation
can be a PresentationDocument
of type Html
(etc.) that loads from the database server to be processed on the server side to add pagination and/or playlist concepts.
FsToolkit.ErrorHandling
Error FS3343
Upgrading FsToolkit.ErrorHandling
to 5.x
broke the build:
Error FS3343 : The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a 'Bind4' method or appropriate 'MergeSources' and 'Bind' methods
This must be because of changes to FsToolkit.ErrorHandling.ResultCE.result
[🔗 GitHub ] such that this is no longer supported:
result {
let! id = (useCamelCase, element) ||> Id.fromInput itemType
and! name = (useCamelCase, element) ||> Name.fromInput itemType
and! displayText = (useCamelCase, element) ||> displayTextGetter itemType
and! resourceIndicator =
match resourceIndicatorGetter with
| Some getter -> ((useCamelCase, element) ||> getter itemType)
| _ -> Ok None
return
{
id = id
itemName = name.toItemName
displayText = displayText
resourceIndicator = resourceIndicator
}
}
…my quick fix is to fall back to non-parallelism, causing a performance hit:
result {
let! id = (useCamelCase, element) ||> Id.fromInput itemType
let! name = (useCamelCase, element) ||> Name.fromInput itemType
let! displayText = (useCamelCase, element) ||> displayTextGetter itemType
let! resourceIndicator =
match resourceIndicatorGetter with
| Some getter -> ((useCamelCase, element) ||> getter itemType)
| _ -> Ok None
return
{
id = id
itemName = name.toItemName
displayText = displayText
resourceIndicator = resourceIndicator
}
}
There appears to be one issue in the FsToolkit.ErrorHandling
repo that recognizes my problem here: “Question: parallel async CE #333” The following comment sounds ominous:
…
and!
for the officialasync
CE was rejected.—https://github.com/demystifyfp/FsToolkit.ErrorHandling/issues/333#issuecomment-2969639301
…where the phrase “was rejected” suggests (to me) that the FsToolkit.ErrorHandling
folks were not the cause of this breaking change.
ASP.NET feature in .NET 9.0: MapStaticAssets
replaces UseStaticFiles
✨ #to-do
Map Static Assets can replace UseStaticFiles in most situations. However, Map Static Assets is optimized for serving the assets from known locations in the app at build and publish time. If the app serves assets from other locations, such as disk or embedded resources, UseStaticFiles should be used.
Map Static Assets (MapStaticAssets) also replaces calling UseBlazorFrameworkFiles in apps that serve Blazor WebAssembly framework files, and explicitly calling UseBlazorFrameworkFiles in a Blazor Web App isn't necessary because the API is automatically called when invoking AddInteractiveWebAssemblyComponents.
This feature [📹 watch ] is highlighted in the following video:
Songhay Modules Publications (F♯): addressing #12
For #12, I recommend no work be done for this because:
The Songhay.Modules.Publications
package is intended for client-side, WebAssembly usage. It should not duplicate the types in Songhay.Publications
which relatively recently saw the addition of the following:
I currently assume that these ‘server-side’ types will be reduced to one of the PresentationDocument
cases before appearing on the client-side (most likely JSON, HTML or XHTML). There should be no immediate need to process any type like the types listed above on the Client, specifically the Web Client.
Python: Toga is a Python native, OS native GUI toolkit.
Russell Keith-Magee, the leading contributor to Toga, presents:
Publications: Maximiliano Firtman promotes “vanilla” JavaScript
Publications: SDUI is an acronym from Netflix
With the goal of building a flexible, configuration-driven system, we looked to server-driven UI (SDUI) as an appealing solution. SDUI is a design approach where the server dictates the structure and content of the UI, allowing for dynamic updates and customization without requiring changes to the client application. Client applications like web, mobile, and TV devices, act as rendering engines for SDUI data. After our teams weighed and vetted all the details, the dust settled and we landed on an approach similar to Command Query Responsibility Segregation (CQRS).
—“Netflix Tudum Architecture: from CQRS with Kafka to CQRS with RAW Hollow”
Rivian: “Yes, Rivian uses Android Automotive OS to build its software experience” 😐💸
I am not happy about this:
Google’s Android Automotive software has been adopted by many carmakers for the EV era, but it tends to vary between different brands. This week Google and Rivian confirmed to 9to5Google that the EV-maker uses Android Automotive as the base of its software experience, something that was previously not known.
Rivian’s operating system powers the software experience on the Rivian R1T and R1S, and will also power the upcoming R2 and R3. The platform is specific to the company’s vehicles and controls virtually of the features in the EVs.
—“Yes, Rivian uses Android Automotive OS to build its software experience”
Songhay Modules Bolero (F♯): I am going to use Regex
to parse my URI templates 😐
I am looking at what think is the ‘procured’ source code [🔗 GitHub ] for UriTemplate
[📖 docs ] which was not migrated from the full .NET Framework and I am seeing a bunch of while
loops and a ConcurrentDictionary<string, string>
.
This Studio uses Tavis.UriTemplates
[🔗 GitHub ] and that source code has dictionaries a foreach
loop [🔗 GitHub ].
A “pure” F♯ approach might be related to the parsing libraries listed on Awesome F# but I am too uninformed to see anything there without an explicit example, “parsing” a URI “template.” My F# Snippets search brought up:
A Uri parser using the Cashel library [1]. This implementation is using ArraySegment as the underlying state, as I'm using it within a server, but it would be trivial to switch it to using a list. Also, note that I am not parsing the Uri into any specific structure, though that, too, would be trivial. For my current purposes, I just needed to validate the Uri. [1] https://github.com/panesofglass/cashel
—“Uri Parser”
…and I am not seeing a thing 😐
At this time, I can see this:
…which means this expression is the equivalent of all of the looping above: /(\{[^}]+\})/g
—I am sure there is a technical reason behind avoiding Regex
. I look for ward to finding out about this later ⌛
Publications: “Tailwind is the Worst of All Worlds”
For reasons we'll get into later, Tailwind decided to burst on to the scene and become the default styling solution for all modern web development despite taking each and every one of these problems, exacerbating them, and applying them to places that didn't have them before. Lets see how Tailwind replicates CSS's main paradigms. Remember, inline styles let you control single element styles simply and fairly explicitly:
style="background: red; color: blue;"
. Classes let you control multi-element styles simply, with the slight annoyance that it's easy to misspell your class name and spend way too long debugging before realizing it:class="todo-item"
.Tailwind exclusively offers inline styles via classes. Classes are single strings separated by spaces, not key-value pairs. So the classes must be something like
class="bg-red txt-blue"
. Key and value must be obscured into a plain string, lowering readability and writability. If you misspell one of these plain strings your editor is not going to tell you. You'll just have to find out once you get into the browser. Did you notice thattxt-blue
is wrong, and it should actually betext-blue
? No? Get used to it, you'll make that mistake daily because Tailwind is inconsistent in how it names things.
Azure: KQL queries can be run from .NET workloads 😐🤓 #day-job #to-do
Microsoft.Azure.Kusto.Data
[🔗 NuGet ] has been out there since 2019. The following docs serve as an intro:
- “Set up your development environment to use Kusto client libraries”
- “Create an app to run basic queries”
- “KQL quick reference”
open pull requests on GitHub 🐙🐈
- https://github.com/BryanWilhite/Songhay.HelloWorlds.Activities/pull/14
- https://github.com/BryanWilhite/dotnet-core/pull/67
sketching out development projects
Eliminating Angular JS in the Studio is the top priority. Replacing the Angular JS app (http://kintespace.com/player.html
) for the kinté space depends on:
- generating a new
index.html
page with eleventy - supplementing the index with responsive images
Proposed future items:
- complete upgrade to .NET 8.0
- replace current b-roll player API with Azure Functions
- switch Studio Publications from Material Design to Bulma 💄 ➡️ 💄✨
- start
Songhay.Modules.Bolero.Index
project - generate responsive and social images with AI