ArtFirma

For artists and their web developers · record format v1

How to prepare your artwork pages

To sign a work, you share the link to its page with the signing app. The app reads the page, shows you a draft record, and after you confirm, freezes it: the tag carries a fingerprint of that exact record. This page says what the app looks for, so your pages produce complete records without retyping.

Confirm your key with your website

The app creates your signing key from 12 words that never leave your phone. To show visitors that the key is really yours, put one line on your own website. In the app: Settings → Register as artist shows it:

artfirma-key=9974b7731089acdc5569…
  • Either a DNS TXT record named _artfirma.example.com with that line as its value,
  • or a page example.com/pages/artfirma containing it (Shopify: Online Store → Pages → Add page, title “artfirma”). /.well-known/artfirma.txt and /artfirma.txt work too.

Then tap Check & register. Verification pages show “key confirmed by example.com” next to your name. The site is checked once, at registration: after that you can delete the page or the DNS record. The registration, and every tag you sign, stay valid.

One page per artwork, with a stable address

  • Each work needs its own public page, readable without logging in.
  • The last part of the address becomes the work id on the tag: …/products/contact-states-xii-film-009-020 → contact-states-xii-film-009-020. Allowed: lowercase letters, digits and hyphens, up to 64 characters (other characters are converted).
  • Do not rename the address of a work after its tag is signed. The tag keeps the old id; the record keeps the old link.

Describe the work with schema.org VisualArtwork (preferred)

Add a JSON-LD block to the page. Search engines read it too, so it is worth having anyway.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "VisualArtwork",
  "name": "Night Field",
  "creator": { "@type": "Person", "name": "Ana Ruiz" },
  "dateCreated": "2025",
  "artform": "Painting",
  "artMedium": "oil on linen",
  "size": "100 × 80 cm",
  "image": "https://example.com/images/night-field.jpg"
}
</script>

The block may also sit inside an @graph array. image may be a URL, an ImageObject with url or contentUrl, or a list (the first is used).

What goes into the record

Record fieldExample
id requirednight-field
title requiredNight Field
artist requiredAna Ruiz
photo requiredJPEG, PNG or WebP, ≥ 1200 px long side
year2025
artformPainting
mediumoil on linen
size100 × 80 cm
seriesfrom the 'Fields' series
notessigned and dated verso
statementshort text about the work
sourcefor people; never used for checking

Every field can be corrected in the draft before you confirm. Missing optional fields are simply left out.

Supported sources

Where each field comes from is not hard-coded: the app and our tools read the same file, sources.json. Sources are tried in this order; a field is taken from the first one that gives a value. The table below is generated from that file. New sites are added there, and the app picks the update up within a day, without a new version.

