Understory is a lightweight, IIIF-focused platform for hosting the media and metadata of digital scholarship projects.
Users of Understory upload images, audio, and video, describe them, and arrange them into collections. Understory stores every work as a IIIF Presentation 3.0 manifest, serves its images through the IIIF Image API, and streams its audio and video. When a collection is ready, a user publishes it, and Understory writes a published copy of the collection and builds its search index.
Use Understory as the backend of a Canopy IIIF site: Understory holds and serves the collection, and Canopy builds the site that presents it.
- Images. Understory converts uploaded and imported images to tiled TIFFs, and serverless-iiif serves them through IIIF Image API 3.0.
- Audio and video. AWS Elemental MediaConvert turns uploads into adaptive HLS streams. Understory copies imported streams as they are.
- Import. Paste the URL of a IIIF manifest or collection, and Understory copies its works and their images. A single imported work keeps its audio and video too. Understory copies only what an anonymous visitor could already fetch.
- Editing. Users edit labels, summaries, metadata, and canvas order, and preview each work in Clover IIIF.
- Publishing. Users publish a collection in two steps, its IIIF documents first and its search index second, so a site and its search change together. Drafts stay editable throughout.
- Roles. Administrators manage everything. Editors manage the collections granted to them.
Admin UI (Next.js) ──▶ API (API Gateway and Lambda, behind Cognito)
├─ S3: draft and published IIIF documents
├─ serverless-iiif: IIIF Image API 3.0
├─ MediaConvert: HLS audio and video
└─ OpenSearch: a search index per published collection
Canopy IIIF site ◀── published documents, images, streams, and search, through CloudFront
Understory runs on AWS and deploys as one SAM stack: S3, CloudFront, Lambda, Step Functions, API Gateway, Cognito, MediaConvert, and Amplify Hosting for the admin UI. It needs one thing it does not create, an Amazon OpenSearch Service domain.
You need an AWS account, the SAM CLI, Docker, Node 22, and an OpenSearch domain.
- Copy
app/aws/samconfig.toml.exampletoapp/aws/samconfig.tomland fill it in: a stack name such as<you>-dev-understory, a GitHub token for Amplify, and your OpenSearch domain. - Deploy with
cd app/aws && sam build --use-container && sam deploy --guided. - Copy the
ImagesDistributionHostoutput into theImageApiForceHostparameter, and deploy again. - Create your user in the stack's Cognito pool and add it to the
admingroup. - Fill in
ui/.env.localfrom the stack outputs, followingui/.env.local.example, then runnpm install && npm run devinui/.
AGENTS.md covers each step in detail, along with the design and the reasons behind it.
| Path | Contents |
|---|---|
app/aws/template.yml |
The whole stack |
app/aws/lambdas/ |
The API, the publish and import workers, and the image and A/V converters |
app/shared/ |
Logic the Lambdas share, with its unit tests |
ui/ |
The admin app |
Run the tests with npm test at the root. Lint the admin app with npm run lint in ui/.
Developed by @kdid and @mathewjordan in Academic Innovation at Northwestern University Libraries.