Releases

v1.5.6

v1.5.6 cmc · 2026-09-12 02:21 UTC · source tar.gz

Descriptions and comments render again. No config changes required.

  • DeviantArt's editor stores descriptions and comments as a document tree rather than the Draft.js blocks the parser expected, so every current description and comment rendered empty. A new renderer handles paragraphs, headings, lists, quotes, code, breaks and rules; bold, italic, underline, strike, code and link marks; official and custom emotes; embedded artworks as proxied thumbnails linking to the post, under the instance's NSFW and hide-ai rules; GIF embeds and mentions as links. Draft.js and plain HTML descriptions still render as before.
  • Emotes in old HTML descriptions are mapped by image name rather than by fixed offsets, so ones the offsets did not fit show again.
  • Media and post URLs are parsed instead of sliced by offset; author.deviantart.com/art/... links now resolve.
FileBytesSHA-256
SHA256SUMS 407 4c731d5746
skunkyart-1.5.6-darwin-arm64.tar.gz 4232851 c28fec1b69
skunkyart-1.5.6-freebsd-amd64.tar.gz 4489677 f086e21fd2
skunkyart-1.5.6-linux-amd64.tar.gz 4508724 404ed5b946
skunkyart-1.5.6-linux-arm64.tar.gz 4089176 c0b5b94a8e

v1.5.5

v1.5.5 cmc · 2026-09-12 01:55 UTC · source tar.gz

Upstream queue fix. No config changes required.

  • A request whose client has already given up no longer takes a turn in the DeviantArt queue: the throttle watches the request context while waiting for a slot and while waiting out the interval, and a cancelled request leaves the interval to the next live one. Under a crawl this was turning the queue into a wall of timeouts for real visitors.
  • Load shedding: a request that would queue longer than a client waits is refused at once with a 503 and Retry-After: 5, never reaching DeviantArt. The API cache serves a stale entry instead when it holds one.
FileBytesSHA-256
SHA256SUMS 407 14a17e3b30
skunkyart-1.5.5-darwin-arm64.tar.gz 4224222 0943029ee2
skunkyart-1.5.5-freebsd-amd64.tar.gz 4476091 fc4baf2ee6
skunkyart-1.5.5-linux-amd64.tar.gz 4494244 6cf4d613c8
skunkyart-1.5.5-linux-arm64.tar.gz 4077627 7b4dcfcc68

v1.5.4

v1.5.4 cmc · 2026-09-11 19:27 UTC · source tar.gz

Media cache rotation fix and a dependency bump. No config changes required.

  • The media cache is trimmed to max-size by removing the oldest files, instead of being emptied. The rotation never touches the cache directory itself, so a bind-mounted cache no longer logs unlinkat and mkdir errors on every pass. Expired files no longer count toward the cap.
  • golang.org/x/net v0.59.0.
FileBytesSHA-256
SHA256SUMS 407 8be2cd9741
skunkyart-1.5.4-darwin-arm64.tar.gz 4223173 4bd05e817d
skunkyart-1.5.4-freebsd-amd64.tar.gz 4474231 c009d5f8ac
skunkyart-1.5.4-linux-amd64.tar.gz 4492604 0c162d1c5f
skunkyart-1.5.4-linux-arm64.tar.gz 4076206 fba6b0d20a

v1.5.3

v1.5.3 cmc · 2026-09-11 19:12 UTC · source tar.gz

Configurable upstream pacing. No config changes required.

  • New upstream block: min-interval-ms (default 400) and max-concurrent (default 2) replace the source constants, so an instance that DeviantArt bans can slow its own requests down without a rebuild. See SETUP.md.
FileBytesSHA-256
SHA256SUMS 407 2f8b14ea0a
skunkyart-1.5.3-darwin-arm64.tar.gz 4224396 413ea2345d
skunkyart-1.5.3-freebsd-amd64.tar.gz 4477023 4a07949d1a
skunkyart-1.5.3-linux-amd64.tar.gz 4495102 48d29113ef
skunkyart-1.5.3-linux-arm64.tar.gz 4078320 5afd8545a9

v1.5.2

v1.5.2 cmc · 2026-09-11 18:58 UTC · source tar.gz

Resilience against DeviantArt blocks, plus two fixes from the art.krz.sh incident. No config changes required.

  • API responses past their TTL are kept for api-cache.stale (default 1h) and served when DeviantArt fails or answers 403/429, so a short egress ban no longer takes the daily deviations, popular searches and feeds down. A block also starts a one minute backoff during which the instance stops asking DeviantArt, instead of every request hitting a WAF that has already said no. The hourly stats line counts stale serves.
  • /api/random answered 401 with proxying on: the media signing token was passed inside the path. It is now a query parameter, as on the media route.
  • The session bootstrap runs before the listener opens, so the first seconds after a restart no longer 502.
