All Articles

1091 articles in total

🔑Retrofitting Firebase auth and a JSONkeeper-compatible API onto codh-mirror so IIIF Curation editing actually works — walking back the earlier `won't work` claim

A follow-up to the earlier codh-mirror post, which explicitly called Firebase auth and the curation save backend out of scope. This time I went back and wired them up: reusing a Firebase project (Authorized domains and sign-in providers), discovering that FirebaseUI 3.x's default redirect signInFlow silently fails on GitHub Pages subpaths, swapping the curationJsonExportUrl in 9 places across five tools, and pointing the iiif-curation-manager submenu links at the sibling tools via relative URLs. Server-side details (Cloudflare Workers + D1 as mainline and PythonAnywhere Flask as upstream-faithful fallback) live in two separate posts; this one covers only the codh-mirror client side.

codhiiiffirebasefirebaseui

🪣Rewriting JSONkeeper on Cloudflare Workers + D1 — A 360-Line Hono + jose Replacement for the IIIF Curation Viewer's Save Backend

A from-scratch rewrite of JSONkeeper — the save backend for the IIIF Curation Viewer — not on top of the original Flask code, but as a Cloudflare Workers + D1 service. Covers Firebase ID-token verification with Hono + jose (no Admin SDK, no service-account key needed), the D1 SQLite schema, top-level + nested JSON-LD `@id` rewriting, a minimal Activity Stream collection, CORS and Viewer-compatible headers, a wrangler-based deployment runbook, and a feature-by-feature diff against upstream JSONkeeper.

cloudflarecloudflareworkersd1hono

🪣Deploying JSONkeeper on PythonAnywhere with HTTP API Only — A Self-Hosted Save Backend for the IIIF Curation Viewer

A reproducible runbook for self-hosting JSONkeeper — the save backend for the IIIF Curation Viewer / Editor / Manager / Board — on PythonAnywhere's free Beginner plan, using only HTTP API calls except for two one-time browser actions (API token issuance and first-time Bash console attach). Covers Flask 1.0 / apscheduler 3.5 incompatibility with modern Python, Firebase Admin SDK service-account key handling, the 100 CPU-second/day cap, CORS, and patching the Viewer-side codh-mirror repository.

pythonanywherejsonkeeperflaskfirebase

📜Reproducing the Vertical-Layout Page of Cing gisun-i Lao Kida with TEI/XML and XSLT — Encoding Manchu Script, Hangul Phonetic Gloss, and Warigaki Translation

Taking the first folio of Cing gisun-i Lao Kida (volume 1, fol. 1a) — a Joseon-era Manchu language primer — I encoded the page in TEI/XML using only standard elements and reproduced its vertical layout (Manchu script + Hangul phonetic gloss + warigaki Korean translation) with XSLT 1.0 generating HTML + SVG. This post records the design decision to separate data from visualization, the column-splitting trick in XSLT 1.0, the SVG-based rendering of Manchu script, and the three-panel comparison view (facsimile / XML / HTML).

teixsltxmlmanchu

📺Adding Japanese Captions to Silent Demo Videos in Bulk with Claude Code

A workflow for generating Japanese subtitles (SRT) for tool demo videos with no audio or captions by having Claude Code inspect frame contact sheets, then uploading them in bulk via the YouTube Data API captions.insert endpoint.

youtubeyoutubedataapipythonytdlp

💳Building a Personal Tech Blog Membership on Cloudflare Workers + better-auth + Stripe

Notes from migrating tech.ldas.jp from Hugo to Next.js (Cloudflare Workers + OpenNext) and adding a Stripe-backed membership with members-only post gating. Covers Workers Free plan CPU limits, Stripe SDK on Workers, SSG/dynamic interplay, and Japan-specific business onboarding details — the parts that the official docs don't quite spell out for this combination.

cloudflareworkersstripebetterauthnextjs

🛠Aligning vdiff.js Default Mode and UI with the Site Design — Swapping the Default with a One-Byte Patch

A record of customizing a temporarily mirrored vdiff.js from the outside to match the design of other pages on the same site. Switching the default comparison mode to 'side-by-side slider' via JavaScript radio-button clicks conflicted with vdiff's initialization timing, so the fix ultimately came down to a one-byte patch on the minified bundle. Also covers the layout approach for keeping the footer on-screen while clipping the image, plus the CSS setup for ja/en language switching and dark mode.

vdiffcodhjquery-uiui-customization

🪞Setting up a dedicated GitHub Pages repository for a temporary CODH-tool mirror — including the missing kuromoji dictionary in Soan

