Statac

Write

Pictures

Keep a picture beside the post, name it in the writing, and Statac publishes it, a photograph as smaller copies made for each screen.

Add a picture to a post

content/
  post-1/
    index.md
    photo-1.jpg
  post-2.md
  photo-2.jpg

In post-1/index.md:

![A gradient from blue to orange](photo-1.jpg)

The brackets hold what a reader who can’t see the picture is given. post-2.md shows photo-2.jpg the same way.

Write What the page shows
![A description](photo-1.jpg) The picture where it is written: in its sentence, or alone in its paragraph.
@figure("photo-1.jpg", alt="A description", caption="Photo 1.") The picture in a <figure>, with its caption beneath. Without alt or caption, those in the picture’s own file. wide=true gives the figure the class wide, and decorative=true marks it as decoration.
@gallery("photo-1.jpg", "photo-2.jpg") Several pictures, each a link to its largest copy. @gallery() shows every photograph beside a page that has a folder of its own.

@figure and @gallery are snippets a new site has, yours to change: see the starter.

How a name is found

Written Found
photo-1.jpg Beside the file it is written in.
/img/logo.png From the top: content/img/logo.png, or else static/img/logo.png.
https://example.org/photo-1.jpg Not looked for: left as written.
<img src="photo-1.jpg"> Not looked for: HTML you write is published as you wrote it.

On a site published under a path, such as https://example.org/blog/, a picture written from / needs no @url(...), unlike a link.

Describe it, or mark it decorative

A description goes in the brackets. For a picture under content/, it can also be written once, in a file beside the picture named after it with .yaml on the end. In photo-1.jpg.yaml:

alt: A gradient from blue to orange
caption: Photo 1.
credit: A photographer
Line What it does
alt The description, used wherever the picture is shown without one, as ![](photo-1.jpg).
caption Words to show with the picture. @figure shows them.
decorative true for a picture that is only decoration and needs no description.
optimise false publishes the file in place of copies.
Any other, such as credit Yours: it reaches templates with the rest.

The file is never published.

Markdown can’t tell empty brackets from a description left out, so mark a picture that is only decoration in one of these ways:

  • decorative: true in the picture’s own file
  • @figure("flourish-1.png", decorative=true) in the writing, or page.photo("flourish-1.png", decorative=true) in a template
  • alt="" on an <img> of your own, as HTML says it

What Statac makes from a photograph

A photograph is a JPEG, or a PNG or WebP that doesn’t move: screenshots too. Statac publishes copies at several widths, and the reader’s browser fetches the one that suits its screen.

The photograph’s width Its copies, with max_width at 1600
3000 400, 800, 1200, 1600
1500 400, 800, 1200, 1500
850 400, 850
300 300

Copies are made at 400, 800, 1200, 1600 and 2400 pixels wide, each where it is under nine tenths of the photograph’s width, and at the photograph’s own width. None is wider than max_width.

Each width is made as When
AVIF Always.
JPEG For the browsers that don’t show AVIF.
PNG, in place of the JPEG Where some pixel of the picture is see-through. A PNG or WebP that could be transparent and isn’t, as most screenshots are, gets the JPEG.

A photograph taken with the camera turned is turned upright. One in a wider colour space than the web’s is converted so its colours look the same. The copies carry nothing else of the file: not where or when it was taken, nor what took it.

Each copy is published beside where the photograph would be, named with its width and a mark that changes whenever the copy does: photo-1-800.5e6f7a8b.jpg.

The photograph itself

The photograph What is published
A page shows it Its copies.
A page links to it, as [the whole photograph](photo-1.jpg), or names it with og_image The file itself, whether or not a page shows it.
No page shows it or links to it The file itself.

The file itself is published byte for byte, so it carries whatever it held: where and when it was taken, what took it. Its copies carry none of that.

Where a JPEG, PNG or WebP published as it is holds where it was taken, statac check notes it:

note  Location published: `content/photo-1.jpg` holds where it was taken in its metadata
  Publish a copy without it, or add `location-published` to `quiet:` in `statac.yaml`.
  More: https://statac.dev/e/location-published/

statac build and statac serve say nothing of it. The same goes for every picture published from content/ as it is. statac check never looks inside a file in static/.

Which pictures get copies

