luv

Workshop wiki

showcase.lisp

luvcraft/showcase.lisp

system luvcraft/web · 17 definitions · on GitHub

The published, source-reproducible stills and films of luvcraft.

The web process owns the semantic page and reads the small capture manifest. Caddy owns the large byte responses: annex symlinks remain ordinary static files and never pass through the character HTTP server.

in-package#:luvcraft.web
defclassshowcase-page
directory:initarg:directory:readershowcase-page-directory
media-path:initarg:media-path:readershowcase-page-media-path
:documentation

The generated capture catalog mounted beside externally served media.

DIRECTORY contains the capture manifest. MEDIA-PATH is the public static url subtree whose files are served by the deployment edge. #IVRWI8

defundefault-showcase-directory
let
configured
uiop:getenv"LUV_SHOWCASE_MEDIA_DIRECTORY"
uiop:ensure-directory-pathname
if
andconfigured
plusp
lengthconfigured
configured
asdf:system-relative-pathname"luvcraft/web""build/wiki/media/"
defundefault-showcase-media-path
or
uiop:getenv"LUV_SHOWCASE_MEDIA_PATH"
"/showcase/media"
defunmake-showcase-page
&keydirectorymedia-path
make-instance'showcase-page:path"/showcase":label"Showcase":description"Reproducible glimpses of little worlds and live proposals.":directory
uiop:ensure-directory-pathname
:media-path
defunsafe-showcase-filename-p
filename
and
stringpfilename
plusp
lengthfilename
every
lambda
character
or
alphanumericpcharacter
findcharacter"-_."
filename
member
pathname-typefilename
'
"png""jpg""jpeg""webp""mp4""webm"
:test#'string-equal
defunread-showcase-manifest
let
pathname
merge-pathnames"manifest.sexp"
showcase-page-directorypage
when
probe-filepathname
with-open-file
streampathname
let
*read-eval*nil
let
manifest
readstreamnilnil
when
and
listpmanifest
eql1
getfmanifest:version
listp
getfmanifest:captures
manifest
defunshowcase-title
capture
string-capitalize
substitute#\Space#\-
or
getfcapture:name
"capture"
defunshowcase-media-url
pagefilename
formatnil"~A/~A"
string-right-trim"/"
showcase-page-media-pathpage
filename
defunshowcase-layout
capture
let
layout
getfcapture:layout:landscape
if
memberlayout'
:landscape:portrait
layout:landscape
defunpositive-showcase-dimension
capturename
let
value
getfcapturename
and
integerpvalue
pluspvalue
value
defunshowcase-card-sizes
capture
if
eq:portrait
"(max-width: 29rem) calc(100vw - 2rem), 27rem""(max-width: 59.5rem) calc(100vw - 2rem), calc((min(100vw - 2rem, 76rem) - 1.5rem) / 2)"
defunwrite-showcase-image
outputpagecapturefilename
let*
original-url
variants
sort
remove-if-not#'safe-showcase-variant-p
copy-list
getfcapture:variants
#'<:key
lambda
variant
getfvariant:width
largest-variant
car
lastvariants
largest-variant-url
andlargest-variant
showcase-media-urlpage
getflargest-variant:file

SRCSET contains only card-sized derivatives, placing a hard ceiling on index traffic. The surrounding link keeps the original available for deliberate detail viewing and download.

formatoutput"<a class=original href=\"~A\" title=\"Open full-resolution image\">"
html-escapedoriginal-url
formatoutput"<img loading=lazy decoding=async src=\"~A\" alt=\"\""
html-escaped
orlargest-variant-urloriginal-url
when
formatoutput" width=~D height=~D"widthheight
whenvariants
formatoutput" srcset=\"~{~A~^, ~}\" sizes=\"~A\""
mapcar
lambda
variant
formatnil"~A ~Dw"
getfvariant:width
variants
formatoutput"></a>"
defunwrite-showcase-video
outputpagecapturefilename
let*
poster
getfcapture:poster
poster-file
and
getfposter:file
formatoutput"<video controls loop muted playsinline preload=~A"
ifposter-file"none""metadata"
whenposter-file
formatoutput" poster=\"~A\""
when
formatoutput" width=~D height=~D"widthheight
formatoutput"><source src=\"~A\" type=\"video/~A\">This browser cannot play the captured video.</video>"
html-escaped
string-downcase
pathname-typefilename
defunwrite-showcase-card
outputpagecapture
let*
filename
getfcapture:file
kind
getfcapture:kind
figure
getfcapture:figure
layout-name
string-downcase
symbol-namelayout
when
formatoutput"<article class=~A><div class=\"media ~A\">"layout-namelayout-name
ecasekind
:image
write-showcase-imageoutputpagecapturefilename
:video
write-showcase-videooutputpagecapturefilename
formatoutput"</div><p class=figure>#~A</p><h2>~A</h2></article>~%"
defunshowcase-page-html
let*
captures
andmanifest
getfmanifest:captures
revision
andmanifest
getfmanifest:source-revision
with-output-to-string
output
formatoutput"<!doctype html><html lang=en><head><meta charset=utf-8>~%"
formatoutput"<meta name=viewport content=\"width=device-width, initial-scale=1\"><title>Luvcraft showcase</title><style>~%"
formatoutput":root{color-scheme:dark;font-family:ui-monospace,SFMono-Regular,monospace;background:#0d100d;color:#edf0e4}body{margin:0;background:radial-gradient(circle at 80% 0,#29352b,#0d100d 42rem)}main{width:min(76rem,calc(100% - 2rem));margin:auto;padding:4rem 0 8rem}header{max-width:48rem;margin-bottom:3rem}a{color:#f2c28f}p{color:#aeb9a8;line-height:1.55}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,28rem),1fr));gap:1.5rem}article{overflow:hidden;border:1px solid #455247;border-radius:.8rem;background:#151a15}.media{aspect-ratio:3/2;background:#080a08;display:grid;place-items:center}.media .original,.media img,.media video{display:block;width:100%;height:100%}.media img,.media video{object-fit:cover}.media.portrait{aspect-ratio:9/16;width:min(100%,27rem);margin-inline:auto}.media.portrait img,.media.portrait video{object-fit:contain}article h2,article .figure{margin-left:1.2rem;margin-right:1.2rem}.figure{font-size:.78rem;color:#d49b68;margin-bottom:.3rem}article h2{margin-top:0;margin-bottom:1.2rem;font-size:1.1rem}</style></head><body><main>~%"
formatoutput"<header><p>LUVCRAFT / SHOWCASE</p><h1>Possible worlds, rendered.</h1><p>These stills and films are generated from named Lisp capture recipes. The source stays small; the media is published separately from its rendering machine.</p><p><a href=\"/\">← all little windows</a>"
whenrevision
formatoutput" · source <code>~A</code>"
html-escaped
subseqrevision0
min12
lengthrevision
formatoutput"</p></header>~%"
ifcaptures
progn
formatoutput"<section class=grid>~%"
dolist
capturecaptures
formatoutput"</section>~%"
formatoutput"<p>No capture manifest has been published here yet.</p>~%"
formatoutput"</main></body></html>~%"
defmethodrespond-to-web-request
if
or
string=path"/"
string=path"/index.html"
ok-response"text/html; charset=utf-8"
call-next-method