content: six real code exhibits, rendered by the panel (AUD-152)
This commit is contained in:
36
content/assets/code/01-actionscript-class.as
Normal file
36
content/assets/code/01-actionscript-class.as
Normal file
@@ -0,0 +1,36 @@
|
||||
package thebeer {
|
||||
import utils.Bg;
|
||||
|
||||
import com.greensock.TweenMax;
|
||||
|
||||
import flash.display.MovieClip;
|
||||
import flash.events.Event;
|
||||
|
||||
/**
|
||||
* @author samrolfe
|
||||
*/
|
||||
public class Siren extends MovieClip {
|
||||
private var targ : Bg;
|
||||
private var delays : Number;
|
||||
private var wide: Number;
|
||||
private var high: Number;
|
||||
|
||||
public function Siren(col:Number,t:Bg,d:Number) {
|
||||
delays=d;
|
||||
targ=t;
|
||||
x=targ.x;
|
||||
y=targ.y;
|
||||
wide=this.width;
|
||||
high=this.high;
|
||||
TweenMax.to(this,0,{autoAlpha:0,colorMatrixFilter:{colorize:col}});
|
||||
}
|
||||
|
||||
private function setPos(e:Event) : void {
|
||||
x=parent[targ].x;
|
||||
y=parent[targ].y;
|
||||
}
|
||||
|
||||
public function flash() : void {
|
||||
TweenMax.to(this,0,{autoAlpha:1,width:wide,height:high});
|
||||
TweenMax.to(this,.1,{width:0,height:0,repeat:5,repeatDelay:delays,yoyo:true,onComplete:finish});
|
||||
}
|
||||
53
content/assets/code/02-js-easing-core.js
Normal file
53
content/assets/code/02-js-easing-core.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// Excerpt from js/utils/text_effects.js (2,156 lines) in the WebsiteBuilder
|
||||
// source. Two regions are reproduced verbatim: the timeline loop that derives
|
||||
// each letter's delay from an easing function (lines 1111-1147), and the
|
||||
// hand-written easing functions themselves (lines 1340-1349).
|
||||
$(mySplitTextTarg).each(function(i){
|
||||
|
||||
tweenData.letter=$(this);
|
||||
tweenData.text_static.letter=$(this);
|
||||
tweenData.text_text_to.letter=$(this);
|
||||
tweenData.text_text_from.letter=$(this);
|
||||
|
||||
if(text_effect_type_animation=="standard"){
|
||||
if(tweenData.ignoreItems=="on" && Math.random()<tweenData.ignore_amount)return;
|
||||
|
||||
if(!keepHide(tweenData,i,$(this).text()))return;
|
||||
|
||||
var transforms=getTransforms(tweenData);
|
||||
|
||||
|
||||
//currenttime,start,change,duration
|
||||
if(tweenData.staggerTimeRnd=="random")stagger=min_max_random(0,tweenData.staggerTime);
|
||||
// stagger=positionsCubic(tweenData.alternatecount, 0, tweenData.duration, tweenData.total)
|
||||
var ease=tweenData.easeFunction;
|
||||
// var ease="easeInCubic";
|
||||
stime=tweenData.duration;
|
||||
if(tweenData.direc=="in"){
|
||||
stagger=jQuery.easing[ease](null,tweenData.alternatecount, 0, tweenData.duration, tweenData.total)+tweenData.startWait
|
||||
transforms.delay=stagger;
|
||||
TweenMax.from($(this), tweenData.duration, transforms);
|
||||
tt=tweenData.duration+stagger;
|
||||
}
|
||||
if(tweenData.direc=="out"){
|
||||
stagger=jQuery.easing[ease](null,tweenData.alternatecount, 0, tweenData.duration, tweenData.total)
|
||||
transforms.delay=stagger;
|
||||
transforms.onComplete=tweenRemove($(this),stagger+stime+tweenData.removeWait)
|
||||
TweenMax.to($(this), tweenData.duration, transforms);
|
||||
tt=tweenData.duration+stagger+tweenData.removeWait+1;
|
||||
}
|
||||
|
||||
setCssTweens(stime,text_effect_type_animation,tweenData,tweenData.text_static,tweenData.text_text_to,tweenData.text_text_from,$(this),stagger);
|
||||
|
||||
|
||||
// --- easing functions, lines 1340-1349 ---
|
||||
//t,b,c,d
|
||||
//currenttime,start,change,duration
|
||||
//t and do can be time or frames
|
||||
function positionsCubic(t, b, c, d){
|
||||
t /= d;
|
||||
return c*t*t*t + b;
|
||||
}
|
||||
function positionSine(t, b, c, d) {
|
||||
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
|
||||
}
|
||||
54
content/assets/code/03-php-encode-op.php
Normal file
54
content/assets/code/03-php-encode-op.php
Normal file
@@ -0,0 +1,54 @@
|
||||
// Excerpt from php/setMediaEncoder.php (3,402 lines) in the WebsiteBuilder
|
||||
// source: the create_gif encode operation, lines 614-665, reproduced verbatim.
|
||||
if($output_options->encode_media=="create_gif") {
|
||||
$output_gif= ".." . $settings->directory . $output_file .$output_options->format .".gif";
|
||||
|
||||
$docmime= checkFinfo($input_file);
|
||||
$doctype=explode("/",$docmime)[0];
|
||||
if ($doctype!="video"){
|
||||
$output_options->error_message= "We only create gifs from a video - it must be the first video in the media list.";
|
||||
$returnFiles = returnFiles ( $output_options, $output_file .$output_options->format . '.mp4', "video/mp4", '', null );
|
||||
return $returnFiles;
|
||||
}
|
||||
|
||||
$cmd = "ffmpeg -i ".$input_file." -y -vf fps=".$settings->settings->movie_frame_rate.",scale=".$settings->settings->video_width.":".$settings->settings->video_height.",palettegen palette.png 2>&1";
|
||||
// $cmd = "ffmpeg -i ".$input_file." -y -vf fps=10,scale=".$settings->settings->video_width.":".$settings->settings->video_height.",palettegen palette.png 2>&1";
|
||||
$result=shell_exec($cmd);
|
||||
$first_media=json_decode($settings->add_media)[0];
|
||||
|
||||
// $cmd = "ffmpeg -ss ".$first_media->add_media_start." -t ".$first_media->add_media_duration." -i ".$input_file." -i palette.png -y -filter_complex \"fps=10[x];[x][1:v]paletteuse\" ".$output_gif." ";
|
||||
$cmd = "ffmpeg -ss ".$first_media->add_media_start." -t ".$first_media->add_media_duration." -i ".$input_file." -i palette.png -y -filter_complex \"fps=".$settings->settings->movie_frame_rate.",scale=".$settings->settings->video_width.":".$settings->settings->video_height.":flags=lanczos[x];[x][1:v]paletteuse\" ".$output_gif." ";
|
||||
ffmpegMsg("ffmpeg","Creating Gif ", 0,$cmd);
|
||||
|
||||
// $cmd_2='mogrify -delay '.$_POST['compress_gif_delay'].' -alpha remove '.$matte.' -depth '.$_POST['compress_gif_depth'].' '.$deconstruct.' '.$dither.' -colors '.$_POST['compress_gif_colors'].' -fuzz '.$_POST['compress_gif_fuzz'].'% '.$loop.' '.$optimize.' '.$path.' 2>&1';
|
||||
|
||||
$_POST['loop_gif']="true";
|
||||
$_POST['compress_gif_matte']="false";
|
||||
$_POST['compress_gif_deconstruct']="false";
|
||||
$_POST['compress_gif_dither']="true";
|
||||
$_POST['compress_gif_optimize']="true";
|
||||
|
||||
$loop=($_POST['loop_gif']=="false")?"-loop 1":"";
|
||||
$matte=($_POST['compress_gif_matte']=="true")?"-matte":"";
|
||||
$deconstruct=($_POST['compress_gif_deconstruct']=="true")?"-deconstruct":"";
|
||||
$dither=($_POST['compress_gif_dither']=="true")?"-dither none ":"";
|
||||
$optimize=($_POST['compress_gif_optimize']=="true")?"-layers optimize ":"";
|
||||
// $optimize=($_POST['compress_gif_optimize']=="true")?" -coalesce -layers RemoveDups ":"";
|
||||
|
||||
$_POST['compress_gif_depth']=16;
|
||||
$_POST['compress_gif_delay']=0;
|
||||
$_POST['compress_gif_fuzz']="4";
|
||||
$_POST['compress_gif_colors']="16";
|
||||
|
||||
$cmd_2='mogrify -delay '.$_POST['compress_gif_delay'].' -alpha remove '.$matte.' -depth '.$_POST['compress_gif_depth'].' '.$deconstruct.' '.$dither.' -colors '.$_POST['compress_gif_colors'].' -fuzz '.$_POST['compress_gif_fuzz'].'% '.$loop.' '.$optimize.' '.$output_gif.' 2>&1';
|
||||
$result=shell_exec($cmd_2);
|
||||
|
||||
|
||||
$output_options->edited_url= $output_options->options->directory.$output_file .$output_options->format . '.gif';
|
||||
$output_options->edited_name= $output_file .$output_options->format . '.gif';
|
||||
$output_options->edited_type = "image/gif";
|
||||
$output_options->edited_filetype = explode ( "/", "image/gif");
|
||||
insert_document($output_options->edited_url,"image/gif",$output_options->edited_name,"image","edited");
|
||||
$returnFiles = returnFiles ( $output_options, $output_file .$output_options->format . '.mp4', "video/mp4", '', null );
|
||||
return $returnFiles;
|
||||
}
|
||||
38
content/assets/code/04-typescript-service-layer.ts
Normal file
38
content/assets/code/04-typescript-service-layer.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
// In file: src/server/api/routers/commandTemplate.ts
|
||||
import { z } from "zod";
|
||||
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
||||
|
||||
export const commandTemplateRouter = createTRPCRouter({
|
||||
// Procedure to get all templates
|
||||
getAll: publicProcedure.query(({ ctx }) => {
|
||||
return ctx.db.commandTemplate.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
}),
|
||||
|
||||
// Procedure to create a new template
|
||||
create: publicProcedure
|
||||
.input(z.object({
|
||||
name: z.string().min(1),
|
||||
type: z.string().min(1),
|
||||
payload: z.record(z.unknown()), // Accepts any JSON object
|
||||
}))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return ctx.db.commandTemplate.create({
|
||||
data: {
|
||||
name: input.name,
|
||||
type: input.type,
|
||||
payload: input.payload,
|
||||
},
|
||||
});
|
||||
}),
|
||||
|
||||
// Procedure to delete a template
|
||||
delete: publicProcedure
|
||||
.input(z.object({ id: z.number() }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return ctx.db.commandTemplate.delete({
|
||||
where: { id: input.id },
|
||||
});
|
||||
}),
|
||||
});
|
||||
31
content/assets/code/05-embedded-cpp-interface.hpp
Normal file
31
content/assets/code/05-embedded-cpp-interface.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Two files from firmware/src/hw, reproduced verbatim: WiFiMgr.hpp (the
|
||||
// interface) and WiFiMgr.cpp (the implementation). The boundary is marked.
|
||||
// WiFiMgr.hpp — the interface the rest of the firmware depends on
|
||||
// WiFiMgr.hpp
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace WiFiMgr {
|
||||
bool connectHome(const char* ssid, const char* psk, uint32_t timeoutMs = 15000);
|
||||
void disconnect();
|
||||
}
|
||||
// WiFiMgr.cpp — the only translation unit that includes <WiFi.h>
|
||||
// WiFiMgr.cpp
|
||||
#include "WiFiMgr.hpp"
|
||||
#include <WiFi.h> // ESP32 WiFi
|
||||
|
||||
namespace WiFiMgr {
|
||||
bool connectHome(const char* ssid, const char* psk, uint32_t timeoutMs) {
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, psk);
|
||||
uint32_t t0 = millis();
|
||||
while (WiFi.status() != WL_CONNECTED && millis() - t0 < timeoutMs) {
|
||||
delay(200);
|
||||
}
|
||||
return WiFi.status() == WL_CONNECTED;
|
||||
}
|
||||
void disconnect() {
|
||||
WiFi.disconnect(true, true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
}
|
||||
33
content/assets/code/06-nix-derivation.nix
Normal file
33
content/assets/code/06-nix-derivation.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{ lib, stdenv, fetchurl }:
|
||||
|
||||
# tuios — terminal window manager (https://github.com/Gaurav-Gosain/tuios)
|
||||
# OVERRIDE: nixpkgs ships tuios 0.7.0; the multi-machine `hosts` UX needs 0.9+.
|
||||
# Official pure-Go prebuilt release binary (no runtime deps, runs bare on NixOS).
|
||||
# To return to nixpkgs packaging: use plain `tuios` in home.packages again and
|
||||
# delete this file (do this once nixpkgs ships tuios >= 0.10).
|
||||
stdenv.mkDerivation {
|
||||
pname = "tuios";
|
||||
version = "0.10.1";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/Gaurav-Gosain/tuios/releases/download/v0.10.1/tuios_0.10.1_Linux_x86_64.tar.gz";
|
||||
sha256 = "85a4bf339a9a6793e0b3d15abdccd9a96ca8d2ff76072007ec99be31f1a16a5f";
|
||||
};
|
||||
|
||||
# Tarball has no wrapping directory (tuios / LICENSE / README.md at root)
|
||||
sourceRoot = ".";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
install -Dm755 tuios $out/bin/tuios
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Terminal window manager — tiling panes, sessions that survive restarts (multi-machine daemon)";
|
||||
homepage = "https://github.com/Gaurav-Gosain/tuios";
|
||||
license = licenses.mit;
|
||||
mainProgram = "tuios";
|
||||
platforms = [ "x86_64-linux" ];
|
||||
};
|
||||
}
|
||||
@@ -8,9 +8,9 @@ confidence: running
|
||||
period: "2020–"
|
||||
tech: [ESP32, LoRa, Zigbee, MQTT, Home Assistant, Snapcast, Pi, PIR, mmWave]
|
||||
metrics: [{label: "edge nodes", value: 20}, {label: "lighting zones", value: 9}, {label: "automations", value: 20}, {label: "hand-built Zigbee routers", value: 2}]
|
||||
artefacts: [{type: doc, label: "Edge architecture — power · radio · deep sleep", url: "content/edge/l3/edge-architecture.md"}, {type: doc, label: "LoRa irrigation under solar power", url: "content/edge/l3/edge-lora-sprinkler.md"}, {type: doc, label: "Hand-built Zigbee routers and lighting", url: "content/edge/l3/edge-zigbee.md"}, {type: doc, label: "Distributed audio — eight endpoints with ducking", url: "content/edge/l3/edge-snapcast.md"}, {type: doc, label: "Front door — vision · voice · and a rebuild", url: "content/edge/l3/edge-front-door.md"}, {type: doc, label: "Sensors and actuation", url: "content/edge/l3/edge-sensors.md"}, {type: doc, label: "The failures, kept in the record", url: "content/edge/l3/edge-failures.md"}]
|
||||
artefacts: [{type: doc, label: "Edge architecture — power · radio · deep sleep", url: "content/edge/l3/edge-architecture.md"}, {type: doc, label: "LoRa irrigation under solar power", url: "content/edge/l3/edge-lora-sprinkler.md"}, {type: doc, label: "Hand-built Zigbee routers and lighting", url: "content/edge/l3/edge-zigbee.md"}, {type: doc, label: "Distributed audio — eight endpoints with ducking", url: "content/edge/l3/edge-snapcast.md"}, {type: doc, label: "Front door — vision · voice · and a rebuild", url: "content/edge/l3/edge-front-door.md"}, {type: doc, label: "Sensors and actuation", url: "content/edge/l3/edge-sensors.md"}, {type: doc, label: "The failures, kept in the record", url: "content/edge/l3/edge-failures.md"}, {type: repo, label: "Embedded C++ — the Wi-Fi manager interface and implementation", url: "content/assets/code/05-embedded-cpp-interface.hpp"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
last_verified: 2026-10-28
|
||||
tags: [edge, iot, esp32, lora, zigbee, audio]
|
||||
---
|
||||
|
||||
@@ -30,6 +30,10 @@ tags: [edge, iot, esp32, lora, zigbee, audio]
|
||||
|
||||
**Cameras and vision.** The front door takes an image, logs it, has the image described, and speaks the result into the house before deciding what to do next. RFID tags on boxes and on trees resolve to records — inventory with prices for the boxes, care notes for the trees — written by an automation rather than typed by hand.
|
||||
|
||||
## Why this exhibit is good code
|
||||
|
||||
The header declares the interface and includes only `Arduino.h`, so a caller compiles without pulling the ESP32 Wi-Fi stack into its translation unit. Only the implementation file knows about station mode, polling and millisecond timeouts, and it returns a boolean so the caller decides what a failed join means. The two files are shown together because the point is the split, not either file alone.
|
||||
|
||||
## Evidence
|
||||
|
||||
| Claim | Evidence | Artefact |
|
||||
|
||||
@@ -8,26 +8,34 @@ confidence: historic
|
||||
period: "2006–2026"
|
||||
tech: [ActionScript, JavaScript, PHP, TypeScript, C++, Nix]
|
||||
metrics: [{label: "code exhibits", value: 6}, {label: "technology eras spanned", value: 5}]
|
||||
artefacts: []
|
||||
artefacts: [{type: repo, label: "ActionScript 3 — the Siren class", url: "content/assets/code/01-actionscript-class.as"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
last_verified: 2026-10-28
|
||||
tags: [history, code, exhibits, artefact]
|
||||
---
|
||||
|
||||
The excerpts are selected from source that exists on disk; each one lands in Phase 7 with two sentences on why it is good code.
|
||||
**Status: published.** This page shows the ActionScript class and indexes the other five, each of which is exhibited on the page where it belongs.
|
||||
|
||||
## The six
|
||||
|
||||
| # | Era | Source | What the excerpt shows |
|
||||
| # | Era | Exhibit | Where it is shown |
|
||||
|---|---|---|---|
|
||||
| 1 | Object-oriented ActionScript | the brief-case builder and the national beer campaign | class design, imports, encapsulation |
|
||||
| 2 | Hand-written JavaScript engine | the text-effects engine from the site builder (about 2 200 lines) | easing and a timeline core |
|
||||
| 3 | PHP media pipeline | the media encoder from the site builder (about 3 400 lines) | one encode operation and the FFmpeg piping around it |
|
||||
| 4 | TypeScript | the vehicle-tracking application's schema and typed service layer | types, interfaces, a router |
|
||||
| 5 | Embedded C++ | the Wi-Fi manager interface and implementation | interface versus implementation in firmware |
|
||||
| 6 | Declarative infrastructure | the 25-line Nix package definition | pinned version, verified hash, written exit condition |
|
||||
| 1 | Object-oriented ActionScript | `01-actionscript-class.as` — class, imports, encapsulation | this page |
|
||||
| 2 | Hand-written JavaScript engine | `02-js-easing-core.js` — easing functions and the timeline loop | [the site builder](../../products/l3/products-websitebuilder.md) |
|
||||
| 3 | PHP media pipeline | `03-php-encode-op.php` — one GIF encode operation and its FFmpeg commands | [the site builder](../../products/l3/products-websitebuilder.md) |
|
||||
| 4 | TypeScript | `04-typescript-service-layer.ts` — a typed tRPC boundary | [the estate](../../platform/platform-estate.md) |
|
||||
| 5 | Embedded C++ | `05-embedded-cpp-interface.hpp` — interface split from implementation | [the edge fleet](../../edge/edge-fleet.md) |
|
||||
| 6 | Declarative infrastructure | `06-nix-derivation.nix` — pinned version, verified hash, exit condition | [the Nix package](../../platform/l3/platform-tuios-package.md) |
|
||||
|
||||
Total is roughly 225 lines across twenty years, which is the point: each excerpt is chosen to show judgement rather than volume.
|
||||
Total is 243 lines across twenty years, which is the point: each excerpt is chosen to show judgement rather than volume.
|
||||
|
||||
## Why this exhibit is good code
|
||||
|
||||
Every field is private and explicitly typed, and the public surface is two methods, so a caller cannot push the object into a state it does not understand. The constructor takes what it needs as parameters instead of reaching for it, which is why the same class can drive every siren on the screen without knowing where any of them are.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
The excerpt is verbatim, including a latent typo (`this.high` rather than `this.height`). It is left as found: the excerpt is evidence, not a portfolio piece.
|
||||
|
||||
## What it proves
|
||||
|
||||
@@ -35,4 +43,4 @@ That the stack changed six times and the discipline did not. Exhibit 6 is the le
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. Source paths are recorded in the planning notes; nothing is published from a path that has not been read at capture time.
|
||||
Published. The six files are in this repository under `content/assets/code/`; the archive path is withheld. The other five are linked above from the pages that carry their claims.
|
||||
|
||||
@@ -8,13 +8,13 @@ confidence: running
|
||||
period: "2026–"
|
||||
tech: [Nix, NixOS]
|
||||
metrics: [{label: "pinned version", value: "0.10.1"}, {label: "nixpkgs version it overrides", value: "0.7.0"}]
|
||||
artefacts: []
|
||||
artefacts: [{type: repo, label: "Nix derivation — tuios 0.10.1 override with a removal condition", url: "content/assets/code/06-nix-derivation.nix"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
last_verified: 2026-10-28
|
||||
tags: [platform, nix, packaging, artefact]
|
||||
---
|
||||
|
||||
The whole file is short enough to publish verbatim; it lands in Phase 7.
|
||||
**Status: published.** The whole file is shown verbatim.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
@@ -24,6 +24,10 @@ A package definition for the agent operations console: `fetchurl` against a rele
|
||||
|
||||
More than knowing Nix exists. The signals are that someone noticed a version gap, fixed it locally instead of waiting, pinned it so the fleet is reproducible, and wrote down when to remove their own patch. Knowing when to delete your own override is the senior part.
|
||||
|
||||
## Why this exhibit is good code
|
||||
|
||||
The override records why it exists and the exact condition under which it should be deleted, which is the part of a local patch that usually goes missing. Pinning a released binary by `fetchurl` with a verified hash keeps the result reproducible without waiting for nixpkgs.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7. The file is in the infrastructure repository; source fact: content spine section 4.2.
|
||||
Published. The file is in this repository at `content/assets/code/06-nix-derivation.nix`; the infrastructure repository remains the source. Source fact: content spine section 4.2.
|
||||
|
||||
@@ -8,9 +8,9 @@ confidence: running
|
||||
period: "2020–"
|
||||
tech: [NixOS, Proxmox, Docker, Caddy, Tailscale, Borg, Kopia, AWS S3, HDMI-CEC]
|
||||
metrics: [{label: "containers in the estate", value: 50}, {label: "hosts", value: 4}, {label: "backup tiers", value: "Borg · Kopia · AWS"}, {label: "public listeners", value: 1}]
|
||||
artefacts: [{type: doc, label: "Declarative multi-host configuration", url: "content/platform/l3/platform-nixos.md"}, {type: doc, label: "A hand-written Nix package with an exit plan", url: "content/platform/l3/platform-tuios-package.md"}, {type: doc, label: "Container inventory", url: "content/platform/l3/platform-containers.md"}, {type: doc, label: "Backups and restore runbook", url: "content/platform/l3/platform-backups.md"}, {type: doc, label: "Network layout and remote access", url: "content/platform/l3/platform-network.md"}, {type: doc, label: "Signage infrastructure — screens as a managed fleet", url: "content/platform/l3/platform-signage.md"}]
|
||||
artefacts: [{type: doc, label: "Declarative multi-host configuration", url: "content/platform/l3/platform-nixos.md"}, {type: doc, label: "A hand-written Nix package with an exit plan", url: "content/platform/l3/platform-tuios-package.md"}, {type: doc, label: "Container inventory", url: "content/platform/l3/platform-containers.md"}, {type: doc, label: "Backups and restore runbook", url: "content/platform/l3/platform-backups.md"}, {type: doc, label: "Network layout and remote access", url: "content/platform/l3/platform-network.md"}, {type: doc, label: "Signage infrastructure — screens as a managed fleet", url: "content/platform/l3/platform-signage.md"}, {type: repo, label: "TypeScript — a typed tRPC service boundary", url: "content/assets/code/04-typescript-service-layer.ts"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
last_verified: 2026-10-28
|
||||
tags: [platform, devops, nixos, docker, backups, networking]
|
||||
---
|
||||
|
||||
@@ -32,6 +32,10 @@ tags: [platform, devops, nixos, docker, backups, networking]
|
||||
|
||||
**Signage infrastructure.** The display work is treated as a fleet to be managed: HDMI-CEC control for power, rotation, mirroring and multi-screen layout, so screens are driven by the platform rather than by a person with a remote control.
|
||||
|
||||
## Why this exhibit is good code
|
||||
|
||||
The Prisma schema defines the stored types, and the tRPC router validates input with Zod at the boundary, so the data layer receives a shape it can trust rather than one it hopes for. Each procedure is a thin call on the database context, which keeps the router a description of the API rather than a second copy of the queries.
|
||||
|
||||
## Evidence
|
||||
|
||||
| Claim | Evidence | Artefact |
|
||||
|
||||
@@ -8,13 +8,13 @@ confidence: delivered
|
||||
period: "2014–"
|
||||
tech: [PHP, JavaScript, three.js, FFmpeg, ImageMagick, MySQL]
|
||||
metrics: [{label: "media editors in the product", value: "drawing · image · video · text animation · transitions · 3D import"}]
|
||||
artefacts: []
|
||||
artefacts: [{type: repo, label: "Text-effects engine — easing functions and the timeline loop", url: "content/assets/code/02-js-easing-core.js"}, {type: repo, label: "Media encoder — one GIF encode operation and its FFmpeg commands", url: "content/assets/code/03-php-encode-op.php"}]
|
||||
public: true
|
||||
last_verified: 2026-10-26
|
||||
last_verified: 2026-10-28
|
||||
tags: [products, cms, media, artefact]
|
||||
---
|
||||
|
||||
Retired as a general-purpose product; kept as the content engine for the signage.
|
||||
**Status: delivered, retained.** Retired as a general-purpose product; kept as the content engine for the signage.
|
||||
|
||||
## What the artefact is
|
||||
|
||||
@@ -24,10 +24,16 @@ The templated builder: pick a template, build the site, publish it — with edit
|
||||
|
||||
Two things at once — depth in media pipelines (FFmpeg, ImageMagick, PDF and office formats, three.js) and the discipline of shipping a general product that strangers could operate without help.
|
||||
|
||||
## Why these exhibits are good code
|
||||
|
||||
The animation engine evaluates a named easing function to give each letter its delay, so the spacing of an animation follows the same curve as its motion instead of a guessed linear stagger. Both directions build from one transform object, which is what stops the two halves of the same effect drifting apart over years of edits.
|
||||
|
||||
The media pipeline checks the real MIME type before it builds a command, so a wrong input returns a message instead of a half-written file. The GIF encode takes two passes — a palette from the clip, then frames mapped onto it — which is the difference between a GIF that holds its colour and one that does not.
|
||||
|
||||
## Limits stated on the page
|
||||
|
||||
The surface was too large for one person to support indefinitely. The plan recorded here is to strip it back to signage plus the content engine and stop selling the rest, which is a decision about focus rather than a claim of failure.
|
||||
The PHP is 2014-era procedural code: global state, interpolated shell commands, and long functions. The exhibit is here for the operational judgement, not as a model of structure. The surface was too large for one person to support indefinitely; the plan recorded here is to strip it back to signage plus the content engine and stop selling the rest, which is a decision about focus rather than a claim of failure.
|
||||
|
||||
## When it is delivered
|
||||
|
||||
Phase 7 for a screen recording of the editors. Source: résumé (2014–2020 freelance) and evidence notes section 3.
|
||||
Phase 7. Both code exhibits are published at `content/assets/code/`; a screen recording of the editors is still to come. Source: résumé (2014–2020 freelance) and evidence notes section 3.
|
||||
|
||||
Reference in New Issue
Block a user