Git Product home page Git Product logo

miiify's Introduction

Introduction

Miiify is a light-weight web annotation server using an embedded database. Its primary use case is to support IIIF applications. There is a choice of two storage backends:

git

Designed to be compatible with the Git protocol. This means annotations can be added or edited using standard git flow mechanisms such as a pull request and all new content can go through a review process before going public.

pack

Designed to be highly-scalable and disk efficient. This backend uses technology that is part of the distributed ledger used within the Tezos blockchain.

Getting started

Miiify can be run with Docker using either the git or pack backend. The example below uses the pack backend.

Starting server

docker compose pull pack
docker compose up pack -d

Check the server is running

http :

Stopping server

docker compose down pack

Basic concepts

Annotations are organised into containers and can be retrieved in pages to display within IIIF viewers such as Mirador. To filter the annotation page to a specific IIIF canvas an additional target parameter can be supplied. The examples below use httpie with a live demo server which spins down when inactive.

Create an annotation container called my-container:

https miiify.onrender.com/annotations/ < miiify/test/container1.json Slug:my-container

Add an annotation called foobar to my-container:

https miiify.onrender.com/annotations/my-container/ < miiify/test/annotation1.json Slug:foobar

Add another annotation but use a system generated id:

https miiify.onrender.com/annotations/my-container/ < miiify/test/annotation1.json

Retrieve the first annotation page from my-container:

https miiify.onrender.com/annotations/my-container/\?page\=0

produces:

{
    "@context": "http://iiif.io/api/presentation/3/context.json",
    "id": "https://miiify.onrender.com/annotations/my-container/?page=0",
    "items": [
        {
            "@context": "http://www.w3.org/ns/anno.jsonld",
            "body": "http://example.org/post1",
            "created": "2023-12-07T17:13:18Z",
            "id": "https://miiify.onrender.com/annotations/my-container/4acb2493-96b2-4efb-a5aa-044cde1408f0",
            "target": "http://example.com/page1",
            "type": "Annotation"
        },
        {
            "@context": "http://www.w3.org/ns/anno.jsonld",
            "body": "http://example.org/post1",
            "created": "2023-12-07T17:11:44Z",
            "id": "https://miiify.onrender.com/annotations/my-container/foobar",
            "target": "http://example.com/page1",
            "type": "Annotation"
        }
    ],
    "partOf": {
        "created": "2023-12-07T17:10:20Z",
        "id": "https://miiify.onrender.com/annotations/my-container/",
        "label": "A Container for Web Annotations",
        "total": 2,
        "type": "AnnotationCollection"
    },
    "startIndex": 0,
    "type": "AnnotationPage"
}

Retrieve the first annotation page from my-container but filter annotations based on their target:

https miiify.onrender.com/annotations/my-container/ < miiify/test/annotation3.json
https miiify.onrender.com/annotations/my-container/\?page\=0\&target\=http://example.com/page3

produces:

{
    "@context": "http://iiif.io/api/presentation/3/context.json",
    "id": "https://miiify.onrender.com/annotations/my-container/?page=0&target=http://example.com/page3",
    "items": [
        {
            "@context": "http://www.w3.org/ns/anno.jsonld",
            "body": "http://example.org/post3",
            "created": "2023-12-07T17:15:47Z",
            "id": "https://miiify.onrender.com/annotations/my-container/20375636-3af4-44e4-b005-b5c5e625ec85",
            "target": "http://example.com/page3",
            "type": "Annotation"
        }
    ],
    "partOf": {
        "created": "2023-12-07T17:10:20Z",
        "id": "https://miiify.onrender.com/annotations/my-container/",
        "label": "A Container for Web Annotations",
        "total": 3,
        "type": "AnnotationCollection"
    },
    "startIndex": 0,
    "type": "AnnotationPage"
}

Retrieve a single annotation:

https miiify.onrender.com/annotations/my-container/foobar

produces

{
    "@context": "http://www.w3.org/ns/anno.jsonld",
    "body": "http://example.org/post1",
    "created": "2023-12-07T17:11:44Z",
    "id": "https://miiify.onrender.com/annotations/my-container/foobar",
    "target": "http://example.com/page1",
    "type": "Annotation"
}

Tutorial

Simple video tutorial to show how to create annotations and display them in the Mirador IIIF viewer.

Other key features

  • Support for validating annotations using ATD
  • Easy to use with Docker and Kubernetes
  • Support for ETag caching and collision avoidance
  • Simple key/value interface for working with IIIF manifests

Building from source

To build your own native Docker images:

cd miiify/test
./build.sh pack

Documentation

API specification

miiify's People

Contributors

dependabot[bot] avatar jptmoore avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

miiify's Issues

Incomplete identifiers and bad `next` URI in AnnotationPages?

Take this annotation page referenced from the manifest at https://miiify.rocks/manifest/diamond_jubilee_of_the_metro:

https://miiify.rocks/annotations/diamond_jubilee_of_the_metro?page=0&target=https%3A//miiifystore.s3.eu-west-2.amazonaws.com/diamond_jubilee_of_the_metro/c/3/23b48727-680c-4562-9f6c-c5dc4f75b449%23xywh%3D431%2C429%2C895%2C330

Its id is https://miiify.rocks/annotations/diamond_jubilee_of_the_metro?page=0

Looking at another annotation page from the same canvas, but with a different target:
https://miiify.rocks/annotations/diamond_jubilee_of_the_metro?page=0&target=https%3A//miiifystore.s3.eu-west-2.amazonaws.com/diamond_jubilee_of_the_metro/c/3/23b48727-680c-4562-9f6c-c5dc4f75b449%23xywh%3D437%2C1406%2C898%2C305

The id is identical to the first annotation. This is likely to cause problems for client applications that use the identifier from the dereferenced resource. The easy fix would probably be to include the target request parameter in the id.

Another issue with the annotations is that the next key is also identical for both annotations, in both cases it's https://miiify.rocks/annotations/diamond_jubilee_of_the_metro?page=1, which contains all of the annotations of the complete manifest. I'd argue that the next key should not even be included, since the way annotation pages are used in this manifest, one page only ever contains a single annotation (the one targeting the resource from the target request parameter). Or am I misunderstanding something? In the application I'm currently working on this causes a large amount of requests, since it naively follows the next links and thus fetches the complete set of annotations multiple times, once for each annotation page referenced from the manifest.

Target filter when target is an object

Currently target filtering assumes target is a string but it is possible that target is an object with a source item that contains the string we need to compare against. Should add support for this variation.

Support custom validation of annotations

Currently only the type field of the JSON payload is checked to see if is equal to 'Annotation'. The entire annotation standard is complex to parse and will incur a performance hit to validate per annotation. Another solution would be to support writing custom parsers to handle specific kinds of fields you might only use. This could be achieved with a simple DSL

HTTP/2 headers are lowercase

Currently HTTP headers are handled as being case sensitive but HTTP/2 now forces that they are in lowercase. This will break in some clients like curl that default to using HTTP/2. A temporary fix is to do something like:

curl -X POST -sk -d @test/container1.json -H "Slug: foo" -H "Content-Type: application/json" --http1.1 https://localhost/annotations/

Readonly flag for pack backend

Add support for the readonly flag in the pack backend which could be useful for situations such as multiple Kubernetes pods mounting the same block storage.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.