3 A minimal git‐based self‐hosted status publishing solution.
 
   7  +  A Python script, `post-receive`, suitable for use as a post‐receive
 
   8       Git hook, which generates a number of `.jsonld` files from a
 
   9       source repository of text posts.
 
  11  +  A small collection of H·T·M·L files designed to display the
 
  12       generated `.jsonld` in a human‐readable fashion.
 
  16  +  A server or server configuration (you will need to supply these
 
  19  +  Suitable for deployment on a simple filesystem server like
 
  20       NeoCities or GitHub Pages (it requires both Git hooks and H·T·T·P
 
  23  +  Interactive in any way (i·e “social media”).
 
  25  +  Compatible with the ActivityPub fediverse (or any other push‐based
 
  26       social media platform).
 
  28 ## Script Configuration
 
  30 You will need to edit the `post-receive` script to adjust the following
 
  31   constants to match your setup :—
 
  33  +  **`GIT_DIRECTORY`**:
 
  34     The absolute path to this Git repository on your server.
 
  35     It is expected that this will be a bare repository (ending in
 
  38  +  **`BUILD_DIRECTORY`**:
 
  39     In order to access the files when you push, the repository will be
 
  41     **This directory will be deleted on every push.**
 
  43  +  **`PUBLIC_DIRECTORY`**:
 
  44     The directory that your server serves files from.
 
  45     **This directory will be deleted on every push,** so if you need to
 
  46       serve additional files (i·e those not generated by this script),
 
  47       you should place those files in a different directory and adjust
 
  48       your server configuration accordingly.
 
  49     Note that the `post-receive` script and associted H·T·M·L files
 
  50       provided by this repository expect a certain server configuration
 
  54      The U·R·L that you are serving your site from (with no trailing
 
  56      You cannot serve Status.git from a subdirectory.
 
  58 A `Makefile` is provided to make installing the `post-receive` script
 
  59   on your server easy (assuming you have `ssh` access).
 
  60 You’ll need to supply some variables there, too :—
 
  66     The domain or other address of your site.
 
  68  +  **`GIT_REPOSITORY`**:
 
  69     The absolute path to this Git repository, as above.
 
  71 ## Server Configuration
 
  73 Your server should be configured to serve the following files from the
 
  74   provided `PUBLIC_DIRECTORY` in response to the following requests :—
 
  78 These responses **must** be served with a `Content-Type` of
 
  79   `text/html;charset=UTF-8` (or equivalent).
 
  80 Note that these paths **do not** have a trailing slash.
 
  83     Serve the file at `/index.html`.
 
  85  +  **`GET /statuses`**:
 
  86     Serve the file at `/.statuses.html`.
 
  87     A `Link` header with the value
 
  88       `</statuses.jsonld>;rel=meta;type="application/ld+json"` (or
 
  89       equivalent) **must** be provided.
 
  91  +  **`GET /$YYYY-MM`** (where `$YYYY-MM` is an `xsd:gYearMonth`):
 
  92     Serve the file at `/.topic.html`.
 
  93     A `Link` header with the value
 
  94       `</$YYYY-MM.jsonld>;rel=meta;type="application/ld+json"` (or
 
  95       equivalent) **must** be provided.
 
  97  +  **`GET /$YYYY-MM/*`** (where `$YYYY-MM` is an `xsd:gYearMonth`):
 
  98     Serve the file at `/.status.html`.
 
  99     A `Link` header with the value
 
 100       `</$YYYY-MM.jsonld>;rel=meta;type="application/ld+json"` (or
 
 101       equivalent) **must** be provided.
 
 104     Serve the file at `/.topics.html`.
 
 105     A `Link` header with the value
 
 106       `</topics.jsonld>;rel=meta;type="application/ld+json"` (or
 
 107       equivalent) **must** be provided.
 
 109  +  **`GET /topics/$TOPIC`** (where `$TOPIC` matches `[0-9A-Za-z_-]+`):
 
 110     Serve the file at `/.topic.html`.
 
 111     A `Link` header with the value
 
 112       `</$TOPIC.jsonld>;rel=meta;type="application/ld+json"` (or
 
 113       equivalent) **must** be provided.
 
 115  +  **`GET /topics/$TOPIC/*`** (where `$TOPIC` matches
 
 117     Serve the file at `/.status.html`.
 
 118     A `Link` header with the value
 
 119       `</$TOPIC.jsonld>;rel=meta;type="application/ld+json"` (or
 
 120       equivalent) **must** be provided.
 
 122 ### Json‐L·D responses
 
 124 These responses **should** be served with a `Content-Type` of
 
 125   `application/ld+json`.
 
 126 In all cases, for `/$PATH.jsonld`, this just serves the file at
 
 127   `/$PATH/index.jsonld`.
 
 129  +  **`GET /statuses.jsonld`**:
 
 130     Serve the file at `/statuses/index.jsonld`.
 
 132  +  **`GET /$YYYY-MM.jsonld`** (where `$YYYY-MM` is an
 
 134     Serve the file at `/$YYYY-MM/index.jsonld`.
 
 136  +  **`GET /topics.jsonld`**:
 
 137     Serve the file at `/topics/index.jsonld`.
 
 139  +  **`GET /topics/$TOPIC.jsonld`** (where `$TOPIC` matches
 
 141     Serve the file at `/topics/$TOPIC/index.jsonld`.
 
 145 All responses **should** have a `Access-Control-Allow-Origin` header
 
 146   with a value of `*` (assuming your server does not use credentials
 
 147   and is not being served behind a firewall).
 
 149 ## Committing Statuses To Git
 
 151 The `post-receive` script will run whenever you make a commit to the
 
 152   `live` branch, which should be set as your default.
 
 153 Statuses are represented by a small collection of files committed to
 
 154   particular locations in this repository :—
 
 156  +  Files committed to `/YYYY/MM/DD/HH.MM.SSZ/` (the final component
 
 157       can actually take any form but a time is **recommended**) are
 
 160  +  Files committed to `/topic/TOPICNAME/a/b/c/d/xxxx` (where `a`, `b`,
 
 161       `c`, and `d` are lowercase hexadecimal digits and `xxxx` can be
 
 162       anything) is a status posted to a specific topic (`TOPICNAME`).
 
 163     It is **recommended** that you make `a/b/c/d` the first four digits
 
 164       of an MD5 hash of the status content and `xxxx` the remaining
 
 165       digits (security is not an issue here, so MD5 is fine).
 
 166     `TOPICNAME` should have the form `[0-9A-Za-z_-]+`.
 
 168 The intent is that “ordinary statuses” are a bit more ephemeral whereas
 
 169   “topic statuses” can serve as reference material.
 
 170 Using an MD5 hash for topic statuses ensures you don’t post the same
 
 173 The files which represent a status are as follows :—
 
 176     The text of the status.
 
 177     Blank lines separate paragraphs; linebreaks will be preserved.
 
 178     There is a special markup for links: `<https://link.example>`, or
 
 179       `<https://link.example>="link text"` if you want to supply link
 
 181     At present, no other markup is supported.
 
 183  +  **`0=x_status_git_1.0`**:
 
 184     This file is **optional** and not currently used for anything, but
 
 185       indicates that the post follows the `1.0` format.
 
 186     The contents of this file, if present, **must** be
 
 187       `x_status_git_1.0`, optionally followed by a trailing newline.
 
 189  +  **`1=NAME`** (where `NAME` might be anything):
 
 190     This file is **recommended** and indicates the author of the
 
 192     Only one author is currently supported.
 
 193     The value of `NAME` **must** give the name of the author of the
 
 195     The contents of this file **must** give the author’s URL,
 
 196       optionally followed by a trailing newline.
 
 198  +  **`3=YYYY-MM-DD`** (where `YYYY-MM-DD` is a date):
 
 199     This file is **required** and indicates the date of the status.
 
 200     Only one date is currently supported.
 
 201     The value of `YYYY-MM-DD` **should** give the date of the status,
 
 202       although this is not used (in favour of the full timestamp).
 
 203     The contents of this file **must** give the full `xsd:dateTime`
 
 204       timestamp of the status, optionally followed by a trailing
 
 207  +  **`4=IDENTIFIER`** (where `IDENTIFIER` might be anything):
 
 208     This file is **required** and provides an identifier for the
 
 210     Only one identifier is currently supported.
 
 211     The contents of this file **must** be an I·R·I which uniquely
 
 212       identifies the status (for example, a U·U·I·D or `tag:` URI).
 
 213     The value of `IDENTIFIER` **must** be a locally‐unique identifier
 
 214       for the status and **should** resemble the contents where
 
 216     (Note, however, that `IDENTIFIER` cannot contain slashes and need
 
 217       not be a valid I·R·I.)
 
 219 Files with names that begin with the strings `2=` or `x_status_git_`
 
 220   are reserved for backwards‐compatible extensions.
 
 222 Status.git has no opinion on how these files make their way into the
 
 223   Git repository, except that all the files for a single status should
 
 224   be added in the same commit.
 
 225 The intention is that the simple nature of these files will make them
 
 228 ## I Am Computer, How Do I Get Status?
 
 230 Assume you are given a U·R·L to a status collection, like `/statuses`,
 
 231   `/YYYY-MM`, or `/topics/my_topic`.
 
 232 Make a `HEAD` request to this U·R·L.
 
 233 If there is a `Link` header with a `rel` of `meta` and a `type` of
 
 234   `application/ld+json`, make a `GET` request to that U·R·L instead.
 
 235 Otherwise, make a `GET` request to the U·R·L you were given.
 
 237 Assuming the U·R·L you were given was valid, you will receive a
 
 238   Json‐L·D response with a `@type` which is either an
 
 239   `OrderedCollection` or an `OrderedCollectionPage`.
 
 240 One of the following will be true :—
 
 242  +  The response is an `OrderedCollectionPage`.
 
 243     Its `items` will be an array of statuses, and the `prev` and
 
 244       `next` properties will give U·R·Ls for previous and next
 
 245       pages of statuses (if any exist).
 
 247  +  The response is an `OrderedCollection` with `first` and
 
 248       `current` properties.
 
 249     These properies give the U·R·Ls for the first and latest pages
 
 250       of statuses, which you can fetch and process as above.
 
 252  +  Otherwise, the `items` property will be an array of every
 
 253       status in the collection.
 
 255  >  If you receive a `Collection` instead of an `OrderedCollection`,
 
 256  >    you are probably looking at a topics listing.
 
 257  >  You will need to choose a topic from the `items` and then fetch it
 
 258  >    to receive the list of statuses.
 
 260 Statuses themselves have the following properties :—
 
 263     The identifier of the status.
 
 265  +  **`created`** [`dcterms:created`]:
 
 266     The creation date for the status, as an `xsd:dateTime`.
 
 268  +  **`creator`** [`dcterms:creator`] (optional):
 
 269     The author of the status, as an object with an `@id` and `name`
 
 272  +  **`identifier`** [`dcterms:identifier`]:
 
 273     An I·R·I which uniquely identifies the status.
 
 274     This differs from the `@id` in that it is not expected to be
 
 277  +  **`subject`** [`dcterms:subject`] (optional):
 
 278     The topic of the status, for topic statuses.
 
 280  +  **`content`** [`sioc:content`]:
 
 281     The content of the status, as an `rdf:XMLLiteral`.