#SourceUsed whenFields
1schema.org VisualArtwork (JSON-LD)JSON-LD VisualArtworktitle ← JSON-LD name
artist ← JSON-LD creator.name
year ← JSON-LD dateCreated
artform ← JSON-LD artform
medium ← JSON-LD artMedium
size ← JSON-LD size
imageUrl ← JSON-LD image.url|contentUrl
2Artlogic CMS (galleries and artist sites)meta generator matching ^[Aa]rtlogic\bartist ← h1.artist without #artist_years
title ← .subtitle .title
year ← .subtitle .year matching ^((?:19|20)[0-9]{2})$
medium ← .detail_view_module_artwork_caption .medium or .medium
size ← .detail_view_module_artwork_caption .dimensions or .dimensions
notes ← .edition_details + .signed_and_dated + .signed
statement ← left empty
3Shopify product (/products/<handle>.json): vendor and short description linesa Shopify product pageartist ← Shopify product vendor matching ^(.* .*)$
description lines (also split at “|”):
year ← line matching ^(19|20)[0-9]{2}$
size ← line matching ^(?=.{1,60}$).*[0-9]+(?:[.,][0-9]+)? ?(?:cm|mm|inches|in|"|″|”)? ?(?:\([a-z]+\) ?)?[x×] ?[0-9]+(?:[.,][0-9]+)? ?(?:cm|mm|inches|in|"|″|”)(?![a-z]) (any case)
medium ← line matching ^(?=.{1,80}$)(?:original[ ,]+)?(?:oil|acrylic|mixed media|watercolou?r|gouache|ink|charcoal|pastel|tempera|encaustic|graphite|pencil|spray paint|enamel|collage)\b.*\b(?:on|over)\b (any case), then ^(?:[Oo]riginal[ ,]+)?(.+)$
notes ← line matching ^(?=.{1,60}$)signed\b (any case)
4Squarespace (7.0 and 7.1 product pages): title, description, size and medium from the description textmeta og:image matching \bsquarespace(?:-cdn)?\.com/title ← h1.product-title
artist ← meta og:site_name matching ^(.+?)(?: [|–—] .*)?$
size ← .product-excerpt or .product-description matching ([0-9]+(?:[.,][0-9]+)? ?(?:cm|mm|inches|in|"|″|”)? ?[x×] ?[0-9]+(?:[.,][0-9]+)?(?: ?(?:cm|mm|inches|in|"|″|”)? ?[x×] ?[0-9]+(?:[.,][0-9]+)?)? ?(?:cm|mm|inches|in|"|″|”))(?![a-z])
medium ← .product-excerpt or .product-description matching \b((?:[Oo]il|[Aa]crylic|[Mm]ixed media|[Ww]atercolou?r|[Gg]ouache|[Ii]nk|[Cc]harcoal|[Pp]astel|[Tt]empera|[Ee]ncaustic|[Gg]raphite|[Pp]encil|[Ss]pray paint|[Ee]namel|[Cc]ollage)(?: and [a-z]+)? on [A-Za-z ]+?)(?=[.,;]|$)
notes ← .product-excerpt or .product-description matching \b([Ss]igned(?: and [a-z]+)?)\b
statement ← .product-excerpt or .product-description
imageUrl ← .product-gallery-slides-item-image[data-image] or #productSlideshow img[data-image]
5Open Graphany pagetitle ← meta og:title
imageUrl ← meta og:image
artist ← meta og:site_name
statement ← meta og:description
6Shopify product (when the page itself gives nothing)a Shopify product pagetitle ← Shopify product title
artist ← Shopify product vendor
imageUrl ← Shopify product images.src

Pages without schema.org

Open Graph tags are enough for a minimal record (title, artist, photo, statement):

<meta property="og:title" content="Night Field">
<meta property="og:site_name" content="Ana Ruiz">
<meta property="og:image" content="https://example.com/images/night-field.jpg">
<meta property="og:description" content="Oil on linen, 2025.">

Shopify stores need nothing extra: the app also reads the product's public /products/<handle>.json: the vendor (when it is a person's name) and short description lines such as 2026, Oil on canvas, 100 x 80 cm, Signed lower right. One fact per line (or separated by |) is read best; longer text stays in the description you can keep.

Artlogic pages (galleries' and artists' sites built on Artlogic CMS) and Squarespace product pages are recognised automatically; see Supported sources. On Squarespace, put the size and medium in the product description, e.g. 100 x 80 cm, oil on canvas.

What exists today: one product page at a time, shared to the app (or typed in); no collection import, no webhook, no signing from a computer yet. A whole edition can be signed from one record: tap Sign seal again for each seal.

After signing, the record is frozen

  • The record and its photo are copied into the public registry and its archives. Changing your website later does not change them.
  • To correct a record, create a new one and sign the tag again. The tag moves to a new key version, and links read before that stop passing the online check.
  • The photo is stored at up to 1600 px on the long side: enough to compare with the work, not for print.

Check your page

Share the page link with the signing app. The draft shows which fields were found; empty ones mean the page does not provide them in a form listed above.