This document specifies the format and system used to create and maintain specifications for the interplanetary stack.
Interplanetary specs are designed to be easy to write and maintain while still providing support for document production features expected from Internet standards. A spec is a Markdown document enriched with a small number of additional directives (a deliberate goal being to avoid the proliferation of ad hoc syntax) and a specialised processor that knows how to resolve and extract metadata that is useful to support rich interlinking in a standards suite.
The name of the Markdown file matters, because it will be used as the spec's shortname.
The shortname of a spec is the key identifier that is used to refer to it when citing that
spec or importing its definitions. The shortname for this spec is spec-for-specs
which means that you can cite it using :cite[spec-for-specs]
which comes out as [spec-for-specs]
(a spec citing itself is not all that useful, really, but you can also do it from other
specs, which is kind of the point). The shortname SHOULD be unique inside interplanetary
specs, and ideally in the entirety of the relevant standards universe, though that can at times
prove challenging.
A spec MUST being with frontmatter. Frontmatter is a preamble to the document placed
right at the start, delimited with ---
and containing YAML data ([YAML]). The frontmatter
for this spec looks like this:
---
title: Specification Title
description: A short description for this specification.
date: 1977-03-15
editors:
- name: Robin Berjon
email: [email protected]
url: https://berjon.com/
github: darobin
twitter: robinberjon
mastodon: "@[email protected]"
affiliation:
name: Protocol Labs
url: https://protocol.ai/
maturity: stable
xref:
- dom
- test-methodology
tags: ['meta']
order: 0
---
The frontmatter MUST contain a title
field, which is the title of the specification. In addition,
it SHOULD include a description
field with the description of the specification.
The frontmatter MUST also contain an editors
field, which is an array of objects describing people
who are responsible for editing this given spec. The editors
field MUST contain at least one
person. The fields that describe a person are name
, email
, url
, github
, twitter
, mastodon
,
and affiliation
which is in turn an object with fields name
and url
. Each person as well as the
affiliation MUST have a name
; every other field is OPTIONAL.
The xref
field exemplified above is described in the references section.
The maturity
field indicates the document's stability. This list is subject to revision, but the
maturity levels currently supported are:
The date
field is a YYYY-MM-DD
specification of the last dated change to the spec.
The tags
field is an array with strings that indicate which group of specifications this particular
specification is part of. For example, the specification you are currently reading, Specs for Specs,
is part of the "meta" group of specifications.
The order
field is a numeric field that includes the order by which the specification will be displayed
in the lists of specifications in the homepage and group pages. For this, 0
is the highest order, and 999
is the default value.
A spec MUST have a title, which is to say an h1
heading (title
field in the frontmatter). It
also SHOULD have only one such title (every other heading should be h2
or more) and have the title right
after the frontmatter. The behaviour of multiple titles or titles positioned at random places in
the spec is undefined and has been shown to disappoint kittens under experimental conditions.
Sections in a spec are nested by using various heading depths. Note that nesting levels are
enforced automatically. If for instance you have an h5
following an h2
, it will be promoted to an
h3
(recursively if it had nested h6
s of its own).
All of the content between the h1
spec title and the first subheading of the document is considered
to be the abstract for the document and will be incorporated into the header material.
Sections automatically get an identifier based on their heading. This is convenient, but it can cause
broken links when the section heading changes. If you wish to specify your own ID for a section you can
do so by appending {#your-id}
to the heading, like so:
### My Cool Section {#cool}
Specifications SHOULD make use of [RFC2119] keywords such as MUST or MUST NOT in order to express conformance expectations as testable assertions.
All you need to do to avail yourself of these keywords is to type them in all caps, no markup required. Additionally, if you use one the processor will automatically add a reference to [RFC2119]. The available RFC2119 keywords are:
It is probably a bad idea to use the SHALL variants, and generally it is best to stick to MUST, SHOULD, MAY, and their negations. In an ideal world, a spec would stick to only using MUST and MUST NOT because optionality in standards is harmful. In practice, however, some flexibility can prove necessary.
I highly recommend reading A Method for Writing Testable Conformance Requirements ([test-methodology]). Hidden behind that fanciful, almost enticingly romantic title is a treasure trove of advice in writing good specification language. The core tenet of that document is simple: a good spec is a testable one, because tests are the empirical ground truth of interoperability. And in order to make a spec testable, it needs to be built from testable assertions and there is an art to writing those effectively, which includes the judicious application of RFC2119 keywords.
A number of additional structural constructs are available to capture common blocks that are useful in specs: issues, warnings, notes, and examples.
An issue looks like this:
This is a big, big problem.
And the code for it is:
:::issue
This is a big, big problem.
:::
A warning looks like this:
Be careful!!!
Thar be dragons!
And the code for it is:
:::warning
Be careful!!!
Thar be dragons!
:::
A note looks like this:
Really, you want to pay attention to these things, because they kind of tend to matter, you know.
And the code for it is:
:::note
Really, you want to pay attention to these things, because they kind of tend to matter,
you know.
:::
An example looks like this:
And then it's just document.getElementById('foo')
.
And the code for it is:
:::example
And then it's just `document.getElementById('foo')`.
:::
When including code, the best option is to specify the code's language as part of the code fence. This enables Prism to kick in and to carry out syntax highlighting.
A definition is a key concept in a specification that can be referenced from other parts of the
spec or in other specs. The definition is created with a :dfn[defined term]
directive. Some definitions can benefit
from having synonyms, and these can be specified as a comma-separated list with an also
attribute as in
:dfn[defined term]{also="term, def"}
.
Plurals are handled for you (for English-language specs), so that you can reference definitions without trouble.
There are two primary types of references: to definitions and to full documents that get added to the spec's bibliographic references section.
Once a definition has been created, it can be referenced with :ref[definition]
. This includes the synonyms it
was given, for instance def.
It's also possible to reference definitions from other specs by importing those other specs by referencing their shortnames
in the xref
section of the YAML frontmatter:
xref:
- dom
- spec-for-specs
Definitions are automatically extracted from each interplanetary spec and stored in the same repository, under
refs/dfn
. You can grep in there to find what you need to import if you are unsure which spec defines a given
term. For specs from the broader standards universe, you can use the xref tool that
is part of ReSpec to look them up. Definition from any spec in the
xref tool can be imported and used in an interplanetary spec. This typically covers
definitions from the W3C, IETF, WHATWG, ECMA TC39, the Khronos Group, Unicode, and an assortment of others.
Once that's done, you can reference, say, the DOM concept of element with just :ref[element]
as if it were
defined locally.
Citing specs or more generally documents like [html], [rfc8890], [privacy-principles], or [spec-for-specs]
is accomplished using the shortname in a
:cite[shortname]
block, as in :cite[html], :cite[rfc8890], :cite[privacy-principles], or :cite[spec-for-specs]
. The idea
is to use this mechanism to easily provide context when you are referring to notions defined in another document but not
specifically a definition in particular.
Simply by citing a given document it will be added to the bibliographic reference section that is automatically generated at the end of your spec. You can use any shortname listed in Specref (there are over 50k docs there) as well as any shortname from the interplanetary space.