+# Status.git
+
+A minimal git‐based self‐hosted status publishing solution.
+
+## What It Is
+
+ + A Python script, `post-receive`, suitable for use as a post‐receive
+ Git hook, which generates a number of `.jsonld` files from a
+ source repository of text posts.
+
+ + A small collection of H·T·M·L files designed to display the
+ generated `.jsonld` in a human‐readable fashion.
+
+## What It Is Not
+
+ + A server or server configuration (you will need to supply these
+ yourself; see below).
+
+ + Suitable for deployment on a simple filesystem server like
+ NeoCities or GitHub Pages (it requires both Git hooks and H·T·T·P
+ routing).
+
+ + Interactive in any way (i·e “social media”).
+
+ + Compatible with the ActivityPub fediverse (or any other push‐based
+ social media platform).
+
+## Script Configuration
+
+You will need to edit the `post-receive` script to adjust the following
+ constants to match your setup :—
+
+ + **`GIT_DIRECTORY`**:
+ The absolute path to this Git repository on your server.
+ It is expected that this will be a bare repository (ending in
+ `.git`).
+
+ + **`BUILD_DIRECTORY`**:
+ In order to access the files when you push, the repository will be
+ checked out here.
+ **This directory will be deleted on every push.**
+
+ + **`PUBLIC_DIRECTORY`**:
+ The directory that your server serves files from.
+ **This directory will be deleted on every push,** so if you need to
+ serve additional files (i·e those not generated by this script),
+ you should place those files in a different directory and adjust
+ your server configuration accordingly.
+ Note that the `post-receive` script and associted H·T·M·L files
+ provided by this repository expect a certain server configuration
+ described below.
+
+ + **`PUBLIC_URL`**:
+ The U·R·L that you are serving your site from (with no trailing
+ slash).
+ You cannot serve Status.git from a subdirectory.
+
+A `Makefile` is provided to make installing the `post-receive` script
+ on your server easy (assuming you have `ssh` access).
+You’ll need to supply some variables there, too :—
+
+ + **`USERNAME`**:
+ Your SSH username.
+
+ + **`DOMAIN`**:
+ The domain or other address of your site.
+
+ + **`GIT_REPOSITORY`**:
+ The absolute path to this Git repository, as above.
+
+## Server Configuration
+
+Your server should be configured to serve the following files from the
+ provided `PUBLIC_DIRECTORY` in response to the following requests :—
+
+### H·T·M·L responses
+
+These responses **must** be served with a `Content-Type` of
+ `text/html;charset=UTF-8` (or equivalent).
+Note that these paths **do not** have a trailing slash.
+
+ + **`GET /`**:
+ Serve the file at `/index.html`.
+
+ + **`GET /statuses`**:
+ Serve the file at `/.statuses.html`.
+ A `Link` header with the value
+ `</statuses.jsonld>;rel=meta;type="application/ld+json"` (or
+ equivalent) **must** be provided.
+
+ + **`GET /$YYYY-MM`** (where `$YYYY-MM` is an `xsd:gYearMonth`):
+ Serve the file at `/.topic.html`.
+ A `Link` header with the value
+ `</$YYYY-MM.jsonld>;rel=meta;type="application/ld+json"` (or
+ equivalent) **must** be provided.
+
+ + **`GET /$YYYY-MM/*`** (where `$YYYY-MM` is an `xsd:gYearMonth`):
+ Serve the file at `/.status.html`.
+ A `Link` header with the value
+ `</$YYYY-MM.jsonld>;rel=meta;type="application/ld+json"` (or
+ equivalent) **must** be provided.
+
+ + **`GET /topics`**:
+ Serve the file at `/.topics.html`.
+ A `Link` header with the value
+ `</topics.jsonld>;rel=meta;type="application/ld+json"` (or
+ equivalent) **must** be provided.
+
+ + **`GET /topics/$TOPIC`** (where `$TOPIC` matches `[0-9A-Za-z_-]+`):
+ Serve the file at `/.topic.html`.
+ A `Link` header with the value
+ `</$TOPIC.jsonld>;rel=meta;type="application/ld+json"` (or
+ equivalent) **must** be provided.
+
+ + **`GET /topics/$TOPIC/*`** (where `$TOPIC` matches
+ `[0-9A-Za-z_-]+`):
+ Serve the file at `/.status.html`.
+ A `Link` header with the value
+ `</$TOPIC.jsonld>;rel=meta;type="application/ld+json"` (or
+ equivalent) **must** be provided.
+
+### Json‐L·D responses
+
+These responses **should** be served with a `Content-Type` of
+ `application/ld+json`.
+In all cases, for `/$PATH.jsonld`, this just serves the file at
+ `/$PATH/index.jsonld`.
+
+ + **`GET /statuses.jsonld`**:
+ Serve the file at `/statuses/index.jsonld`.
+
+ + **`GET /$YYYY-MM.jsonld`** (where `$YYYY-MM` is an
+ `xsd:gYearMonth`):
+ Serve the file at `/$YYYY-MM/index.jsonld`.
+
+ + **`GET /topics.jsonld`**:
+ Serve the file at `/topics/index.jsonld`.
+
+ + **`GET /topics/$TOPIC.jsonld`** (where `$TOPIC` matches
+ `[0-9A-Za-z_-]+`):
+ Serve the file at `/topics/$TOPIC/index.jsonld`.
+
+### Other Headers
+
+All responses **should** have a `Access-Control-Allow-Origin` header
+ with a value of `*` (assuming your server does not use credentials
+ and is not being served behind a firewall).
+
+## Committing Statuses To Git
+
+The `post-receive` script will run whenever you make a commit to the
+ `live` branch, which should be set as your default.
+Statuses are represented by a small collection of files committed to
+ particular locations in this repository :—
+
+ + Files committed to `/YYYY/MM/DD/HH.MM.SSZ/` (the final component
+ can actually take any form but a time is **recommended**) are
+ ordinary statuses.
+
+ + Files committed to `/topic/TOPICNAME/a/b/c/d/xxxx` (where `a`, `b`,
+ `c`, and `d` are lowercase hexadecimal digits and `xxxx` can be
+ anything) is a status posted to a specific topic (`TOPICNAME`).
+ It is **recommended** that you make `a/b/c/d` the first four digits
+ of an MD5 hash of the status content and `xxxx` the remaining
+ digits (security is not an issue here, so MD5 is fine).
+ `TOPICNAME` should have the form `[0-9A-Za-z_-]+`.
+
+The intent is that “ordinary statuses” are a bit more ephemeral whereas
+ “topic statuses” can serve as reference material.
+Using an MD5 hash for topic statuses ensures you don’t post the same
+ thing twice.
+
+The files which represent a status are as follows :—
+
+ + **`text`**:
+ The text of the status.
+ Blank lines separate paragraphs; linebreaks will be preserved.
+ There is a special markup for links: `<https://link.example>`, or
+ `<https://link.example>="link text"` if you want to supply link
+ text.
+ At present, no other markup is supported.
+
+ + **`0=x_status_git_1.0`**:
+ This file is **optional** and not currently used for anything, but
+ indicates that the post follows the `1.0` format.
+ The contents of this file, if present, **must** be
+ `x_status_git_1.0`, optionally followed by a trailing newline.
+
+ + **`1=NAME`** (where `NAME` might be anything):
+ This file is **recommended** and indicates the author of the
+ status.
+ Only one author is currently supported.
+ The value of `NAME` **must** give the name of the author of the
+ status.
+ The contents of this file **must** give the author’s URL,
+ optionally followed by a trailing newline.
+
+ + **`3=YYYY-MM-DD`** (where `YYYY-MM-DD` is a date):
+ This file is **required** and indicates the date of the status.
+ Only one date is currently supported.
+ The value of `YYYY-MM-DD` **should** give the date of the status,
+ although this is not used (in favour of the full timestamp).
+ The contents of this file **must** give the full `xsd:dateTime`
+ timestamp of the status, optionally followed by a trailing
+ newline.
+
+ + **`4=IDENTIFIER`** (where `IDENTIFIER` might be anything):
+ This file is **required** and provides an identifier for the
+ status.
+ Only one identifier is currently supported.
+ The contents of this file **must** be an I·R·I which uniquely
+ identifies the status (for example, a U·U·I·D or `tag:` URI).
+ The value of `IDENTIFIER` **must** be a locally‐unique identifier
+ for the status and **should** resemble the contents where
+ possible.
+ (Note, however, that `IDENTIFIER` cannot contain slashes and need
+ not be a valid I·R·I.)
+
+Files with names that begin with the strings `2=` or `x_status_git_`
+ are reserved for backwards‐compatible extensions.
+
+Status.git has no opinion on how these files make their way into the
+ Git repository, except that all the files for a single status should
+ be added in the same commit.
+The intention is that the simple nature of these files will make them
+ easy to automate.
+
+## I Am Computer, How Do I Get Status?
+
+Assume you are given a U·R·L to a status collection, like `/statuses`,
+ `/YYYY-MM`, or `/topics/my_topic`.
+Make a `HEAD` request to this U·R·L.
+If there is a `Link` header with a `rel` of `meta` and a `type` of
+ `application/ld+json`, make a `GET` request to that U·R·L instead.
+Otherwise, make a `GET` request to the U·R·L you were given.
+
+Assuming the U·R·L you were given was valid, you will receive a
+ Json‐L·D response with a `@type` which is either an
+ `OrderedCollection` or an `OrderedCollectionPage`.
+One of the following will be true :—
+
+ + The response is an `OrderedCollectionPage`.
+ Its `items` will be an array of statuses, and the `prev` and
+ `next` properties will give U·R·Ls for previous and next
+ pages of statuses (if any exist).
+
+ + The response is an `OrderedCollection` with `first` and
+ `current` properties.
+ These properies give the U·R·Ls for the first and latest pages
+ of statuses, which you can fetch and process as above.
+
+ + Otherwise, the `items` property will be an array of every
+ status in the collection.
+
+ > If you receive a `Collection` instead of an `OrderedCollection`,
+ > you are probably looking at a topics listing.
+ > You will need to choose a topic from the `items` and then fetch it
+ > to receive the list of statuses.
+
+Statuses themselves have the following properties :—
+
+ + **`@id`**:
+ The identifier of the status.
+
+ + **`created`** [`dcterms:created`]:
+ The creation date for the status, as an `xsd:dateTime`.
+
+ + **`creator`** [`dcterms:creator`] (optional):
+ The author of the status, as an object with an `@id` and `name`
+ [`foaf:name`].
+
+ + **`identifier`** [`dcterms:identifier`]:
+ An I·R·I which uniquely identifies the status.
+ This differs from the `@id` in that it is not expected to be
+ dereferenceable.
+
+ + **`subject`** [`dcterms:subject`] (optional):
+ The topic of the status, for topic statuses.
+
+ + **`content`** [`sioc:content`]:
+ The content of the status, as an `rdf:XMLLiteral`.