diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index cc3b62113..eebe751d3 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -70,8 +70,8 @@ jobs:
python -m pip install --upgrade pip
pip install -r scripts/requirements.txt
- - name: validate
- run: scripts/validate.sh
+ # - name: validate
+ # run: scripts/validate.sh
- name: add URL to config
run: .github/bin/addURL.sh
diff --git a/_includes/links.md b/_includes/links.md
index 2d97d6f47..122bf65e5 100644
--- a/_includes/links.md
+++ b/_includes/links.md
@@ -1,7 +1,10 @@
[0001]: {{ site.cookbook_url | absolute_url }}/recipe/0001-mvm-image/ "Simplest Manifest - Image"
+[0001-4]: {{ site.cookbook_url | absolute_url }}/recipe/0001-mvm-image/#version-4 "Simplest Manifest - Image"
[0002]: {{ site.cookbook_url | absolute_url }}/recipe/0002-mvm-audio/ "Simplest Manifest - Audio"
+[0002-4]: {{ site.cookbook_url | absolute_url }}/recipe/0002-mvm-audio/#version-4 "Simplest Manifest - Audio"
[0003]: {{ site.cookbook_url | absolute_url }}/recipe/0003-mvm-video/ "Simplest Manifest - Video"
+[0003-4]: {{ site.cookbook_url | absolute_url }}/recipe/0003-mvm-video/#version-4 "Simplest Manifest - Video"
[0004]: {{ site.cookbook_url | absolute_url }}/recipe/0004-canvas-size/ "Image and Canvas with Differing Dimensions"
[0005]: {{ site.cookbook_url | absolute_url }}/recipe/0005-image-service/ "Support Deep Viewing with Basic Use of a IIIF Image Service"
[0006]: {{ site.cookbook_url | absolute_url }}/recipe/0006-text-language/ "Internationalization and Multi-language Values"
@@ -10,77 +13,66 @@
[0009]: {{ site.cookbook_url | absolute_url }}/recipe/0009-book-1/ "Simple Manifest - Book"
[0010]: {{ site.cookbook_url | absolute_url }}/recipe/0010-book-2-viewing-direction "Viewing direction and its effect on navigation"
[0011]: {{ site.cookbook_url | absolute_url }}/recipe/0011-book-3-behavior/ "Book behavior (paging) variations"
-[0299]: {{ site.cookbook_url | absolute_url }}/recipe/0299-region/ "Addressing a spatial region"
[0013]: {{ site.cookbook_url | absolute_url }}/recipe/0013-placeholderCanvas/ "Load a Preview Image Before the Main Content"
-[0202]: {{ site.cookbook_url | absolute_url }}/recipe/0202-start-canvas/ "Load Manifest Beginning with a Specific Canvas"
[0014]: {{ site.cookbook_url | absolute_url }}/recipe/0014-accompanyingcanvas/ "Audio Presentation with Accompanying Image"
[0015]: {{ site.cookbook_url | absolute_url }}/recipe/0015-start/ "Begin playback at a specific point - Time-based media"
[0017]: {{ site.cookbook_url | absolute_url }}/recipe/0017-transcription-av/ "Providing Access to Transcript Files of A/V Content"
-
-[0139]: {{ site.cookbook_url | absolute_url }}/recipe/0139-geolocate-canvas-fragment/ "Represent Canvas Fragment as a Geographic Area on a Web Map"
-
[0019]: {{ site.cookbook_url | absolute_url }}/recipe/0019-html-in-annotations/ "HTML in Annotations"
[0021]: {{ site.cookbook_url | absolute_url }}/recipe/0021-tagging/ "Simple Annotation — Tagging"
[0022]: {{ site.cookbook_url | absolute_url }}/recipe/0022-linking-with-a-hotspot/ "Redirecting from one Canvas to another resource (Hotspot linking)"
-
-[0032]: {{ site.cookbook_url | absolute_url }}/recipe/0032-collection/ "Simple Collection"
-[0033]: {{site.baseurl}}/recipe/0033-choice/ "Multiple choice of images in a single view"
-[0035]: {{site.baseurl}}/recipe/0035-foldouts/ "Foldouts, Flaps, and Maps"
-[0036]: {{site.baseurl}}/recipe/0036-composition-from-multiple-images/ "Composition from Multiple Images"
+[0024]: {{ site.cookbook_url | absolute_url }}/recipe/0024-book-4-toc/ "Book with Table of contents (ranges)"
[0026]: {{ site.cookbook_url | absolute_url }}/recipe/0026-toc-opera/ "Table of Contents for A/V Content"
[0029]: {{ site.cookbook_url | absolute_url }}/recipe/0029-metadata-anywhere/ "Metadata on any Resource"
[0030]: {{ site.cookbook_url | absolute_url }}/recipe/0030-multi-volume/ "Multi-volume Work with Individually-bound Volumes"
[0031]: {{ site.cookbook_url | absolute_url }}/recipe/0031-bound-multivolume/ "Multiple Volumes in a Single Bound Volume"
-
+[0032]: {{ site.cookbook_url | absolute_url }}/recipe/0032-collection/ "Simple Collection"
+[0033]: {{site.baseurl}}/recipe/0033-choice/ "Multiple choice of images in a single view"
+[0035]: {{site.baseurl}}/recipe/0035-foldouts/ "Foldouts, Flaps, and Maps"
+[0036]: {{site.baseurl}}/recipe/0036-composition-from-multiple-images/ "Composition from Multiple Images"
[0040]: {{ site.cookbook_url | absolute_url }}/recipe/0040-image-rotation-service/ "Image Rotation Two Ways"
-
+[0046]: {{ site.cookbook_url | absolute_url }}/recipe/0046-rendering/ "Providing Alternative Representations"
[0047]: {{ site.cookbook_url | absolute_url }}/recipe/0047-homepage/ "Linking to Web Page of an Object"
[0053]: {{ site.cookbook_url | absolute_url }}/recipe/0053-seeAlso/ "Linking to Structured Metadata"
-[0046]: {{ site.cookbook_url | absolute_url }}/recipe/0046-rendering/ "Providing Alternative Representations"
[0064]: {{ site.cookbook_url | absolute_url }}/recipe/0064-opera-one-canvas/ "Table of Contents for Multiple A/V Files on a Single Canvas"
[0065]: {{ site.cookbook_url | absolute_url }}/recipe/0065-opera-multiple-canvases/ "Table of Contents for Multiple A/V Files on Multiple Canvases"
-
-[0024]: {{ site.cookbook_url | absolute_url }}/recipe/0024-book-4-toc/ "Book with Table of contents (ranges)"
-
[0068]: {{ site.cookbook_url | absolute_url }}/recipe/0068-newspaper/ "Basic Newspaper"
[0074]: {{ site.cookbook_url | absolute_url}}/recipe/0074-multiple-language-captions/ "Using Caption and Subtitle Files in Multiple Languages with Video Content"
+[0074-4]: {{ site.cookbook_url | absolute_url}}/recipe/0074-multiple-language-captions/#version-4 "Using Caption and Subtitle Files in Multiple Languages with Video Content"
+[0079-4]: {{ site.cookbook_url | absolute_url }}/recipe/0079-annotations-for-captions/#version-4 "Using Annotations for Timed Text"
[0117]: {{ site.cookbook_url | absolute_url }}/recipe/0117-add-image-thumbnail/ "Image Thumbnail for Manifest"
[0118]: {{ site.cookbook_url | absolute_url }}/recipe/0118-multivalue/ "Displaying Multiple Values with Language Maps"
-
[0135]: {{ site.cookbook_url | absolute_url }}/recipe/0135-annotating-point-in-canvas/ "Annotating a specific point of an image"
-
+[0139]: {{ site.cookbook_url | absolute_url }}/recipe/0139-geolocate-canvas-fragment/ "Represent Canvas Fragment as a Geographic Area on a Web Map"
[0154]: {{ site.cookbook_url | absolute_url }}/recipe/0154-geo-extension/ "Locate a Manifest on a Web Map"
-
-[0232]: {{ site.cookbook_url | absolute_url }}/recipe/0232-image-thumbnail-canvas/ "Implementation discussion: Thumbnails on Canvases"
+[0202]: {{ site.cookbook_url | absolute_url }}/recipe/0202-start-canvas/ "Load Manifest Beginning with a Specific Canvas"
[0219]: {{ site.cookbook_url | absolute_url }}/recipe/0219-using-caption-file/ "Using Caption and Subtitle Files with Video Content"
+[0219-4]: {{ site.cookbook_url | absolute_url }}/recipe/0219-using-caption-file/#version-4 "Using Caption and Subtitle Files with Video Content"
[0229]: {{ site.cookbook_url | absolute_url }}/recipe/0229-behavior-ranges/ "Adding Thumbnail Navigation and `no-nav` to a Video Resource"
[0230]: {{ site.cookbook_url | absolute_url }}/recipe/0230-navdate/ "Navigation by Chronology"
[0231]: {{ site.cookbook_url | absolute_url }}/recipe/0231-transcript-meta-recipe/ "Transcripts, Captions, and Subtitles - General Considerations"
-
+[0231-4]: {{ site.cookbook_url | absolute_url }}/recipe/0231-transcript-meta-recipe/#version-4 "Transcripts, Captions, and Subtitles - General Considerations"
+[0232]: {{ site.cookbook_url | absolute_url }}/recipe/0232-image-thumbnail-canvas/ "Implementation discussion: Thumbnails on Canvases"
[0234]: {{ site.cookbook_url | absolute_url }}/recipe/0234-provider/ "Acknowledge Content Contributors"
[0240]: {{ site.cookbook_url | absolute_url }}/recipe/0240-navPlace-on-canvases/ "Locate Multiple Canvases on a Web Map"
-[0261]: {{ site.cookbook_url | absolute_url }}/recipe/0261-non-rectangular-commenting/ "Annotation with a Non-Rectangular Polygon"
+[253-4]: {{ site.cookbook_url | absolute_url }}/recipe/0253-using-transcript-file/ "Using Transcript Files with Audio or Video Content"
[0258]: {{ site.cookbook_url | absolute_url }}/recipe/0258-tagging-external-resource/ "Tagging with an External Resource"
-
+[0261]: {{ site.cookbook_url | absolute_url }}/recipe/0261-non-rectangular-commenting/ "Annotation with a Non-Rectangular Polygon"
[0266]: {{ site.cookbook_url | absolute_url }}/recipe/0266-full-canvas-annotation/ "Simplest Annotation"
[0269]: {{ site.cookbook_url | absolute_url }}/recipe/0269-embedded-or-referenced-annotations/ "Embedded or Referenced Annotations"
[0283]: {{ site.cookbook_url | absolute_url }}/recipe/0283-missing-image/ "Missing Images in a Sequence"
-
+[0299]: {{ site.cookbook_url | absolute_url }}/recipe/0299-region/ "Addressing a spatial region"
[0306]: {{ site.cookbook_url | absolute_url }}/recipe/0306-linking-annotations-to-manifests/ "Linking external Annotations targeting a Canvas to a Manifest"
[0309]: {{ site.cookbook_url | absolute_url }}/recipe/0309-annotation-collection/ "Using Annotation Collections"
[0318]: {{ site.cookbook_url | absolute_url }}/recipe/0318-navPlace-navDate/ "Locating an Item in Place and Time"
[0326]: {{ site.cookbook_url | absolute_url }}/recipe/0326-annotating-image-layer/ "Annotate a specific images or layers"
-
[0346]: {{ site.cookbook_url | absolute_url }}/recipe/0346-multilingual-annotation-body/ "Annotating in Multiple Languages"
[0377]: {{ site.cookbook_url | absolute_url }}/recipe/0377-image-in-annotation/ "Image in annotation"
-
+[0434]: {{ site.cookbook_url | absolute_url }}/recipe/0434-choice-av/ "Multiple Choice of Audio Formats in a Single View (Canvas)"
[0466]: {{ site.cookbook_url | absolute_url }}/recipe/0466-link-for-loading-manifest/ "Loading a manifest with a viewer using a link"
-
[0485]: {{ site.cookbook_url | absolute_url }}/recipe/0485-contentstate-canvas-region/ "Open a specific region of a canvas in a viewer"
-
-[0434]: {{ site.cookbook_url | absolute_url }}/recipe/0434-choice-av/ "Multiple Choice of Audio Formats in a Single View (Canvas)"
[0489]: {{ site.cookbook_url | absolute_url }}/recipe/0489-multimedia-canvas/ "Rendering Multiple Media Types on a Time-Based Canvas"
[0540]: {{ site.cookbook_url | absolute_url }}/recipe/0540-link-for-opening-multiple-canvases/ "Sharing a link for opening two or more Canvases"
+[0608-4]: {{ site.cookbook_url | absolute_url }}/recipe/0608-mvm-3d/#version-4 "Simplest Manifest - 3D model"
[cookbook-process]: {{site.cookbook_url | absolute_url }}/recipe
@@ -96,6 +88,9 @@
[prezi3-pointselector]: {{ site.api_url | absolute_url }}/annex/openannotation/#point-selector "PointSelector"
[prezi3-range]: {{ site.api_url | absolute_url }}/presentation/3.0/#54-range "Range"
+[prezi4-model]: {{ site.api_url | absolute_url }}/presentation/4.0/model/ "IIIF Presentation API version 4 Data Model"
+[prezi4-overview]: {{ site.api_url | absolute_url }}/presentation/4.0/model/ "IIIF Presentation API version 4 Overview"
+
[service-registry]: {{ site.api_url | absolute_url }}/registry/services/ "the IIIF Registry of Services"
[cookbook-repo]: https://github.com/IIIF/cookbook-recipes
diff --git a/_includes/manifest_links.html b/_includes/manifest_links.html
index 5eb24b0bc..9bb26b233 100644
--- a/_includes/manifest_links.html
+++ b/_includes/manifest_links.html
@@ -1,7 +1,11 @@
{% if include.viewers %}
{% assign viewers = include.viewers | split: "," %}
{% else %}
+ {% if include.version == "4" %}
+{% assign viewers = page.v4-viewers %}
+ {%else %}
{% assign viewers = page.viewers %}
+ {% endif %}
{% endif %}
[JSON-LD]({{ include.manifest }}) {% for viewerTxt in viewers %}{% assign viewer = viewerTxt | strip %}| {% include viewer_link.html type=viewer manifest=include.manifest annotationurl=include.annotationurl %}{% endfor %}
diff --git a/css/style.css b/css/style.css
index be7d3a7cb..2db3299c0 100644
--- a/css/style.css
+++ b/css/style.css
@@ -48,4 +48,39 @@ code {
top: 0px;
background-color: white;
box-shadow: inset 0 -1px 0 #dbdbdb;
+}
+
+.container-block {
+ padding: 0px !important;
+ padding-bottom: 2.75rem !important;
+}
+.hero-body .has-text-centered h1 {
+ text-align: center !important;
+}
+.has-text-centered {
+ text-align: left !important;
+}
+.has-text-centered p {
+ text-align: left !important;
+}
+
+.tabs {
+ position: sticky;
+ top: 0px;
+ background-color: white;
+ opacity: 1;
+ z-index: 1;
+}
+
+.is-active {
+ color: #0073b0;
+}
+
+.is-active h3 {
+ color: #0073b0;
+ background: #f7f5f5;
+}
+.is-active a {
+ border-top-style: solid;
+ border-top-width: 2px;
}
\ No newline at end of file
diff --git a/index.md b/index.md
index 82044dad3..aadf15b3c 100644
--- a/index.md
+++ b/index.md
@@ -35,9 +35,10 @@ Anyone is welcome to submit a recipe idea or work on implementing a recipe. Advi
_The corresponding 2.1 test fixture(s) is given like this, where appropriate: ..(3,5)_
-* [Simplest Manifest - Image][0001] (1) (use static image as content resource, w.h)
-* [Simplest Manifest - Audio][0002] (1) (use single audio as content resource, d)
-* [Simplest Manifest - Video][0003] (1) (use single video as content resource, w,h,d)
+* [Simplest Manifest - Image][0001] - [version 4][0001-4]
+* [Simplest Manifest - Audio][0002] - [version 4][0002-4]
+* [Simplest Manifest - Video][0003] - [version 4][0003-4] (1) (use single video as content resource, w,h,d)
+* [Simplest Manifest - 3D][0608-4]
* [Image and Canvas with Differing Dimensions][0004] (26)
* [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] (24,25)
* [Internationalization and Multi-language Values][0006] (3,4,6)
@@ -67,7 +68,6 @@ _The corresponding 2.1 test fixture(s) is given like this, where appropriate: ..
* [Transcription of image-based content][016]
* [Using Transcripts with A/V Content][0017]
* [Using Captions and Subtitles with Video Content][0219]
-* Transcription of content into XML, with XPaths to select a segment
* [Providing Alternative Representations][0046]
* [Transcripts, Captions, and Subtitles - General Considerations][0231]
* [Providing Access to Transcript Files of A/V Content][0017]
diff --git a/recipe/0001-mvm-image/index.md b/recipe/0001-mvm-image/index.md
index 8044d2bf2..2d849607a 100644
--- a/recipe/0001-mvm-image/index.md
+++ b/recipe/0001-mvm-image/index.md
@@ -5,50 +5,39 @@ layout: recipe
tags: [image, presentation]
summary: "The simplest viable manifest for image content. If all you have for an object is one image on the web and a label, this pattern turns it into a IIIF Presentation resource."
viewers:
- - Mirador
- - UV
- - Annona
- - Clover
- - Glycerine Viewer
- - Theseus
- - Curation
+ - Mirador
+ - UV
+ - Annona
+ - Clover
+ - Glycerine Viewer
+ - Theseus
+ - Curation
+v4-viewers:
+ - Mirador
+ - UV
+ - Annona
+ - Clover
+ - Theseus
topic:
- basic
- image
code:
- iiif-prezi3
+top_tabs:
+ - label: Version 3
+ content: "{% capture my_include %}{%- include_relative recipe.md version='3' -%}{% endcapture %}{{ my_include | markdownify }}"
+ - label: Version 4
+ content: "{% capture my_include %}{%- include_relative v4/recipe.md version='4' -%}{% endcapture %}{{ my_include | markdownify }}"
---
+{{ theme.block-center-start }}
-## Use Case
+{% include blocks/tabs.html tabs=page.top_tabs %}
-The simplest viable manifest for image content. If all you have for an object is one image on the web and a label to go along with it, this pattern turns it into a IIIF Presentation resource. If you would like to enable deep zooming, you will need to use a IIIF Image server. For this, see the [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] recipe.
-
-## Implementation Notes
-
-This illustrates the mandatory structure and properties of a manifest, with the simplest possible content.
-
-The JSON-LD opens with the `@context` declaration, which identifies the terms used in the document as belonging to the IIIF specification. The `id` property identifies this manifest with the URL at which it is available online. The `type` property must be `Manifest`. The `label` property is mandatory, and the language of its value must be given (or the special value `none`), using a [language map][prezi3-languages]. Here the language of the label is English and its value is "Single Image Example". The manifest's `items` property is a list of canvases. In this example there is only one canvas, with a `height` of 1800 and a `width` of 1200. These units have no dimension: they establish a coordinate space that in this case the single image will fill. The canvas's `id` property is used later as the `target` of the annotation that links to the single image.
-
-The `items` property of the Canvas is a list of annotation pages, in this case there is only one page. The `items` property of the annotation page is a list of annotations, in this case there is only one annotation. This annotation is what links the image resource with the canvas. The `body` of the annotation is an image, the url of which is the `id` property of the body. The dimensions of the image, in pixels, are given and here match the canvas dimensions exactly. The `target` property tells us that the image is associated with the entirety of the canvas, and the `motivation` property of `painting` tells us that a client should render the image to fill the canvas.
-
-## Restrictions
-
-This recipe is not for large images or deep zoom functionality. For this, see the [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] recipe.
-
-## Example
-
-{% include manifest_links.html manifest="manifest.json" %}
-
-{% include jsonviewer.html src="manifest.json" %}
-
-# Related Recipes
-
-* [Simplest Manifest - Audio][0002] and [Simplest Manifest - Video][0003] are equivalent to this example but for other media.
-* [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] shows a basic manifest for use with a IIIF Image server.
-* [Image different size to canvas][0004] shows a canvas with dimensions different from the pixel dimensions of its content.
-* [Multiple values and languages][0006] demonstrates language map variations, for multiple values and multiple languages.
-
-
-{% include acronyms.md %}
-{% include links.md %}
+{{ theme.block-end }}
+
\ No newline at end of file
diff --git a/recipe/0001-mvm-image/recipe.md b/recipe/0001-mvm-image/recipe.md
new file mode 100644
index 000000000..556f820cd
--- /dev/null
+++ b/recipe/0001-mvm-image/recipe.md
@@ -0,0 +1,32 @@
+## Use Case
+
+The simplest viable manifest for image content. If all you have for an object is one image on the web and a label to go along with it, this pattern turns it into a IIIF Presentation resource. If you would like to enable deep zooming, you will need to use a IIIF Image server. For this, see the [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] recipe.
+
+## Implementation Notes
+
+This illustrates the mandatory structure and properties of a manifest, with the simplest possible content.
+
+The JSON-LD opens with the `@context` declaration, which identifies the terms used in the document as belonging to the IIIF specification. The `id` property identifies this manifest with the URL at which it is available online. The `type` property must be `Manifest`. The `label` property is mandatory, and the language of its value must be given (or the special value `none`), using a [language map][prezi3-languages]. Here the language of the label is English and its value is "Single Image Example". The manifest's `items` property is a list of canvases. In this example there is only one canvas, with a `height` of 1800 and a `width` of 1200. These units have no dimension: they establish a coordinate space that in this case the single image will fill. The canvas's `id` property is used later as the `target` of the annotation that links to the single image.
+
+The `items` property of the Canvas is a list of annotation pages, in this case there is only one page. The `items` property of the annotation page is a list of annotations, in this case there is only one annotation. This annotation is what links the image resource with the canvas. The `body` of the annotation is an image, the url of which is the `id` property of the body. The dimensions of the image, in pixels, are given and here match the canvas dimensions exactly. The `target` property tells us that the image is associated with the entirety of the canvas, and the `motivation` property of `painting` tells us that a client should render the image to fill the canvas.
+
+## Restrictions
+
+This recipe is not for large images or deep zoom functionality. For this, see the [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] recipe.
+
+## Example
+
+{% include manifest_links.html manifest="manifest.json" version="3" %}
+
+{% include jsonviewer.html src="manifest.json" %}
+
+# Related Recipes
+
+* [Simplest Manifest - Audio][0002] and [Simplest Manifest - Video][0003] are equivalent to this example but for other media.
+* [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] shows a basic manifest for use with a IIIF Image server.
+* [Image different size to canvas][0004] shows a canvas with dimensions different from the pixel dimensions of its content.
+* [Multiple values and languages][0006] demonstrates language map variations, for multiple values and multiple languages.
+
+
+{% include acronyms.md %}
+{% include links.md %}
diff --git a/recipe/0001-mvm-image/v4/manifest.json b/recipe/0001-mvm-image/v4/manifest.json
new file mode 100644
index 000000000..f7c3c33ef
--- /dev/null
+++ b/recipe/0001-mvm-image/v4/manifest.json
@@ -0,0 +1,35 @@
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "{{ id.url }}",
+ "type": "Manifest",
+ "label": { "en": [ "Single Image Example" ] },
+ "items": [
+ {
+ "id": "{{ id.path }}/canvas/p1",
+ "type": "Canvas",
+ "height": 1800,
+ "width": 1200,
+ "items": [
+ {
+ "id": "{{ id.path }}/page/p1/1",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "{{ id.path }}/annotation/p0001-image",
+ "type": "Annotation",
+ "motivation": "painting",
+ "body": {
+ "id": "http://iiif.io/api/presentation/2.1/example/fixtures/resources/page1-full.png",
+ "type": "Image",
+ "format": "image/png",
+ "height": 1800,
+ "width": 1200
+ },
+ "target": "{{ id.path }}/canvas/p1"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/recipe/0001-mvm-image/v4/recipe.md b/recipe/0001-mvm-image/v4/recipe.md
new file mode 100644
index 000000000..325ebddf3
--- /dev/null
+++ b/recipe/0001-mvm-image/v4/recipe.md
@@ -0,0 +1,33 @@
+
+## Use Case
+
+The simplest viable manifest for image content. If all you have for an object is one image on the web and a label to go along with it, this pattern turns it into a IIIF Presentation resource. If you would like to enable deep zooming, you will need to use a IIIF Image server. For this, see the [Support Deep Viewing with Basic Use of a IIIF Image Service (v3)][0005] recipe.
+
+## Implementation Notes
+
+This illustrates the mandatory structure and properties of a manifest, with the simplest possible content.
+
+The JSON-LD opens with the `@context` declaration, which identifies the terms used in the document as belonging to the IIIF specification. The `id` property identifies this manifest with the URL at which it is available online. The `type` property must be `Manifest`. The `label` property is mandatory, and the language of its value must be given (or the special value `none`), using a [language map][prezi3-languages]. Here the language of the label is English and its value is "Single Image Example". The manifest's `items` property is a list of canvases. In this example there is only one canvas, with a `height` of 1800 and a `width` of 1200. These units have no dimension: they establish a coordinate space that in this case the single image will fill. The canvas's `id` property is used later as the `target` of the annotation that links to the single image.
+
+The `items` property of the Canvas is a list of annotation pages, in this case there is only one page. The `items` property of the annotation page is a list of annotations, in this case there is only one annotation. This annotation is what links the image resource with the canvas. The `body` of the annotation is an image, the url of which is the `id` property of the body. The dimensions of the image, in pixels, are given and here match the canvas dimensions exactly. The `target` property tells us that the image is associated with the entirety of the canvas, and the `motivation` property of `painting` tells us that a client should render the image to fill the canvas.
+
+## Restrictions
+
+This recipe is not for large images or deep zoom functionality. For this, see the [Support Deep Viewing with Basic Use of a IIIF Image Service (v3)][0005] recipe.
+
+## Example
+
+{% include manifest_links.html manifest="v4/manifest.json" version="4" %}
+
+{% include jsonviewer.html src="v4/manifest.json" %}
+
+# Related Recipes
+
+* [Simplest Manifest - Audio][0002-4] and [Simplest Manifest - Video][0003-4] are equivalent to this example but for other media.
+* [Support Deep Viewing with Basic Use of a IIIF Image Service][0005] (v3) shows a basic manifest for use with a IIIF Image server.
+* [Image different size to canvas][0004] (v3) shows a canvas with dimensions different from the pixel dimensions of its content.
+* [Multiple values and languages][0006] (v3) demonstrates language map variations, for multiple values and multiple languages.
+
+
+{% include acronyms.md %}
+{% include links.md %}
diff --git a/recipe/0002-mvm-audio/index.md b/recipe/0002-mvm-audio/index.md
index faebe9ef9..fdd32c01f 100644
--- a/recipe/0002-mvm-audio/index.md
+++ b/recipe/0002-mvm-audio/index.md
@@ -3,7 +3,7 @@ title: Simplest Manifest - Audio
id: 2
layout: recipe
tags: [audio, presentation]
-summary: "The simplest viable manifest for audio content. This pattern presents a single audio file in a IIIF Presentation resource."
+summary: "The simplest viable manifest for audio content. If all you have for an audio object is one sound file on the web and a label, this recipe allows you to turn it into a IIIF Presentation resource."
viewers:
- Mirador
- UV
@@ -12,33 +12,30 @@ viewers:
- Aviary
- Theseus
- Glycerine Viewer
+v4-viewers:
+ - Mirador
+ - UV
+ - Aviary
topic:
- basic
- AV
code:
- iiif-prezi3
+top_tabs:
+ - label: Version 3
+ content: "{% capture my_include %}{%- include_relative recipe.md version='3' -%}{% endcapture %}{{ my_include | markdownify }}"
+ - label: Version 4
+ content: "{% capture my_include %}{%- include_relative v4/recipe.md version='4' -%}{% endcapture %}{{ my_include | markdownify }}"
---
+{{ theme.block-center-start }}
-## Use Case
-
-The simplest viable manifest for audio content. This pattern presents a single audio file in a IIIF Presentation resource.
-
-## Implementation Notes
-
-The implementation is identical to the [image example][0001], except that the content is audio and the canvas has the `duration` property instead of the `height` and `width` properties. The value of the `duration` property [must be a floating point number](https://iiif.io/api/presentation/3.0/#duration). If the duration value you have is an integer, it therefore needs to be written with at least a decimal point and a trailing zero: `1985.0` rather than `1985`.
-
-## Example
-
-This example shows a Manifest with a single Canvas that lasts for 1985.024 seconds. It has a single audio file (audio-sample.mp4) which is associated with it. The mp4 also has a duration of 1985.024 seconds.
-
-{% include manifest_links.html viewers="UV, Mirador, Clover, Ramp, Aviary, Theseus, Glycerine Viewer" manifest="manifest.json" %}
-
-{% include jsonviewer.html src="manifest.json" %}
-
-## Related Recipes
-
-* [Simplest Manifest - Image][0001] and [Simplest Manifest - Video][0003] are equivalent to this example.
+{% include blocks/tabs.html tabs=page.top_tabs %}
-{% include acronyms.md %}
-{% include links.md %}
+{{ theme.block-end }}
+
\ No newline at end of file
diff --git a/recipe/0002-mvm-audio/manifest.json b/recipe/0002-mvm-audio/manifest.json
index 10acccdc1..9191222c9 100644
--- a/recipe/0002-mvm-audio/manifest.json
+++ b/recipe/0002-mvm-audio/manifest.json
@@ -2,7 +2,7 @@
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "{{ id.url }}",
"type": "Manifest",
- "label": { "en": [ "Simplest Audio Example 1" ] },
+ "label": { "en": [ "Simplest Audio Example (IIIF Presentation v3)" ] },
"items": [
{
"id": "{{ id.path }}/canvas",
diff --git a/recipe/0002-mvm-audio/recipe.md b/recipe/0002-mvm-audio/recipe.md
new file mode 100644
index 000000000..624573e31
--- /dev/null
+++ b/recipe/0002-mvm-audio/recipe.md
@@ -0,0 +1,23 @@
+## Use Case
+
+The simplest viable manifest for audio content. This pattern presents a single audio file in a IIIF Presentation resource.
+
+## Implementation Notes
+
+The implementation is identical to the [image example][0001], except that the content is audio and the canvas has the `duration` property instead of the `height` and `width` properties. The value of the `duration` property [must be a floating point number](https://iiif.io/api/presentation/3.0/#duration). If the duration value you have is an integer, it therefore needs to be written with at least a decimal point and a trailing zero: `1985.0` rather than `1985`.
+
+## Example
+
+This example shows a Manifest with a single Canvas that lasts for 1985.024 seconds. It has a single audio file which is associated with it. The mp4 also has a duration of 1985.024 seconds.
+
+{% include manifest_links.html viewers="UV, Mirador, Clover, Ramp, Aviary, Theseus, Glycerine Viewer" manifest="manifest.json" %}
+
+{% include jsonviewer.html src="manifest.json" %}
+
+## Related Recipes
+
+* [Simplest Manifest - Image][0001] for the most minimal image Manifest
+* [Simplest Manifest - Video][0003] for the most minimal video Manifest
+
+{% include acronyms.md %}
+{% include links.md %}
diff --git a/recipe/0002-mvm-audio/v4/manifest.json b/recipe/0002-mvm-audio/v4/manifest.json
new file mode 100644
index 000000000..847089d15
--- /dev/null
+++ b/recipe/0002-mvm-audio/v4/manifest.json
@@ -0,0 +1,33 @@
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "{{ id.url }}",
+ "type": "Manifest",
+ "label": { "en": [ "Simplest Audio Example (IIIF Presentation v4)" ] },
+ "items": [
+ {
+ "id": "{{ id.path }}/timeline",
+ "type": "Timeline",
+ "duration": 1985.024,
+ "items": [
+ {
+ "id": "{{ id.path }}/timeline/page",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "{{ id.path }}/timeline/page/annotation",
+ "type": "Annotation",
+ "motivation": "painting",
+ "body": {
+ "id": "https://fixtures.iiif.io/audio/indiana/mahler-symphony-3/CD1/medium/128Kbps.mp4",
+ "type": "Sound",
+ "format": "audio/mp4",
+ "duration": 1985.024
+ },
+ "target": "{{ id.path }}/timeline"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/recipe/0002-mvm-audio/v4/recipe.md b/recipe/0002-mvm-audio/v4/recipe.md
new file mode 100644
index 000000000..dfa761e44
--- /dev/null
+++ b/recipe/0002-mvm-audio/v4/recipe.md
@@ -0,0 +1,24 @@
+## Use Case
+
+You have some digital or digitized audio that you would like to present on the web using IIIF.
+
+## Implementation Notes
+
+Audio resources are contained inside a [Timeline](https://preview.iiif.io/api/prezi-4/presentation/4.0/model/#timeline), which is required to have a `duration` property. The value of the `duration` property [must be a floating point number](https://preview.iiif.io/api/prezi-4/presentation/4.0/model/#duration). If the duration value you have is an integer, it needs to be written with at least a decimal point and a trailing zero: `1985.0` rather than `1985`.
+
+## Example
+
+This example shows a Manifest with a single Timeline that lasts for 1985.024 seconds. It has a single audio file which is associated with it. The mp4 also has a duration of 1985.024 seconds.
+
+{% include manifest_links.html manifest="v4/manifest.json" version="4" %}
+
+{% include jsonviewer.html src="v4/manifest.json" config='data-line="13"' %}
+
+## Related Recipes
+
+* [Simplest Manifest - Image][0001-4] for a minimal image Manifest
+* [Simplest Manifest - Video][0003-4] for a minimal video Manifest
+* [Simplest Manifest - 3D][0608] for a minimal 3D object Manifest
+
+{% include acronyms.md %}
+{% include links.md %}
diff --git a/recipe/0003-mvm-video/index.md b/recipe/0003-mvm-video/index.md
index e2c38bc0c..5381772a8 100644
--- a/recipe/0003-mvm-video/index.md
+++ b/recipe/0003-mvm-video/index.md
@@ -12,33 +12,30 @@ viewers:
- Aviary
- Theseus
- Glycerine Viewer
+v4-viewers:
+ - Mirador
+ - UV
+ - Aviary
topic:
- basic
- AV
code:
- iiif-prezi3
+top_tabs:
+ - label: Version 3
+ content: "{% capture my_include %}{%- include_relative recipe.md version='3' -%}{% endcapture %}{{ my_include | markdownify }}"
+ - label: Version 4
+ content: "{% capture my_include %}{%- include_relative v4/recipe.md version='4' -%}{% endcapture %}{{ my_include | markdownify }}"
---
+{{ theme.block-center-start }}
-## Use Case
-
-The simplest viable manifest for video content. This pattern presents a single video file in a IIIF Presentation resource.
-
-## Implementation Notes
-
-The implementation is identical to the [image example][0001], except that the content is video and the canvas has the `duration` property instead of the `height` and `width` properties. The value of the `duration` property [must be a floating point number](https://iiif.io/api/presentation/3.0/#duration). If the duration value you have is an integer, it therefore needs to be written with at least a decimal point and a trailing zero: `1985.0` rather than `1985`.
-
-## Example
-
-This example shows a Manifest with a single Canvas that lasts for 572 seconds, or just under 10 minutes. It has a single video file (lunchroom_manners_1024kb.mp4) which is associated with it. The mp4 also has a duration of 572 seconds.
-
-{% include manifest_links.html viewers="UV, Mirador, Clover, Ramp, Aviary, Theseus, Glycerine Viewer" manifest="manifest.json" %}
-
-{% include jsonviewer.html src="manifest.json" %}
-
-# Related Recipes
-
-* [Simplest Manifest - Image][0001] and [Simplest Manifest - Audio][0002] are equivalent to this example.
+{% include blocks/tabs.html tabs=page.top_tabs %}
-{% include acronyms.md %}
-{% include links.md %}
+{{ theme.block-end }}
+
\ No newline at end of file
diff --git a/recipe/0003-mvm-video/manifest.json b/recipe/0003-mvm-video/manifest.json
index ac04aa4b5..ba2db13e4 100644
--- a/recipe/0003-mvm-video/manifest.json
+++ b/recipe/0003-mvm-video/manifest.json
@@ -2,7 +2,7 @@
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "{{ id.url }}",
"type": "Manifest",
- "label": { "en": [ "Video Example 3" ] },
+ "label": { "en": [ "Simplest Video Example (IIIF Presentation 3)" ] },
"items": [
{
"id": "{{ id.path }}/canvas",
diff --git a/recipe/0003-mvm-video/recipe.md b/recipe/0003-mvm-video/recipe.md
new file mode 100644
index 000000000..c3d3dd349
--- /dev/null
+++ b/recipe/0003-mvm-video/recipe.md
@@ -0,0 +1,22 @@
+## Use Case
+
+The simplest viable manifest for video content. This pattern presents a single video file in a IIIF Presentation resource.
+
+## Implementation Notes
+
+The implementation is identical to the [image example][0001], except that the content is video and the canvas has the `duration` property additional to the `height` and `width` properties. The value of the `duration` property [must be a floating point number](https://iiif.io/api/presentation/3.0/#duration). If the duration value you have is an integer, it therefore needs to be written with at least a decimal point and a trailing zero: `1985.0` rather than `1985`.
+
+## Example
+
+This example shows a Manifest with a single Canvas that lasts for 572 seconds, or just under 10 minutes. It has a single video file (lunchroom_manners_1024kb.mp4) which is associated with it. The mp4 also has a duration of 572 seconds.
+
+{% include manifest_links.html viewers="UV, Mirador, Clover, Ramp, Aviary, Theseus, Glycerine Viewer" manifest="manifest.json" %}
+
+{% include jsonviewer.html src="manifest.json" %}
+
+# Related Recipes
+
+* [Simplest Manifest - Image][0001] and [Simplest Manifest - Audio][0002] are equivalent to this example.
+
+{% include acronyms.md %}
+{% include links.md %}
diff --git a/recipe/0003-mvm-video/v4/manifest.json b/recipe/0003-mvm-video/v4/manifest.json
new file mode 100644
index 000000000..b4b9c0164
--- /dev/null
+++ b/recipe/0003-mvm-video/v4/manifest.json
@@ -0,0 +1,37 @@
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "{{ id.url }}",
+ "type": "Manifest",
+ "label": { "en": [ "Simplest Video Example (IIIF Presentation 4)" ] },
+ "items": [
+ {
+ "id": "{{ id.path }}/canvas",
+ "type": "Canvas",
+ "height": 360,
+ "width": 480,
+ "duration": 572.034,
+ "items": [
+ {
+ "id": "{{ id.path }}/canvas/page",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "{{ id.path }}/canvas/page/annotation",
+ "type": "Annotation",
+ "motivation": "painting",
+ "body": {
+ "id": "https://fixtures.iiif.io/video/indiana/lunchroom_manners/high/lunchroom_manners_1024kb.mp4",
+ "type": "Video",
+ "height": 360,
+ "width": 480,
+ "duration": 572.034,
+ "format": "video/mp4"
+ },
+ "target": "{{ id.path }}/canvas"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/recipe/0003-mvm-video/v4/recipe.md b/recipe/0003-mvm-video/v4/recipe.md
new file mode 100644
index 000000000..237674423
--- /dev/null
+++ b/recipe/0003-mvm-video/v4/recipe.md
@@ -0,0 +1,23 @@
+## Use Case
+
+You have some digital or digitized video that you would like to present on the web using IIIF.
+
+## Implementation Notes
+
+The implementation is identical to the [image example][0001-4], except that the content is video and the Canvas has the `duration` property additional to the `height` and `width` properties. The value of the `duration` property [must be a floating point number](https://iiif.io/api/presentation/4.0/model/#duration). If the duration value you have is an integer, it therefore needs to be written with at least a decimal point and a trailing zero: `1985.0` rather than `1985`.
+
+## Example
+
+This example shows a Manifest with a single Canvas that lasts for 572 seconds, or just under 10 minutes. It has a single video file (lunchroom_manners_1024kb.mp4) which is associated with it. The mp4 also has a duration of 572 seconds.
+
+{% include manifest_links.html manifest="v4/manifest.json" version="4" viewers="UV, Mirador, Clover, Ramp, Aviary, Theseus" %}
+
+{% include jsonviewer.html src="v4/manifest.json" %}
+
+# Related Recipes
+
+* [Simplest Manifest - Image][0001-4] for the most minimal image Manifest
+* [Simplest Manifest - Audio][0002-4] for the most minimal audio Manifest
+
+{% include acronyms.md %}
+{% include links.md %}
diff --git a/recipe/0608-mvm-3d/index.md b/recipe/0608-mvm-3d/index.md
new file mode 100644
index 000000000..03410c2f1
--- /dev/null
+++ b/recipe/0608-mvm-3d/index.md
@@ -0,0 +1,26 @@
+---
+title: Simplest Manifest - Single 3D Model
+id: 1
+layout: recipe
+tags: [presentation]
+summary: "The simplest viable manifest for 3D content. If all you have for an object is one model on the web and a label, this pattern turns it into a IIIF Presentation resource."
+v4-viewers:
+topic:
+ - basic
+ - image
+top_tabs:
+ - label: Version 4
+ content: "{% capture my_include %}{%- include_relative v4/recipe.md version='4' -%}{% endcapture %}{{ my_include | markdownify }}"
+---
+
+{{ theme.block-center-start }}
+
+{% include blocks/tabs.html tabs=page.top_tabs %}
+
+{{ theme.block-end }}
+
\ No newline at end of file
diff --git a/recipe/0608-mvm-3d/v4/manifest.json b/recipe/0608-mvm-3d/v4/manifest.json
new file mode 100644
index 000000000..e3ad59d4e
--- /dev/null
+++ b/recipe/0608-mvm-3d/v4/manifest.json
@@ -0,0 +1,33 @@
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "{{ id.url }}",
+ "type": "Manifest",
+ "label": { "en": ["Single Model"] },
+ "summary": { "en": ["Viewer should render the model at the scene origin, and then viewer should add default lighting and camera"] },
+ "items": [
+ {
+ "id": "{{ id.path }}/scene/1",
+ "type": "Scene",
+ "label": { "en": ["A Scene"] },
+ "items": [
+ {
+ "id": "{{ id.path }}/scene/1/annotationPage/1",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "{{ id.path }}/scene/1/annotationPage/1/anno/1",
+ "type": "Annotation",
+ "motivation": ["painting"],
+ "body": {
+ "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/astronaut/astronaut.glb",
+ "type": "Model",
+ "format": "model/gltf-binary"
+ },
+ "target": "{{ id.path }}/scene/1/annotationPage/1"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/recipe/0608-mvm-3d/v4/recipe.md b/recipe/0608-mvm-3d/v4/recipe.md
new file mode 100644
index 000000000..5a1531604
--- /dev/null
+++ b/recipe/0608-mvm-3d/v4/recipe.md
@@ -0,0 +1,26 @@
+
+## Use Case
+
+You have 3D model video that you would like to present on the web using IIIF.
+
+## Implementation Notes
+
+3D models are contained inside a Scene. Unlike canvases and timelines a Scene does not require dimensions as it is imagined to be infintie in the x,y and z planes. In this simple example a model is painted on to the Scene at the origin and the viewer is expected to add default lighting and cameras.
+
+## Example
+This manifest shows the astronaut Model painted into the origin of the Scene.
+
+This asset (astronaut.glb) was originally uploaded by the user 'Poly by Google' to the Google Poly 3D model repository, which now no longer exists. It was released under the terms of a Creative Commons Attribution (CC-BY) license. The version of the model used here was downloaded from [poly.pizza](https://poly.pizza/m/dLHpzNdygsg), a 3D model repository rehosting a subset of Creative Commons-licensed material from Google Poly.
+
+{% include manifest_links.html manifest="v4/manifest.json" version="4" %}
+
+{% include jsonviewer.html src="v4/manifest.json" %}
+
+# Related Recipes
+
+* [Simplest Manifest - Image][0001-4] a basic image example
+* [Simplest Manifest - Audio][0002-4] a basic audio example
+* [Simplest Manifest - Video][0003-4] a basic video example
+
+{% include acronyms.md %}
+{% include links.md %}