Kind of file Published as Written into the page
JPEG, or a PNG or WebP that doesn’t move Copies A <picture> naming the copies
A PNG or WebP that moves The file as it is An <img> with its width and height
GIF, SVG or AVIF The file as it is An <img> with its width and height
HEIC or HEIF The file as it is An <img> with no size

Statac tells a picture’s kind by what the file holds, not by its name. An SVG has a size only where its first tag gives a width and a height in pixels.

Statac doesn’t read HEIC or HEIF, and few browsers show one. Export the photograph as a JPEG and show that.

What goes in the page

For a picture published as it is:

<img src="/post-1/drawing-1.gif" alt="How the parts fit" width="640" height="400" loading="lazy" decoding="async">

For a photograph:

<picture><source type="image/avif" srcset="/post-1/photo-1-400.1a2b3c4d.avif 400w, /post-1/photo-1-800.2e3f4a5b.avif 800w" sizes="(max-width: 46rem) 100vw, 46rem"><img src="/post-1/photo-1-800.5e6f7a8b.jpg" srcset="/post-1/photo-1-400.9c0d1e2f.jpg 400w, /post-1/photo-1-800.5e6f7a8b.jpg 800w" sizes="(max-width: 46rem) 100vw, 46rem" width="800" height="533" alt="A gradient from blue to orange" loading="lazy" decoding="async"></picture>

The browser chooses a copy by the sizes, which the site’s image_sizes gives.

Warning:

A stylesheet that narrows pictures with a max-width or a width on img needs height: auto beside it, or a picture made narrower is shown too tall.

The first build

Made 60 copies of 11 photographs.

Statac keeps every copy in .statac/, in the site’s folder, so a later build makes copies only of photographs new or changed.

After a build that publishes the site, Statac removes the copies no page shows any more. A build with --url adds copies and removes none.

statac check makes no copies and writes nothing.

Change what Statac makes

In statac.yaml:

max_width: 2400
Setting What it does Unless you say
max_width No copy is wider, in pixels. Under 400, each photograph gets one copy. It is for the whole site: in a picture’s own file it changes nothing. 1600
image_sizes How wide photographs are shown on the page, as the sizes of an <img>: (max-width: 40rem) 100vw, 40rem for a column 40rem wide that fills a narrow screen. (max-width: 46rem) 100vw, 46rem
optimise_images false makes no copies: each photograph is published as it is. true

Leave a photograph as it is

In photo-1.jpg.yaml:

optimise: false

The photograph is published as it is, and written into the page as any other picture is, with its width and height.

Pictures in templates and snippets

{% set picture = page.photo("photo-1.jpg") %}
<img src="{{ picture.src }}" width="{{ picture.width }}" height="{{ picture.height }}" alt="{{ picture.alt }}">

page.photo finds a name as the writing does. Any page can be asked, so a list shows each post’s picture with post.photo(post.cover).

Field What it is
src The address to show: a photograph’s copy 1,200 pixels wide, or its widest where none is that wide.
avif, fallback A photograph’s copies, as AVIF and as JPEG or PNG, each a srcset. Empty for a picture published as it is.
sizes The site’s image_sizes, or the call’s: page.photo("photo-1.jpg", sizes="(max-width: 30rem) 100vw, 15rem").
full The widest copy’s address, to link to. With full=true, one more copy at the photograph’s own width, whatever max_width says. For a picture published as it is, the picture.
width, height The size in pixels, a photograph’s once turned upright. Empty where it isn’t known.
alt, caption What the picture’s own file says, or empty.
name The file’s name read as words: photo-1.jpg as “Photo 1”.
A line of your own Each other line of the picture’s file, as picture.credit.

decorative=true marks the picture as decoration where it is shown.

page.photos(["photo-1.jpg", "photo-2.jpg"]) gives pictures in the order named, and page.photos() every photograph beside a page that has a folder of its own. Both take sizes, full and decorative.

Files, videos and recordings are asked for the same way: videos and files.

Where next?

  • Videos and files: videos, recordings and files beside a post, and videos kept on YouTube or Vimeo
  • Writing: Markdown, links and snippet calls
  • Sharing cards: the picture a link preview shows
  • Settings: everything in statac.yaml

Something unclear or wrong? Open an issue on GitHub.