While the ROIS-DS Center for Open Data in the Humanities (CODH) website is down for long-term maintenance (notice issued 2026-02-24, no announced reopen date), I restored several CODH tools (vdiff.js / IIIF Curation Viewer / Soan / etc.) from the Wayback Machine and similar sources and published them as a standalone GitHub Pages repository (codh-mirror). This post covers the setup procedure and the gotchas I hit (notably the missing kuromoji dictionary for Soan). Strictly a temporary measure until CODH service resumes.

codhiiifvdiffsoan

🪞Embedded apps under `static/` get overwritten with the 404 page by Nuxt 2 generate, and how to retire the old Service Worker

On a Nuxt 2 + target:'static' site I dropped a third-party demo app under static/<tool>/index.html and ran into a problem: the generate crawler overwrote it with the 404 app shell. This post covers the cause, the workaround (generate.exclude), and the related cleanup of an old @nuxtjs/pwa Service Worker cache that bit me at the same time.

nuxtnuxt2static-siteservice-worker

🪞Restoring CODH's vdiff.js from the Wayback Machine to Temporarily Bring Back The Tale of Genji's Face Comparison Feature

The website of the ROIS-DS Center for Open Data in the Humanities (CODH) is currently down for long-term maintenance (notice issued 2026-02-24, no announced reopen date), which broke the 'patapata face comparison' feature on Digital Tale of Genji that called CODH's vdiff.js directly. As a stop-gap until CODH comes back, I pulled the vdiff.js distribution out of the Wayback Machine and self-hosted a mirror. This post records the procedure. Strictly a temporary measure until CODH service resumes.

codhvdiffwayback-machinearchive

📚DH Weekly Topics — 2026年5月10日週

DH Weekly Topics — 2026年5月10日週

dhweeklydigitalhumanitiesデジタルアーカイブocr

📜Building a macOS App That Turns a Folder of Page Images Into a Single TEI/XML — From Apple Vision OCR to Developer ID Distribution

I built TEI Scanner, a macOS desktop app that runs Apple's Vision OCR over a folder of scanned page images and emits a single TEI/XML document. This post records the SwiftUI implementation, project management via xcodegen, notarization driven by an App Store Connect API key, and .dmg distribution through GitHub Releases.

macosswiftswiftuivision

🗺️Serving IIIF Historic Maps as WMTS — Built on Allmaps, Integrated into a Next.js Portfolio

Serving IIIF historic maps as a WMTS-compatible tile service, built on top of Allmaps and integrated into a Next.js portfolio site.

iiifwmtsallmapsnextjs

🌙Connecting OpenDrift Drift Simulation with a Calendar and Tidal Calculation App: GeoJSON Bridge Design

A record of connecting a JavaScript-based traditional calendar and tidal calculation tool with a Python-based drift simulation using GeoJSON as the interchange format.

opendriftpythonjavascriptgeojson

🌊Drift Simulation in the Kuroshio Region Using OpenDrift and OSCAR Climatology

A record of running monthly drift simulations from offshore Amami Naze Port using NASA OSCAR monthly climatology and NCEP/NCAR reanalysis wind data.

opendriftpythonkuroshioocean

Aligning IIIF 3D Viewer with Presentation API 4 — converting legacy manifests at runtime

I aligned IIIF 3D Viewer with the IIIF 3D Technical Specification Group's Presentation API 4 draft (Scene / PointSelector / WKTSelector / PerspectiveCamera). Existing manifests authored against IIIF Presentation 3 with a project-local 3DSelector / camPos extension are funnelled through a runtime converter so the rest of the pipeline only deals with v4. This post records the diff, the conversion rules, and the implementation outline.

iiif3dpresentation-apiweb-annotation

Auto-Updating a Statistics Page from TEI/XML Transcription Data via CI/CD — A Case Study from the Kouigenjimonogatari Text DB

How a statistics page that aggregates pages, lines, characters, and waka counts per chapter is generated from TEI/XML transcription data, and how the rebuild and redeployment are automated with GitHub Actions.

teixmldhgithub-actions

Probing the Public APIs of the Tohoku University Digital Archives — Exporting per-setSpec Excel via OAI-PMH

I surveyed which public APIs are available on the Tohoku University Digital Archives (touda.tohoku.ac.jp/collection) and worked out a procedure to harvest metadata per setSpec via OAI-PMH and write each set into its own Excel file.

oaipmhiiifpythonopenpyxl

📥researchmap Achievement Registration: Options for Individual Researchers and a Playwright Implementation

researchmap provides an official write API and CSV/JSON/JSONL import for individual users, each with its own constraints. This article reviews the available options and presents a Playwright implementation that adds full automation and PDF attachment support.

researchmapplaywrightpythonautomation

A YAML-Driven Next.js Admin Console — Multiple Sites, Multiple Actions

Notes on extending an admin console so that adding sites and actions requires editing one YAML file rather than touching code, with a tabbed UI for multiple actions per site.

nextjscloudflaregithub-appyaml