-- prelude
This post is written in NeoDoc to provide
an example of what the format looks like.
A version with syntax highlighting and
live links is available >> here |
https://neodoc.style/blog/neodoc-and-the-atmosphere/ >>
if you'd like to read it that way.
-- tldr
I believe content portability is critical
to fulfilling the promise of a decentralized
internet. After all, being able to move your
content doesn't count for much if it doesn't
work anywhere else. You're implicitly
locked-in, even if you're seemingly in
control^^control^^.
A few years ago, I designed a plain-text
format to replace Markdown on >> my sites |
https://links.alanwsmith.com/ >>.
It's called NeoDoc and it offers a potential
solution for bringing portable, human-readable
content to the Atmosphere.
You can learn more about it at
>> neodoc.style | https://neodoc.style/ >>
-- title
NeoDoc and The Atmosphere
Hey folks,
While I've been on Bluesky for a bit, I
didn't really know about the Atmosphere until
recently. The more I learn, the more it has
my attention. I can't remember the last time
I was this excited about new tech.
My introduction was standard.site^^standard^^.
It made several appearances in my feed over
the past few weeks. I jumped^^jump^^ on it.
It's the kind of stuff I dream about^^manifesto^^.
I wasn't entirely sure how content worked
in standard.site and went looking for details.
One thing the leaflet^^leaflet^^ post I found
points out is that the lexicon is for content
discovery and social features. But,
-- blockquote/
Importantly, [it] is not a standard for
site content.
-- /blockquote
The only other^^other^^ post I've seen on a
content standard for the Atmosphere has to do
with a wordpress lexicon for publishing HTML.
-- h2
The Contenders
I submit that HTML could work as a standardized
content format. It's a battle tested standard
that renders natively in browsers without
modification. There are, however, a couple
things that recommend against it.
-- numbered/
1. It's not friendly to write by hand.
Unless you're hard-core, it's not something
most folks are into.
2. It's tough to standardize different
types of content. Microformats^^micro^^
were an attempt. They never took off.
That's at least in part because they lock
the content into the rendering layer. You
can do all kinds of things with CSS, but
you're stuck with a specific set of elements
and have to set up a separate parser if
you want to use the data in them
independently.
-- /numbered
Markdown^^md^^ is another option. It's easy to
learn and has huge market share in the developer
community. While it's great for blog posts,
it sucks for everything else. You can always
roll your own HTML to do interesting work.
But, you wind up back with its unwieldy
nature and parsing complexity.
The key feature missing from Markdown
is the ability to define content types.
For example, say you want to make a page of
book reviews with explicit styles for the
title, author, rating, and your thoughts.
There's no native way in Markdown to define
a container that provides access to the
individual pieces of data.
About the best you can do is define specific
positions for each piece of information and
write a custom parser to process and assemble
them^^mdbook^^. Possible, but you'd be better
off writing the HTML directly which leads
back to the same issues.
-- h2
Introducing NeoDoc
There are other content formats out there.
I reviewed a bunch when I got fed up with
Markdown and decided to switch to something
else for >> my various project websites
| https://links.alanwsmith.com/ >>.
None of the alternatives offered the combination
of flexibility and ease of use I was after.
So, I designed a new format. It's called
NeoDoc and you're reading it right
now^^maybe^^.
NeoDoc is designed to be simple to write
without sacrificing the power built into
HTML. The format breaks down like this:
-- list/
-- h3: The Details
- NeoDocs are built from sections. Each
one starts with two dashes and a name. For
example, we're currently in a ``list``
section.
Section names that don't end with a ``/``
keep going until the next section starts.
Section names that have a ``/``at the end
can wrap other sections. They go until they
hit the matching tag that closes them
(e.g. the ``-- /list``for this section
that you'll see below).
- Sections can have attributes like the
``-- h3: The Details``above. They're
available during rendering to do thing
like adding an ``H3``tag with specific
text above a list (which is what this one
does when this page is rendered to HTML).
- There's a pre-defined set of sections like:
``list``, ``checklist``, and ``numbered``.
You can also make ad hoc sections simply by
naming them. For example, you can make a
``-- book-review``section.
- Custom sections can have attributes just
like the pre-defined ones. So, we can make
a book review like this:
-- pre/
-- book-review
-- title: Dungeon Crawler Carl
-- author: Matt Dinniman
-- rating: 5 stars
-- tags: fantasy
Always trust the friends you've known
since third grade when they recommend
a book...
-- /pre
- Inline formatting and shorthands are
available for spans of text. For example,
you can wrap text in asterisks that
convert to HTML ``strong``tags during
rendering like:
**Alfa Bravo Charlie**
- Inline spans can also have attributes.
For example, here's a ``class``attribute
with the strong shorthand syntax:
**Alfa Bravo Charlie | class: green**
-- /list
That's it.
Sections, spans, and attributes.
A simple combination that turns out
to be incredibly powerful.
-- h2
Outro
I designed NeoDoc three years ago. It's
currently embedded in my personal static
site generator where it powers
>> something like three thousand pages |
https://www.alanwsmith.com/neo-files/report >>.
The format feels like a natural fit for
the Atmosphere. So, I'm extracting the
tools to make them independently available.
Once they're ready, I'll make them open
source so anyone can use them.
I'm incredibly excited about the Atmosphere.
I hope NeoDoc can become a part of it.
Because, if I'm right, the ability to
easily move the stuff we make to wherever
we want it will be key to practical
decentralization. I believe NeoDoc can
be instrumental in making that happen.
-alan
-- endnote
If you've got questions or feedback,
I'm all ears:
>> @al9000.com |
https://bsky.app/profile/al9000.com >>
-- endnote
I'd love to see NeoDoc become an active
participant in the Atmosphere. However, it's
way more important to me that general content
gets standardized on __something__, regardless
of what it is.
There will always be a need for custom formats
for specific applications. For everything else,
if we can't move it, it fails the promise
and potential of decentralization.
-- endnote
I didn't get into it here, but the section
and attribute approach NeoDoc uses effectively
turn content into a free-form database.
For example, you can aggregate all your
``-- book-review``content in one place.
Or, build something like Goodreads by
watching the fire hose for those sections
and building social features around them
(name-spacing is, of course, recommended).
The content will vary in how messy it is.
That's a feature. Not a bug. We've been living
so long in systems that force our content
into database schemas that we've forgotten
what a personal touch feels like.
NeoDoc provides structure for finding,
grouping, and laying out content without
forcing everything to fit rigid data
structures that prioritize storage over
creativity.
-- endnote/
I also didn't get into how transforming
content works. At the high level, the
reference NeoDoc app (when it's extracted
from my static site generator) performs
three functions:
-- numbered/
1. Takes a NeoDoc formatted input and
transforms it into a JSON formatted AST.
2. Transforms a NeoDoc AST into HTML
based on a standardized set of default
templates.
3. Accepts optional templates that override
the defaults when generating output.
-- /numbered
Collectively, that means NeoDoc can be
used out of the box to generate
standardized HTML. App can override the
templates to either supply their own
or pass in templates from the content
authors. The combination lets apps provide
complete control over the output with
the option to pass that control on to
the authors.
More details on templating will be in
the docs.
-- /endnote
-- endnote
Another thing Markdown suffers from is lack
of an official standard. Different,
competing standards have cropped up as a
result. NeoDoc's development includes a
standard in the form of a comprehensive
test suite for use in validating conforming
processors.
-- endnote
NeoDoc isn't a theoretical idea. I've
been using it in production on my site
for years. The fundamentals are solid.
I expect feedback from other folks will
lead to some modifications during a
beta period as more folks use it. But,
I don't foresee anything that would
significantly change its potential.
Work on extracting NeoDoc from my site
generator is underway. I don't have a
specific target date, but it won't be
that long until it's ready for other
folks to start poking at.
-- footnote
-- id: control
It is, of course, possible to migrate
data from one format to another. However,
that's a non-trivial amount of friction
most folks would need someone else to
set up for them (e.g. most folks aren't
going to build their own ETL systems).
-- footnote
-- id: standard
>> Standard.site | https://standard.site/ >>
The shared lexicons for long-form
publishing on AT Protocol.
-- footnote
-- id: jump
I've still got some work to do to get
standard.site connections up and running
for my site. The requirement to verify
every page individually is more work
than I've got time for at the moment.
-- footnote
-- id: manifesto
>>A Vision for the Web |
https://www.alanwsmith.com/en/2v/xa/cn/vj/>>
(originally titled "A Website Manifesto")
is a draft where I kicked around ideas
for a more interconnected web.
Basically, I was trying to figure out
how to build the Atmosphere using
RSS.
-- footnote
-- id: leaflet
>> Leaflet, standard.site, and open
social publishing! |
https://lab.leaflet.pub/3md4qsktbms24 >>
is a great intro to what standard.site is
all about and its integration into leaflet.
-- footnote
-- id: other
>> Automatically syncing your blog to atproto
and standard.site |
https://jola.dev/posts/automatically-syncing-your-blog-atproto-standard-site >>
which mentions the wordpress HTML lexicon.
At least, I think it's referencing a lexicon. I'm
not sure and don't yet know where to look to
figure that out.
-- footnote
-- id: micro
>> Microformats | https://indieweb.org/microformats >>
The >> IndieWeb's | https://indieweb.org/ >>
attempt at standardizing content that never quite
made it.
-- footnote
-- id: md
>> Markdown | https://www.markdownguide.org/ >>
The de facto standard for static site generators
everywhere. Great at what it does, but limited
in what it can achieve.
-- footnote
-- id: mdbook
For example, you could set up a parser to pull the
title from an H2 and then put the author in an H3
with the text for the review below that. That
would work, but it's super brittle and doesn't
provide for expansion without rewriting the
parser and updated all the existing content.
-- footnote
-- id: maybe
Assuming a processor wasn't used to render
this content that transformed the content
to straight HTML.
-- metadata
-- created: 2026-08-03T16:22:00-04:00
-- published: 2026-08-04T16:08:00-04:00
-- id: 01/n7/1y/38
-- tags: neodoc
-- status: done
Welcome! There are a LOT of people with opinions on text formats here ![]()
I have done terrible crimes with YAML frontmatter over the years!
Wonderful write-up. I think alongside this, there should be an effort to establish a common container format that provides a sufficiently extensible structure for metadata such as content format, language, authorship, rights, etc. I personally see MASL as fulfilling this role:
hehehe, yeah. I expect text formats are something you can ask ten people about and get twelve opinions. I guess you could say NeoDoc is the manifestation of mine. I figure I’ve already got the parser so I might as well offer it for consideration.
(At a minimum it’ll be a fun exercise to see if the way I think makes sense to other folks or if it only makes sense to me because I built it.
)
-- title
Progress Update [2026-08-07]
I'm making good progress extracting the
NeoDoc parser from my static site generator.
And by "extracting", I really mean redoing
it from scratch as a stand-alone library.
The original code is much to intertwined
with the generator to untangle in any
meaningful way.
I don't have an ETA yet. I'll be able
to give more guidance in a few days.
-a
-- metadata
-- created: 2026-08-07T07:51:00-04:00
-- published: 2026-08-07T09:16:00-04:00
-- tags: neodoc
-- title
Spoiler/Content-Warning Update
Part of the NeoDoc spec is a list of
section types that include reference
HTML templates and rendering expectations
for output.
Two new section types have been added
based on the discussion from
>> In Which A Book Lexicon is Born |
https://discourse.atmosphere.community/t/in-which-a-book-lexicon-is-born/1042 >>.
They are: Spoilers and Content Warnings.
There's also a new inline Spoiler tag.
The specific start/stop tokens are TBD,
but it'll be something like:
-- pre/
This is ;;a spoiler;; to
keep things a surprise.
-- /pre
-- h2
The NeoDoc Advantage
The Spoiler and Content Warning sections
are prime examples of NeoDoc's ability to
offer content portability to the Atmosphere.
Without NeoDoc (or something like it) the
ability to migrate content with spoilers
or warnings between apps is impractical
at best.
For example, assuming the use of Markdown,
the two ways that come to mind for
identifying spoiler and content-warning
content in plain-text storage are:
-- numbered/
1. Add custom Markdown tokens like:
-- pre/
\```cw Content Warning Label Goes Here
Everything in this section is
behind a content warning.
\```
\```spoiler
This is the content of a spoiler
section.
\```
And ;;this text;; is an inline
spoiler.
-- /pre
2. Define specific HTML tag/class
combinations and roll out to using them.
For example:
-- pre/
<section class="content-warning">
<div class="label">
Content Warning Label Goes Here
</div>
Everything in this section is
behind a content warning.
Markdown parsers should be able
to automatically transform these
blocks into paragraphs.
</section>
<section class="spoiler">
Everything in this section is
behind a spoiler interface.
Markdown parsers should be able
to automatically transform these
blocks into paragraphs.
</section>
Here is <span class="spoiler">some
spoiler text</span> that gets
hidden.
-- /pre
-- /numbered
In either case, every app that uses
the content must agree on the syntax/html
in order to maintain functionality.
That's a practical impossibility.
There's no realistic way to have portable
spoiler/content-warning content using
Markdown as a result. The same issue
arises with any other format that doesn't
have native spoiler or content-warning
types.
With the feature built in to NeoDoc,
apps don't have to invent or coordinate
on custom syntax. They simply use
what's already defined in the spec.
-- h2
Change Window
I've been using NeoDoc for three years
in my static site generator. No one else
has it yet. That provides a fantastic
opportunity to refine its capabilities
to further support the Atmosphere while
it's being extracted into its own library.
The spoiler/content-warning is a perfect
example. I hadn't thought of them
until the topic came up in the community.
What's nice about NeoDoc's format is
that no alterations to the parser are
necessary to accommodate the change. The
only modification is an update to the
spec to include the section types in the
pre-defined list and supply their
reference templates.
A critical point is that these type of
adjustments can only be made before NeoDoc
is actively in production. Once it is, it'll
be like a lexicon where stability of the
spec is a requirement. (Further enhancements
are still possible. They would just have
to be a matter of community convention
with the possibility of optional addendum
section type specs, but the parser
functionality won't change.)
-- h2
Outro
I'll end with my refrain:
Without portable content the full promise
of a decentralized internet can't be
achieved.
While you can move from one PDS to
another, you're content is still locked
into specific apps if no one else uses
the format its stored in. Handling
multiple formats is, of course, possible.
But, it would be better spending time
on features that enhance app experience
rather than building ETLs.
I believe moving content between apps
is more appealing to non-technical users
than being able to migrate their PDS.
While Markdown is portable, it's
incredibly limited. At the epoch of
the Atmosphere, we should aim for
better.
-a
-- endnote
Adding the inline spoiler tag __is__
a change to the parser. Those changes
are only possible before NeoDoc is
in production. Once the shorthand
tokens have been locked down no
new ones will be added since that
would break backwards compatibility.
-- metadata
-- created: 2026-08-07T07:53:00-04:00
-- published: 2026-08-07T10:16:00-04:00
-- tags: neodoc
I just put up the initial draft of the docs. It’s mostly stubs, but it includes all the features.
feedback is welcome.
I’m reviewing inline shorthands as part of the process of pulling NeoDoc’s parser out of my static site generator. I’m pretty sure I’m going to move underscores (which are emphasis/italics in markdown) to identify underlines.
Some folks will have Very Strong Opinions about that. I’m okay with it. I prefer to give priority to the long term over the way we’ve done things in the past and underscores provide a way better visual representation of an underline.
With that switch, the shorthand set looks like this:
``a span of code``
<<custom|let's you make your own types>>
;;this is emphasis italics;;
^^footnote^^
@@footnote return link@@
!!highlight aka mark!!
((raw html goes here))
++image_path|alt text++
>>link text|url>>
**strong aka bold**
~~strike through~~
__underline__
Other than the underscore thing, I’m open to suggestions for using different tokens or if another/different functionality should have a shorthand assigned.