FileBytesSHA-256
SHA256SUMS 407 d6a92d6e95
skunkyart-1.5.2-darwin-arm64.tar.gz 4223848 768e4d7acf
skunkyart-1.5.2-freebsd-amd64.tar.gz 4476743 8b887e1ce4
skunkyart-1.5.2-linux-amd64.tar.gz 4494738 535baec283
skunkyart-1.5.2-linux-arm64.tar.gz 4078342 2c8f578743

v1.5.1

v1.5.1 cmc · 2026-09-11 16:12 UTC · source tar.gz

Build fix for the container image and the binary tarballs. No code changes from v1.5.0.

go.mod requires Go 1.26 since the API cache brought in golang.org/x/sync, but the Dockerfile and the binaries job still built with Go 1.25, so the v1.5.0 tag produced no image. Both now use Go 1.26.

The v1.5.0 notes describe everything else in this release line.

FileBytesSHA-256
SHA256SUMS 407 b681034f7b
skunkyart-1.5.1-darwin-arm64.tar.gz 4221726 517efc4e01
skunkyart-1.5.1-freebsd-amd64.tar.gz 4474183 cf5c8f57d8
skunkyart-1.5.1-linux-amd64.tar.gz 4492326 8f8b06751e
skunkyart-1.5.1-linux-arm64.tar.gz 4076795 007186ee1e

v1.5.0

v1.5.0 cmc · 2026-09-11 15:31 UTC · source tar.gz

Upstream request caching and rate limiting, escaped output, a valid Atom feed, and a translated interface.

Fewer requests to DeviantArt

DeviantArt bans egress IPs that ask too often, so this release cuts what an instance asks for.

  • In-memory cache of API responses with singleflight coalescing: repeat and concurrent views of one page cost one upstream call. api-cache block, on by default, 64 MB, 5 minute TTL.
  • Avatars and emotes are cached alongside media, and the media cache is on by default (lifetime 1w, max-size 200).
  • Cache-Control on every response: a year on signed media, a day on avatars and static files, five minutes on pages and API JSON. Error responses carry none.
  • /robots.txt keeps crawlers off search, the API, profiles, media and pagination.
  • A per-client token bucket for page, feed and API requests (rate-limit: 60 per minute, burst 20; 0 disables). Media is exempt. Behind a reverse proxy the client comes from X-Forwarded-For, trusted only from a loopback or private connection.
  • Comment threads load on request behind a "Comments (N)" link, so a post view is one upstream call instead of two.
  • /api/random picks from the cached daily deviations instead of firing random searches.

Fixes

  • Every string rendered from user input or DeviantArt content is escaped; templates use html/template.
  • The Atom feed validates: feed id, updated and self link, IRI entry ids, RFC 3339 timestamps, media:thumbnail.
  • User About tabs render interests, social links and registration age again.
  • Group search pagination no longer skips results 10 to 19.
  • Emojitar returns after a 404 instead of writing a body over it.
  • skunkyart -x -c no longer panics.
  • The 502 page shows one escaped line of the upstream error.
  • Templates are parsed once at startup, per language; a broken template fails at boot.

Interface

  • Every string is translated, including the ones the Go code used to hardcode; pages declare their language.
  • Standard viewport meta and portrait CSS sized for it.
  • Alt text on every image; the post title is a heading.
  • The "Folders" option on profiles, which was a favourites search, is labelled as one.

Operating

  • config.json is optional when it is the default path; -c must point at a real file. Built-in nsfw default is now false.
  • Working systemd unit (DynamicUser, state directory for the cache, hardening).
  • Makefile: build, test, lint, dist. Tarballs for linux/amd64, linux/arm64, darwin/arm64 and freebsd/amd64 are attached here and to the GitHub mirror's release.
  • CI on every push: build, vet, test with the race detector, golangci-lint. A daily job checks every listed instance.
  • gitbay is the canonical forge; the GitHub mirror only builds the image.
  • SETUP.md rewritten; API.md corrected (t is tag search).

Upgrading

No config changes are required. New blocks api-cache and rate-limit take their defaults when absent. If your config omitted cache, the media cache is now on and writes to ./cache; set "cache": {"enabled": false} to keep the old behaviour.

FileBytesSHA-256
SHA256SUMS 407 5a6434c9b6
skunkyart-1.5.0-darwin-arm64.tar.gz 4221709 6bb3b80b02
skunkyart-1.5.0-freebsd-amd64.tar.gz 4474201 629269e1db
skunkyart-1.5.0-linux-amd64.tar.gz 4492329 a1720489bc
skunkyart-1.5.0-linux-arm64.tar.gz 4076788 6e81929c55