Minimal Image Macro Server (mini-macro)

Self-hostable image macro creation and hosting service.

  • Add and use whatever template images you want
  • Add as many pieces of text, formatted as you want, to each image
  • Images are stored and transferred efficiently as SVGs
  • SVG markup is screen-reader accessible
  • Web UI and REST API for managing image macros and templates

Efficient, Accessible SVG Image Macros

Rather than render new PNG (or other raster) formatted images, the renderer used here actually generates SVG files that look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1"
  width="800" height="600"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  style="user-select: none">
  <title>Image Macro Title Text</title>

  <!-- The image template is referenced as a separate, external file -->
  <image x="0" y="0"
    width="800" height="600"
    xlink:href="http://example.com/abcdefghijkl">
    <title>Image Template Title Text</title>
  </image>
  
  <!-- Each section of text gets its own <text> node -->
  <text x="400" y="50"
    text-anchor="middle"
    font-size="48"
    font-family="sans-serif"
    font-weight="600"
    stroke="#000"
    stroke-width="2"
    fill="#fff"
    >Top Text</text>
    
  <text x="400" y="550"
    text-anchor="middle"
    font-size="48"
    font-family="sans-serif"
    font-weight="600"
    stroke="#000"
    stroke-width="2"
    fill="#fff"
    >Bottom Text</text>
</svg>

That sample XML above is about 800 bytes in total with the comments removed; The raster formats that might otherwise be used would typically be several kilobytes at least.

Obviously, the externally referenced template image still has to be downloaded. However that external image (the largest part of an image macro, and the part that gets reused over and over) can be cached separately by clients so that it does not need to be downloaded separately each time it gets used to make a new image. Additionally, only one copy of it actually gets stored on the server, regardless of how many times its used.

Additionally, since an SVG is markup rather than a raster image, they can be read by screen readers (including the additional <title> text for both the whole image, and the template).

Embedding in HTML

The one drawback to this approach is that, in web browsers, SVGs do not load external resources when rendered in an image context (e.g. when used in an <img> tag). That said, you can embed it using either the <embed> or <object> elements, which will both render it as a document.

<!-- NOT This: <img> doesn't work with external resources -->
<img type="image/svg+xml" src="http://example.com/FrztglsLexLRWg">

<!-- Either of these will work: -->
<embed type="image/svg+xml" src="http://example.com/FrztglsLexLRWg"></embed>
<object type="image/svg+xml" data="http://example.com/FrztglsLexLRWg"></object>

REST API

Image Template List

Media Type: application/vnd.mini-macro.image-templates+json

todo

Supports: GET

{
  "items": [
    {
      "id": "<template_id>",
      "title": "Image Template Title",
      "width": 800,
      "height": 600,
      "links": {
        "self": {
          "href": "/templates/<template_id>",
          "type": "application/vnd.mini-macro.image-template+json"
        },
        "alternate": {
          "href": "/templates/<template_id>",
          "type": "image/png"
        }
      }
    }
  ],
  "links": {
    "next": {
      "href": "/templates?anchor=<template_id>",
      "type": "application/vnd.mini-macro.image-templates+json"
    }
  }
}

Image Template

General Support: DELETE

Media Type: application/vnd.mini-macro.image-template+json

todo

Supports: GET, POST, PUT

{
  "id": "<template_id>",
  "title": "Image Template Title",
  "width": 800,
  "height": 600,
  "links": {
    "self": {
      "href": "/templates/<template_id>",
      "type": "application/vnd.mini-macro.image-template+json"
    },
    "alternate": {
      "href": "/templates/<template_id>",
      "type": "image/png"
    }
  }
}

Other Media Types: image/png, image/jpeg

Supports: GET, PUT

Image Macro

General Support: DELETE

Media Type: application/vnd.mini-macro.image-macro+json

todo

Supports: GET, POST, PUT

{
  "id": "<image_id>",
  "name": "Image Macro Name",
  "text_style": {
    "fill": "#fff",
    "stroke": "#000",
    "stroke_width": 2,
    "font_size": 48,
    "font_family": "sans-serif",
    "font_weight": 600
  },
  "text": [
    {
      "text": "Top Text",
      "top": 50,
      "left": 400,
    },
    {
      "text": "Bottom Text",
      "top": 550,
      "left": 400,
    },
  ]
  "links": {
    "self": {
      "href": "/images/<template_id>",
      "type": "application/vnd.mini-macro.image-macro+json"
    },
    "alternate": {
      "href": "/images/<template_id>",
      "type": "image/png"
    },
    "/rel/template": {
      "href": "/templates/<template_id>",
      "type": "application/vnd.mini-macro.image-template+json"
    }
  }
}

Other Media Types: image/svg+xml

Supports: GET

Description
No description provided
Readme 86 KiB
Languages
TypeScript 100%