<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>House of Nettles: #code</title>
  <id>https://nex-3.com/tag/code/</id>
  <link href="https://nex-3.com/tag/code/feed.xml" rel="self"/>
  <link href="https://nex-3.com/tag/code/" />
  <updated>2026-06-22T19:53:18Z</updated>
    <entry>
      <title>An interactive introduction to the terrific experience of rendering Arabic typography and its technical debt</title>
      <link href="https://lr0.org/blog/p/arabic/" rel="alternate"/>
      <id>https://lr0.org/blog/p/arabic/</id>
      <published>2026-06-22T19:53:18Z</published>
      <updated>2026-07-07T01:13:19Z</updated>
      <author><name>lr0</name></author><category term="really cool post about about all the complexities involved in Arabic fonts" label="really cool post about about all the complexities involved in Arabic fonts"/><category term="and this one dude in Cairo tirelessly working to address them all" label="and this one dude in Cairo tirelessly working to address them all"/><category term="language" label="language"/><category term="code" label="code"/><category term="repost" label="repost" /><content type="html">&lt;p&gt;The history deserves recording because most people outside the small world
of Arabic font engineering don&#39;t know it, and it is wonderful. Classical
Arabic typography, by which I mean the manuscript tradition that the early
printers of Istanbul and Bulaq spent their careers chasing, justifies a line
of text without stretching the spaces between words at all. Stretched spaces
are the Latin convention, and in Arabic they produce an effect the scribes
would have found simply ugly. Instead the scribe extends the letterforms
themselves along the baseline, using what is called &lt;em&gt;taṭwīl&lt;/em&gt; or, in the
modern technical vocabulary, &lt;em&gt;kashida&lt;/em&gt;: the connecting strokes between
certain pairs of letters can be lengthened, sometimes lavishly, to carry a
line out to the margin. A well-set page of Naskh from the seventeenth century
has every line flush at both margins, and the result is the dense, regular
weave that anyone who has spent time with a good manuscript Qurʾān will
recognise on sight.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[...]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The one great exception is Amiri, the Naskh face that Khaled Hosny, an
Egyptian doctor by training who taught himself OpenType tooling over the
course of about a decade, built and released under the SIL Open Font License
in 2011 and has polished continuously since. The name is the lineage: Amiri
revives the typeface of al-Maṭbaʿa al-Amīriyya, the Bulaq Press face that set
the 1924 Cairo Qurʾān, which means the best free Arabic font of the digital
era is a one-man reconstruction of the best government-funded font of the
metal era, and I never get tired of saying that sentence. And it is
engineered, not merely drawn. The required ligatures are done with care; the
1.0 rewrite, in 2022, reimplemented the &lt;em&gt;allāh&lt;/em&gt; ligature to be more
cautious about when it fires. The mark stacking holds up under fully vowelled
text. And since that rewrite the font carries a &lt;em&gt;curvilinear kashida&lt;/em&gt;:
feed it elongations and it substitutes graded, swelling curved strokes, in
four sizes, the way the pen would. Scroll back to the mockup card at the top
of the page; those curves are Amiri&#39;s own work, performed live in your
browser. If you are reading an Arabic text rendered well on the open web in
2026, there is a respectable chance you are reading Amiri. The rest of the
ecosystem (Scheherazade New from SIL International, Reem Kufi also by Hosny,
the various Noto Arabic faces Google commissioned) fills in around it.&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://lr0.org/blog/p/arabic/&#34; class=&#34;read-more&#34; title=&#34;Read More&#34;&gt;…&lt;/a&gt;&lt;/p&gt;

</content>
    </entry>
  
    <entry>
      <title></title>
      <link href="https://nex-3.com/blog/all-im-saying-is/" rel="alternate"/>
      <id>https://nex-3.com/blog/all-im-saying-is/</id>
      <published>2025-05-08T22:48:54Z</published>
      <updated>2025-05-08T22:48:54Z</updated>
      <author><name>Natalie Weizenbaum</name>
          <uri>https://nex-3.com/</uri></author><category term="code" label="code"/><content type="html">&lt;p&gt;All I&#39;m saying is that the first government to start funding grants for working
on the fun parts of software instead of betting on machine learning as the
be-all end-all is gonna have an incredible leg up on prestige and talent
acquisition when it comes to shaping the digital world over the next half
century. The USA&#39;s place as the center of software gravity isn&#39;t just eroding,
it&#39;s being purposefully gutted by short-sighted fools who think they can save
labor costs by farming out a medium that requires both creativity and precision
to machines that are fundamentally capable of neither. Jobs are scarce and
prestigious, fun jobs are scarcer. A huge orchard of talent is ripe for the
picking.&lt;/p&gt;
&lt;p&gt;And I don&#39;t just mean funding grants for open-source libraries or public-service
web infrastructure or things like that (although they should do that too). I
mean fully &lt;em&gt;arts&lt;/em&gt; grants, blank checks to create experimental digital media,
video games, demoscene demos, wacky hardware, video game mods. Fund the stuff
that engineers do in their &lt;em&gt;spare time&lt;/em&gt; as long as they do it on your soil and
make it available in your language. Build goodwill, build local networks of
skill and renown, and you&#39;ll have a lock on the whole culture as America
continues to collapse.&lt;/p&gt;
</content>
    </entry>
  
    <entry>
      <title></title>
      <link href="https://nex-3.com/blog/history-of-sass/" rel="alternate"/>
      <id>https://nex-3.com/blog/history-of-sass/</id>
      <published>2025-04-05T03:00:17Z</published>
      <updated>2025-04-09T00:33:58Z</updated>
      <author><name>Natalie Weizenbaum</name>
          <uri>https://nex-3.com/</uri></author><category term="ask" label="ask"/><category term="code" label="code"/><category term="sass" label="sass"/><content type="html"> &lt;blockquote class=&#34;h-entry u-in-reply-to&#34; style=&#34; padding: 0.75rem; margin: 1rem 0.2rem 1.15rem; border-radius: 0.5rem; box-shadow: 0px 4px 5px rgba(0, 0, 0, 0.14), 0px 1px 10px rgba(0, 0, 0, 0.12), 0px 2px 4px rgba(0, 0, 0, 0.2); &#34;&gt; &lt;p&gt; &lt;strong class=&#34;p-author h-card&#34;&gt;&lt;span class=&#34;p-name&#34;&gt;Lindsay Michael&lt;/span&gt;&lt;/strong&gt; asked: &lt;/p&gt; &lt;div class=&#34;e-content&#34;&gt;&lt;h1 class=&#34;p-name&#34;&gt;History of SASS&lt;/h1&gt; &lt;p&gt;I am a student writing a short paper about SASS and have run into a bit of a black hole when it comes to the development of the language. Beyond a few archived blog posts, I can&#39;t find a whole lot about the conceptualization or development of the language. Would you have any pointers toward that information? I&#39;m curious about how the idea for the preprocessor came up and how the development team came together.&lt;/p&gt;&lt;/div&gt; &lt;/blockquote&gt; 

&lt;p&gt;I guess there isn&#39;t much about this up anywhere particularly easy to find, is
there? Sure, let&#39;s get into the history.&lt;/p&gt;
&lt;h2 id=&#34;it-all-starts-with-haml&#34;&gt;It All Starts with Haml&lt;/h2&gt;
&lt;p&gt;So, before Sass (&lt;a href=&#34;https://sassnotsass.com/&#34;&gt;not SASS&lt;/a&gt;), there was
&lt;a href=&#34;https://haml.info/&#34;&gt;Haml&lt;/a&gt;. Haml was created way back in the summer of 2006 by
&lt;a href=&#34;https://en.wikipedia.org/wiki/Hampton_Lintorn-Catlin&#34;&gt;Hampton Lintorn-Catlin&lt;/a&gt;&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn1&#34; id=&#34;fnref1&#34;&gt;[1]&lt;/a&gt;&lt;/sup&gt;, when Ruby on Rails had lit the web
development world on fire and everyone was rushing to invent cool new ways of
writing server-side-rendered web applications with light &lt;a href=&#34;https://en.wikipedia.org/wiki/Ajax_(programming)&#34;&gt;AJAX&lt;/a&gt; support. Rails
used YAML for its configuration and Hampton liked the terseness and indentation,
so (as he once described to me) he took a template written in &lt;a href=&#34;https://en.wikipedia.org/wiki/ERuby&#34;&gt;ERB&lt;/a&gt; (the
dominant templating language at the time) and just deleted redundant characters
until he got something that felt more &lt;a href=&#34;https://en.wikipedia.org/wiki/Don%27t_repeat_yourself&#34;&gt;DRY&lt;/a&gt;. After some tweaks, the result
looked essentially like modern Haml:&lt;/p&gt;
&lt;pre class=&#34;language-haml&#34;&gt;&lt;code class=&#34;language-haml&#34;&gt;&lt;span class=&#34;token tag&#34;&gt;%section.container&lt;/span&gt;
  &lt;span class=&#34;token tag&#34;&gt;%h1&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;token code&#34;&gt; post&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;title&lt;/span&gt;
  &lt;span class=&#34;token tag&#34;&gt;%h2&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;token code&#34;&gt; post&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;subtitle&lt;/span&gt;
  &lt;span class=&#34;token tag&#34;&gt;.content&lt;/span&gt;
    &lt;span class=&#34;token punctuation&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;token code&#34;&gt; post&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;content&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That fall, just as Haml was released to the public, I was in college taking a
Software Design and Development course&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn2&#34; id=&#34;fnref2&#34;&gt;[2]&lt;/a&gt;&lt;/sup&gt; in which the instructor encouraged us
to get involved with open source projects. Rails being the big thing at the
time, I hung out on the mailing list&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn3&#34; id=&#34;fnref3&#34;&gt;[3]&lt;/a&gt;&lt;/sup&gt; looking for good opportunities to dip
my toes in. When Haml got announced, it was a perfect opportunity: it was still
small and easy to understand, and it had a number of clear tasks that needed
doing. I started sending patches, and pretty quickly (at least in part by virtue
of having a lot more free time between classes than Hampton did with a full-time
job), I became the &lt;em&gt;de facto&lt;/em&gt; lead developer.&lt;/p&gt;
&lt;h2 id=&#34;sass-emerges&#34;&gt;Sass Emerges&lt;/h2&gt;
&lt;p&gt;Haml quickly becomes quite popular in the Rails world. Writing HTML closing tags
by hand kinda sucks, it turns out, and we&#39;re not the last to try to solve this
in various ways (although we may have been the first). Hampton is a big ideas
guy, and he&#39;s always excited to find another big thing to dig into. By this
point we&#39;re working together pretty closely, so at some point in late 2006 he
messages me about his idea for &#34;Haml for CSS&#34;, which he wants to call &#34;Sass&#34;.&lt;/p&gt;
&lt;p&gt;That was the original pitch Hampton sold to me: just like Haml was basically
just a different syntax for HTML (or more accurately, for ERB, since it did
include the ability to inject Ruby code), Sass was going to be just a different
syntax for CSS. The first draft didn&#39;t even have variables, although by the time
it was actually released&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn4&#34; id=&#34;fnref4&#34;&gt;[4]&lt;/a&gt;&lt;/sup&gt; we had added them (at the time called
&#34;constants&#34;&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn5&#34; id=&#34;fnref5&#34;&gt;[5]&lt;/a&gt;&lt;/sup&gt;). Hampton drafted some examples of how the language
would look and wrote &lt;a href=&#34;https://github.com/sass/ruby-sass/commit/fa5048ba405619273e474a50400c7243fbff54fe&#34;&gt;a quick prototype&lt;/a&gt;, which I ended up &lt;a href=&#34;https://github.com/sass/ruby-sass/commit/015a1b191d06cf418b519e33d98f86970e0512ac&#34;&gt;totally refactoring&lt;/a&gt;
shortly thereafter. As for Haml, I did most of the coding work for Sass.&lt;/p&gt;
&lt;p&gt;It also looked dramatically different than the indented syntax does today:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;!color = #fff

body
  :margin 0
  :font 0.85em &#34;Lucida Grande&#34;, &#34;Trebuchet MS&#34;, Verdana, sans-serif
  :color = !color
  :background url(/images/global_bg.gif)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Initially, we were a lot less concerned with making the syntax look at all like
CSS than we were with making it feel like Haml. Haml distinguished each syntax a
line could have using its initial character, so we used &lt;code&gt;:&lt;/code&gt; as the initial
character for properties in Sass. Haml used &lt;code&gt;=&lt;/code&gt; to indicate that the contents of
a tag should come from a Ruby expression, so Sass used &lt;code&gt;=&lt;/code&gt; to indicate that it
should come from a Sass expression and didn&#39;t parse it at all otherwise.&lt;/p&gt;
&lt;p&gt;Looking back, a lot of these design choices seem quaint (perhaps even
wrongheaded) in retrospect. But there was already an idea here that would become
critical to the entire concept of &#34;preprocessors&#34; and what Sass would eventually
become: &lt;em&gt;there was no Ruby code in the stylesheets at all&lt;/em&gt;. We knew from the
beginning that we wanted to support user-defined constants&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn6&#34; id=&#34;fnref6&#34;&gt;[6]&lt;/a&gt;&lt;/sup&gt;, but rather than
just having people assign Ruby variables and inject Ruby code, we knew from the
beginning we wanted a syntax that was specific to Sass.&lt;/p&gt;
&lt;h2 id=&#34;the-rails-mindset&#34;&gt;The Rails Mindset&lt;/h2&gt;
&lt;p&gt;To understand where we were coming from, we have to go back again to Haml and
the context it emerged in. The early Rails world was hard to describe in a
modern context, because the web development ecosystem it existed in was orders
of magnitude smaller. Rails in 2006 had vastly fewer users in an absolute sense
than React does today, or even something smaller like Vue.js. But it had &lt;em&gt;all&lt;/em&gt;
the mindshare. Everyone who was at all interested in the cutting edge of web
technology was either using Rails or building another framework that was a
reaction to Rails.&lt;/p&gt;
&lt;p&gt;And this wasn&#39;t just because Rails had good PR (although without a doubt that
contributed). Rails was the first really popular open-source existence proof
that web development could be simultaneously &lt;em&gt;architecturally-sound software
development&lt;/em&gt;, unlike tools like PHP or Perl which at the time were tightly
coupled to the &lt;a href=&#34;https://en.wikipedia.org/wiki/Common_Gateway_Interface&#34;&gt;CGI&lt;/a&gt; mode of page-by-page rendering; and also &lt;em&gt;lightweight and
developer-oriented&lt;/em&gt;, unlike tools like &lt;a href=&#34;http://ASP.NET&#34;&gt;ASP.NET&lt;/a&gt; or whatever Java people were
doing at the time. It made people sit up and take web development seriously, and
led to a huge boom in thought and discussions and articles&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn8&#34; id=&#34;fnref8&#34;&gt;[8]&lt;/a&gt;&lt;/sup&gt; about how best to
structure these applications.&lt;/p&gt;
&lt;p&gt;Haml was heavily influenced by these discussions. In particular, it took the
idea of &#34;thin views&#34; very seriously. Rails followed a Model/View/Controller
architecture, where the template was framed as a &#34;view&#34; of the underlying data.
It was only supposed to be responsible for displaying the data, not manipulating
it or even really getting it into a form that was easy to display. To that end,
Hampton intentionally made it annoying to write complex logic in Haml. For the
first few releases, Haml didn&#39;t even have a way of writing Ruby statements that
didn&#39;t emit values to HTML specifically to encourage people to put all that
logic in the model or controller instead.&lt;/p&gt;
&lt;p&gt;So when we were designing Sass, making sure it wasn&#39;t too powerful in the wrong
ways was at the top of our minds. We didn&#39;t want people just dumping a bunch of
code in their stylesheets, because if views should only express the translation
from a code object into a document structure, then stylesheets should only
express styles. So when we decided to add constants, we chose to invent our own
little expression language that was particularly suited to the needs of CSS
rather than just embedding Ruby expressions and calling it a day. This had its
own practical benefits as well: it allowed us to add first-class support for CSS
types that didn&#39;t have literal Ruby equivalents, like dimensions (&lt;code&gt;10px&lt;/code&gt;,
&lt;code&gt;50%&lt;/code&gt;), colors, and unquoted strings.&lt;/p&gt;
&lt;h2 id=&#34;the-preprocessor-is-born&#34;&gt;The Preprocessor is Born&lt;/h2&gt;
&lt;p&gt;I think this was the key insight that caused Sass to create the class of &lt;em&gt;CSS
preprocessor&lt;/em&gt; rather than just being a template system. CSS template systems had
existed before this, at least to the extent that people were running CSS through
ERB (and surely also PHP and so on). But no one writing those was thinking much
about how their language design would feed back into the quality and
maintainability of stylesheets written in that language. Sass was, even if at
the time it was awkward and not fully fleshed-out.&lt;/p&gt;
&lt;p&gt;And even as limited as it was, people got really excited about it! It&#39;s hard to
overstate how valuable constants in CSS were alone, and the core Haml fanbase
liked having an indented way to write it. We spent the next year largely just
making iterative improvements—adding features like comments, &lt;code&gt;@import&lt;/code&gt;&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn9&#34; id=&#34;fnref9&#34;&gt;[9]&lt;/a&gt;&lt;/sup&gt;,
support for @-rules, and just generally tightening up various corners of the
language.&lt;/p&gt;
&lt;p&gt;I was still the primary developer of the language, and most of the design
direction was coming from Hampton and me talking to one another&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn10&#34; id=&#34;fnref10&#34;&gt;[10]&lt;/a&gt;&lt;/sup&gt;. I was still
in college, I had only learned to program at all a few years prior, and I was
having the time of my life writing code that actual people out in the world were
not just using but enjoying. I was majoring in computer science, but my actual
classwork didn&#39;t involve much code, and I&#39;ve always just really &lt;em&gt;liked&lt;/em&gt; the
process of writing it and the feeling of contributing something to the world.&lt;/p&gt;
&lt;p&gt;Through all this time, we were almost exclusively interacting over the internet.
Hampton was at the time living in Toronto; I was (and still am) in Seattle. His
company, the now-defunct Unspace Interactive, did fly me out to a few
conferences over the years where we were able to spend time together in person,
but those were mostly &lt;em&gt;not&lt;/em&gt; heavily technical discussions. We collaborated over
instant messenger (probably Google Chat at the time?), email, and issue
trackers.&lt;/p&gt;
&lt;p&gt;An important aside: in retrospect, this whole situation was more than slightly
exploitative. I was writing (and continue to write!) code that was being used by
corporations to make a profit without seeing any remuneration, either
commensurate to that profit or to my labor. This certainly wasn&#39;t Hampton&#39;s
fault, or his company&#39;s—it&#39;s the unfortunate nature of open source in a
capitalist world. I&#39;m still proud of the work I did, and I don&#39;t regret doing
it, but I think it&#39;s worth mentioning that I can&#39;t wholeheartedly endorse that
people take the same path of doing a lot of labor for no compensation. I was
very lucky to have the stability to spend so much time and energy on this &lt;em&gt;and&lt;/em&gt;
to work on a project and at a time when that would lead to a lot of future
career opportunities..&lt;/p&gt;
&lt;h2 id=&#34;the-next-level&#34;&gt;The next level&lt;/h2&gt;
&lt;p&gt;Anyway! I wasn&#39;t the only person working on Sass at the time. In addition to
Hampton&#39;s occasional code contributions, we were getting a &lt;em&gt;lot&lt;/em&gt; of patches from
users. Before GitHub existed&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn11&#34; id=&#34;fnref11&#34;&gt;[11]&lt;/a&gt;&lt;/sup&gt;, Hampton ran an issue-tracking tool called
&lt;a href=&#34;https://trac.edgewall.org/&#34;&gt;Trac&lt;/a&gt; that allowed people to upload patch files that we&#39;d then land in the
&lt;a href=&#34;https://subversion.apache.org/&#34;&gt;Subversion&lt;/a&gt; project. It was not great! GitHub has done some nasty stuff in the
years since&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn12&#34; id=&#34;fnref12&#34;&gt;[12]&lt;/a&gt;&lt;/sup&gt;, and the long-term effects of centralizing open source
developments in a single corporation&#39;s hands are not great, but at the time it
felt like a breath of fresh air coming from within our community.&lt;/p&gt;
&lt;p&gt;One such contribution was from one Garry Hill&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn13&#34; id=&#34;fnref13&#34;&gt;[13]&lt;/a&gt;&lt;/sup&gt;, and would go on to shape the
future of the language: &lt;a href=&#34;https://github.com/sass/ruby-sass/commit/917bd658c5e9f6c8e2d3e8e7e7cdab45919b3856&#34;&gt;the addition of mixins&lt;/a&gt; in April 2008. Although mixins
were very limited initially—they didn&#39;t even have parameters in their first
release!—they represented a broader level of abstraction than had been possible
before in stylesheets at all. While Haml was still just another syntax for HTML,
mixins cemented the idea that Sass was in a totally different tier of
expressiveness relative to vanilla CSS, and they opened the door for a cascade
of iterative improvements that would shape Sass into what it is now.&lt;/p&gt;
&lt;p&gt;In June 2008, we added the first built-in Sass function, &lt;code&gt;hsl()&lt;/code&gt;. In August, we
added mixin parameters, booleans, &lt;code&gt;@if&lt;/code&gt;, &lt;code&gt;@for&lt;/code&gt;, &lt;code&gt;@while&lt;/code&gt;. In October, we
started allowing &#34;constants&#34; to be reassigned (and, correspondingly, started
calling them &#34;variables&#34; instead). All of these made Sass less of just an
alternative stylesheet syntax and more of a language in its own right. Although
it would take another two years to add &lt;code&gt;@function&lt;/code&gt;, we were already tossing
around the idea.&lt;/p&gt;
&lt;h2 id=&#34;the-scss-era&#34;&gt;The SCSS era&lt;/h2&gt;
&lt;p&gt;Concurrently, there were a couple important things brewing. I had begun working
closely with &lt;a href=&#34;https://github.com/chriseppstein&#34;&gt;Chris Eppstein&lt;/a&gt;, who had created &lt;a href=&#34;https://github.com/Compass/compass&#34;&gt;Compass&lt;/a&gt;&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn14&#34; id=&#34;fnref14&#34;&gt;[14]&lt;/a&gt;&lt;/sup&gt;. He started
submitting a number of pull requests to Sass, and we pretty quickly decided to
bring him on as a core team member. By this point Hampton was mostly focused on
other projects, so Chris and I made most of the major design decisions together
for the next few years.&lt;/p&gt;
&lt;p&gt;Several of those decisions were strongly influenced by our first real
competitor: &lt;a href=&#34;https://lesscss.org/&#34;&gt;Less&lt;/a&gt;, first released in May 2009. At the time also written in
Ruby, Less was clearly heavily inspired by Sass, but advertised one&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn16&#34; id=&#34;fnref16&#34;&gt;[16]&lt;/a&gt;&lt;/sup&gt; key
distinguishing feature: it claimed to be&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn17&#34; id=&#34;fnref17&#34;&gt;[17]&lt;/a&gt;&lt;/sup&gt; a superset of CSS. It quickly
boomed in popularity, and was even threatening to displace Sass as the most
popular preprocessor. We took this as a clear sign that the desire for the power
of a preprocessor had far outstripped the desire for a different syntax for CSS,
and we set about designing and building the SCSS syntax, which would go on to
release with Ruby Sass 3.0.0 a year later in May 2010.&lt;/p&gt;
&lt;p&gt;The addition of SCSS led to a number of additional changes to the way we thought
about the design of the syntax. We were committed to being as close to a
superset of CSS as possible&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn18&#34; id=&#34;fnref18&#34;&gt;[18]&lt;/a&gt;&lt;/sup&gt;, and in pursuit of that we wanted to make the
new syntax feel more &#34;CSS-y&#34;. We&#39;d already changed the indented declaration
syntax to allow &lt;code&gt;color: blue&lt;/code&gt; rather than &lt;code&gt;:color blue&lt;/code&gt;, but with SCSS we
decided to remove the distinction between &#34;script&#34; values (written &lt;code&gt;property = expression&lt;/code&gt;) and &#34;literal&#34; values (written &lt;code&gt;property: expression&lt;/code&gt;). This in turn
committed us to being able to parse all expression-level CSS as SassScript,
which led to a cascade of other small changes.&lt;/p&gt;
&lt;p&gt;We also became much more concerned with avoiding forwards-incompatibilies with
new CSS syntax that could theoretically be added in the future. We changed the
variable character from &lt;code&gt;!&lt;/code&gt; to &lt;code&gt;$&lt;/code&gt; to avoid conflicting with the existing CSS
&lt;code&gt;!important&lt;/code&gt; syntax, replaced the &lt;code&gt;||=&lt;/code&gt; assignment operator with &lt;code&gt;!default&lt;/code&gt;,
introduced &lt;code&gt;@mixin&lt;/code&gt; and &lt;code&gt;@include&lt;/code&gt;&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn19&#34; id=&#34;fnref19&#34;&gt;[19]&lt;/a&gt;&lt;/sup&gt;, and expanded the scope of what could be
interpolated. Sass 3.0.0 was really the first modern-looking release of the
language. It laid a lot of groundwork for the future, and also made a lot of
decisions that I would eventually spend a bunch of time undoing.&lt;/p&gt;
&lt;h2 id=&#34;road-to-dart-sass&#34;&gt;Road to Dart Sass&lt;/h2&gt;
&lt;p&gt;Over the next few years, development slowed on Ruby Sass. I had graduated
college and started programming full-time, which substantially diminished the
amount of time and energy I had for programming projects that weren&#39;t my day
job. Hampton was busy with Wikimedia, and most of Chris&#39;s spare programming time
was wrapped up in Compass. We certainly made progress, gradually introducing
many of the major features that still exist today like lists, maps, user-defined
functions, more advanced mixins, and on and on.&lt;/p&gt;
&lt;p&gt;In 2012, driven by the waning popularity of Ruby in the face of the rise of
Node.js, Hampton—then working at Moovweb—launched a project to create a more
widely-usable Sass implementation written in C++. This would become &lt;a href=&#34;https://sass-lang.com/libsass/&#34;&gt;LibSass&lt;/a&gt;,
which was initially written largely by Hampton&#39;s Moovweb colleague &lt;a href=&#34;https://github.com/akhleung&#34;&gt;Aaron Leung&lt;/a&gt;
before eventually being maintained by &lt;a href=&#34;https://github.com/xzyfer&#34;&gt;Michael Mifsud&lt;/a&gt; and &lt;a href=&#34;https://github.com/mgreter&#34;&gt;Marcel Greter&lt;/a&gt;. I
can&#39;t give a tremendous amount of detail on the internal development process
here, because I never worked on it myself, but I can talk about how it was used.&lt;/p&gt;
&lt;p&gt;LibSass was quickly adopted by the Node.js community through the &lt;a href=&#34;http://npmjs.com/package/node-sass&#34;&gt;&lt;code&gt;node-sass&lt;/code&gt;&lt;/a&gt;
wrapper package. This turned out to be a bit of a double-edged sword for Sass as
a language: on the one hand, &lt;code&gt;node-sass&lt;/code&gt; was vastly faster and easier to get up
and running (even given the headaches of building a C++ Node.js plugin&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn20&#34; id=&#34;fnref20&#34;&gt;[20]&lt;/a&gt;&lt;/sup&gt;)
than Ruby Sass, which was doubtlessly crucial for the continued popularity of
Sass as the web development center of gravity shifted away from Ruby and towards
Node in the early 2010s; on the other hand, poor communication between the Sass
core team and the LibSass maintainers led to it being essentially a black-box
reimplementation whose internal diverged &lt;em&gt;massively&lt;/em&gt; from Ruby Sass, which ended
up making LibSass fairly buggy, largely incompatible, and increasingly difficult
to add new features to.&lt;/p&gt;
&lt;p&gt;It was clear that something needed to change. By the middle of the decade, Ruby
was clearly not meeting our needs anymore, so we sat down and tried to figure
out what came next. We considered a number of possibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Leaning into LibSass and declaring it the official implementation moving
forward. Although this had the obvious benefit of an existing implementation,
the reality was that we&#39;d probably need to rewrite the whole thing from the
ground up anyway.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using Rust, which was at the time still quite young. I did do a bit of work to
prototype this, and came to the conclusion that the recursive object structure
of ASTs didn&#39;t play nicely at all with Rust&#39;s memory management schema. It
would also likely force us to write our own garbage collector for Sass objects
rather than relying on the native language&#39;s, adding a lot of complexity in
exchange for native-code speeds we weren&#39;t sure we even needed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JavaScript, which had the sizable benefit of being the new &lt;em&gt;lingua franca&lt;/em&gt; of
the web (and being much more likely to hold that position than Ruby thanks to
its monopoly on the browser). The biggest drawback here was that, while the V8
JS engine was substantially faster than Ruby, we weren&#39;t sure we could get the
performance we wanted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dart, which we ended up settling on. Despite being quite obscure at the time,
Dart had a number of advantages: it had its own VM that could run code close
to native speed, it was easy to distribute cross-platform Dart executables,
and it could compile to JS for even easier distribution and a high level of
pluggability. I was also working on the Dart team at the time, so I could much
more easily justify using some of my work hours on writing a new
implementation of Sass than I could for any other language.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I spent 2016 and 2017 working on Dart Sass, using all the lessons I&#39;d learned
from Ruby Sass to improve the structure of the code and using the substantial
corpus of test cases that Chris and the LibSass team had built up to verify its
behavior. In March 2018, we released Dart Sass 1.0.0, and in April we
&lt;a href=&#34;https://sass-lang.com/blog/ruby-sass-is-deprecated/&#34;&gt;deprecated Ruby Sass&lt;/a&gt;. In October 2020, &lt;a href=&#34;https://sass-lang.com/blog/libsass-is-deprecated/&#34;&gt;LibSass followed suit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In 2019, I had the opportunity to start a dedicated CSS/Sass infrastructure team
at Google, which has included &lt;a href=&#34;http://github.com/jathak&#34;&gt;Jennifer Thakar&lt;/a&gt;, &lt;a href=&#34;https://github.com/awjin&#34;&gt;Awjin Ahn&lt;/a&gt; (who has since
moved on to Peregrine), &lt;a href=&#34;https://github.com/goodwine&#34;&gt;Carlos &#34;Goodwine&#34;&lt;/a&gt;, and &lt;a href=&#34;https://github.com/pamelalozano16&#34;&gt;Pamela Lozano&lt;/a&gt;, all of whom
have made numerous contributions to Sass (Jen in particular is responsible for
the migrator tool). Beyond that point, the history is too recent for me to put
in context effectively, but hopefully it will be easier to find information from
the last few years.&lt;/p&gt;
&lt;p&gt;I&#39;m sure this is a bit more information than you bargained for, but as I was
writing this post I realized that a lot of this information has never been
written down in any kind of unified way before, so I appreciate you giving me
the impetus to do so.&lt;/p&gt;
&lt;hr class=&#34;footnotes-sep&#34;&gt;
&lt;section class=&#34;footnotes&#34;&gt;
&lt;ol class=&#34;footnotes-list&#34;&gt;
&lt;li id=&#34;fn1&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Did Hampton call it &#34;Haml&#34; because it sounded kind of like his name
combined with &#34;HTML&#34;, and then come up with an acronym after the fact?
Absolutely yes. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref1&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn2&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;This course was taught by &lt;a href=&#34;https://en.wikipedia.org/wiki/Gayle_Laakmann_McDowell&#34;&gt;Gayle Laakman McDowell&lt;/a&gt; when she was still at
Google, a few years before she ended up hitting it big writing interview
and career advice books. I haven&#39;t actually read any of those books, but
her class was fantastic. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref2&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn3&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Back then, instead of Discord servers or subreddits, open source projects
had email lists. They might have had IRC channels too, but those were
really just for support; any discussions or announcements happened over
email lists because they could be easily archived and searched and didn&#39;t
require any particular kind of account. If you&#39;re thinking &#34;but Discord
doesn&#39;t solve any of those problems either&#34;, you&#39;re right! &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref3&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn4&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;For a long time, Sass was actually distributed as part of the Haml
RubyGem, until the release of Sass 3.3.0 in 2014 on its own. This was
initially a naked attempt on our part to promote our new language by
piggybacking on the initial popularity of Haml, although ironically Sass
quickly overshadowed its older sibling. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref4&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn5&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;After reading this over, Hampton reminded me that we originally
came to the name &#34;constants&#34; in part because we wanted to emphasize that
(unlike a template language like Haml) they weren&#39;t connected to Ruby
variables and didn&#39;t change based on serve-time state. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref5&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn6&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;CSS custom properties didn&#39;t exist yet&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn7&#34; id=&#34;fnref7&#34;&gt;[7]&lt;/a&gt;&lt;/sup&gt;, and the absence of a way to
abstract out and name repeated values was keenly felt by anyone writing
CSS to any more than a cursory extent &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref6&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn7&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;They didn&#39;t exist yet because they were largely inspired by Sass,
something I will go to my grave extremely proud of. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref7&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn8&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Rails&#39; ascent coincided with the apex of blogging culture, which
contributed to this intellectual atmosphere as well. There were a handful
of people who could regularly write essays about web development that
would then be read by essentially everyone influential. In a kind of sad
poetry, the Rails community itself contained the seeds of the downfall of
this culture: Twitter was created that same year in the Rails shop Odeo,
and went on to be the tentpole for the social media culture that
obliterated the ubiquity of personal blogs. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref8&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn9&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;One of my deepest regrets is how messy we made the semantics of &lt;code&gt;@import&lt;/code&gt;
initially. This was the downside of coming from a Ruby context—we
essentially copied Ruby&#39;s &lt;code&gt;require&lt;/code&gt; system, which did little more than
evaluate a file in the global scope. We didn&#39;t even think to copy the part
where it wouldn&#39;t load the same file twice. I&#39;m &lt;em&gt;still&lt;/em&gt; paying down the
technical debt from that nearly-20-year-old design decision. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref9&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn10&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;At times I may not have kept him as looped-in as I ought to have. Sorry,
Hampton! &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref10&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn11&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Sass actually migrated from Hampton&#39;s self-hosted SVN repository onto
GitHub during this time period. We were one of the earliest projects to do
so, even in the Ruby world that made up most of GitHub&#39;s early adopters.
&lt;a href=&#34;https://api.github.com/users/nex3&#34;&gt;My GitHub user ID&lt;/a&gt; is 188; &lt;a href=&#34;https://api.github.com/users/hamptonmakes&#34;&gt;Hampton&#39;s&lt;/a&gt; is 111. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref11&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn12&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Defense contracting and nonconsensualy training large language models on
their users&#39; code being the two that stick out most in my mind, although
the cofounder [getting ousted for sexual harassment] is also pretty
damning. Fun fact: the &#34;TOML&#34; format that Rust uses for its config files
is not only named after this guy, he&#39;s still involved with its
development! Gross! &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref12&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn13&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;There are a few &#34;Garry Hill&#34;s currently working in tech who I can find on
the internet, but I can&#39;t definitively identify any of them as the person
who submitted this change. He showed up, added mixins, and left without a
trace. Garry, if you see this, let me know what you&#39;re up to these days! &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref13&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn14&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Compass is defunct now, but it was the first framework written for Sass.
It started out as a port of Blueprint after Chris failed to convince the
team to use Sass natively&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fn15&#34; id=&#34;fnref15&#34;&gt;[15]&lt;/a&gt;&lt;/sup&gt;, but it eventually grew to be a broader
framework with flexible tools for layout and browser compatibility. It
eventually faded from relevance along with Ruby, and especially because
browsers&#39; native support for layout and tools like autoprefixer rendered
most of its functionality outmoded. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref14&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn15&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;They ended up reversing their course on this later on, of course. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref15&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn16&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;There was actually another feature that was also frequently cited by
users as a benefit: in Less you could use any style rule whose selector
was just a CSS class as a mixin, rather than declaring mixins using a
different syntax. We considered this an anti-feature, both because it
treated class names as a uniquely special type of selector, and because
the lack of separation between style rules intended as mixins and style
rules intended as styles made it inherently risky for stylesheet
libraries to change &lt;em&gt;any&lt;/em&gt; styles without potentially breaking people
using it in ways they hadn&#39;t intended. We instead took a different
approach to the goal of &#34;re-using existing style rules&#34; by creating &lt;a href=&#34;https://sass-lang.com/documentation/at-rules/extend/&#34;&gt;the
&lt;code&gt;@extend&lt;/code&gt; rule&lt;/a&gt;. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref16&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn17&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;The early versions of Less were more than a little haphazard in their
support of the CSS spec. I would eventually dig pretty deeply through its
implementation in the process of making a Less-to-SCSS transpiler, and I
found plenty of places where it would fail to parse valid CSS correctly,
or even just choke on it. I&#39;ll admit that it irked me how popular it was
despite this, given how much time we&#39;d put into aligning Sass with the
CSS spec at that point. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref17&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn18&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;There are still a few edge cases where technically valid, meaningful CSS
is interpreted differently by Sass. We&#39;re working on removing &lt;code&gt;@import&lt;/code&gt;
and the use of &lt;code&gt;/&lt;/code&gt; as division outside &lt;code&gt;calc()&lt;/code&gt;, but the last case—Sass
interpolation syntax in custom property values—will for better or worse
always prevent us from being a &lt;em&gt;true&lt;/em&gt; superset. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref18&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn19&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Previously in the indented syntax, mixins were declared with &lt;code&gt;=&lt;/code&gt; and
included with &lt;code&gt;+&lt;/code&gt;, following the Haml style of syntax being determined by
the first character on a line. You can [still use single characters in
the indented syntax], although these days I find them needlessly
line-noisey. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref19&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn20&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;Inexplicably, this process &lt;em&gt;still&lt;/em&gt; uses a tool &lt;a href=&#34;https://github.com/nodejs/node-gyp&#34;&gt;named after a racial
slur&lt;/a&gt;. This industry can be a nightmare sometimes. &lt;a href=&#34;https://nex-3.com/blog/history-of-sass/#fnref20&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
  
    <entry>
      <title>How to fail to read a Fediverse post</title>
      <link href="https://nex-3.com/blog/so-im-trying-to-add-support/" rel="alternate"/>
      <id>https://nex-3.com/blog/so-im-trying-to-add-support/</id>
      <published>2024-10-28T00:36:43Z</published>
      <updated>2024-10-28T00:51:18Z</updated>
      <author><name>Natalie Weizenbaum</name>
          <uri>https://nex-3.com/</uri></author><category term="meta" label="meta"/><category term="code" label="code"/><category term="mastodon" label="mastodon"/><content type="html">&lt;p&gt;So I&#39;m trying to add support for automatically embedding Fediverse posts on this
blog, right? And yeah I could use the Mastodon API for it, but I&#39;d really rather
be able to make it work with &lt;em&gt;anything&lt;/em&gt; that speaks ActivityPub. So okay, I look
up &lt;a href=&#34;https://www.w3.org/TR/activitypub/&#34;&gt;the ActivityPub spec&lt;/a&gt;. It&#39;s a bit confusing, but I figure out how to at make
a GET request for an ActivityPub resource: just add &lt;code&gt;Content-Type: application/ld+json; profile=&amp;quot;https://www.w3.org/ns/activitystreams&amp;quot;&lt;/code&gt;. I can
even make a request for one of my statuses and it works! Fantastic!&lt;/p&gt;
&lt;p&gt;Just to verify, I make a request to another server, and that&#39;s where things
start getting hairy. Instead of a nice JSON representation of the post, I get
back a 401 Unauthorized with a body that says &amp;quot;Request not signed&amp;quot;. This is a
public post, but after some digging it turns out Mastodon (and by extension
ActivityPub as a whole) has a &lt;a href=&#34;https://docs.joinmastodon.org/spec/security/#http&#34;&gt;&amp;quot;secure mode&amp;quot;&lt;/a&gt; where &lt;em&gt;all&lt;/em&gt; requests have to be
signed.&lt;/p&gt;
&lt;p&gt;Signed by what though? This is a distributed system—there&#39;s no central authority
to distribute authorization in the first place.&lt;/p&gt;
&lt;p&gt;To answer that I looked in the spec. I searched for &amp;quot;signature&amp;quot; and found
nothing particularly relevant. Eventually I found the &lt;a href=&#34;https://www.w3.org/TR/activitypub/#authorization&#34;&gt;Authentication and
Authorization&lt;/a&gt; section, which says &amp;quot;Unfortunately at the time of
standardization, there are no strongly agreed upon mechanisms for
authentication.&amp;quot; Well, shit. Clearly &lt;em&gt;some people&lt;/em&gt; agree enough for it to be
implemented, but I guess not enough for it to be actually specified!&lt;/p&gt;
&lt;p&gt;This does, mercifully, link to &lt;a href=&#34;https://www.w3.org/wiki/ActivityPub/Primer/Authentication_Authorization&#34;&gt;a wiki page&lt;/a&gt; that purports to lay out &amp;quot;some
possible directions&amp;quot; and, under the &lt;a href=&#34;https://www.w3.org/wiki/ActivityPub/Primer/Authentication_Authorization#Server_to_Server&#34;&gt;Server to Server&lt;/a&gt; section, seems to
describe the scheme that &lt;a href=&#34;https://stackoverflow.com/questions/75025657/activitypub-mastodon-how-to-get-an-actor#answer-76396982&#34;&gt;this StackOverflow post&lt;/a&gt; describes as &amp;quot;an odd,
somewhat well-known ActivityPub quirk&amp;quot;&lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;https://nex-3.com/blog/so-im-trying-to-add-support/#fn1&#34; id=&#34;fnref1&#34;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. This wiki page may not be an official
specification, but at the very least it describes the &lt;code&gt;publicKey&lt;/code&gt; field that I
can see in the actor JSON on Mastodon.social.&lt;/p&gt;
&lt;p&gt;This is all fundamentally busywork. Because the whole thing is decentralized,
the receiving instance has no choice but to trust whatever public key a new
requesting instance provides. All this scheme really does is prove that
someone making requests runs a server somewhere that speaks basic ActivityPub,
and even then this constraint only exists for ActivityPub requests—HTTP
requires no authentication at all.&lt;/p&gt;
&lt;pre class=&#34;language-json&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;&lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;id&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;https://mastodon.social/users/nex3&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;type&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;Person&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;token comment&#34;&gt;/* ... */&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;publicKey&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;token property&#34;&gt;&#34;id&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;https://mastodon.social/users/nex3#main-key&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;token property&#34;&gt;&#34;owner&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;https://mastodon.social/users/nex3&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;token property&#34;&gt;&#34;publicKeyPem&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n&#34;&lt;/span&gt;
  &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or does it? The &lt;code&gt;publicKey&lt;/code&gt; link there points to
&lt;a href=&#34;https://web-payments.org/vocabs/security#publicKey&#34;&gt;https://web-payments.org/vocabs/security#publicKey&lt;/a&gt;, a URL that at time of
writing is refusing HTTPS connections entirely. Naturally I looked it up on
&lt;a href=&#34;http://archive.org&#34;&gt;archive.org&lt;/a&gt;, only to find that &lt;a href=&#34;https://web.archive.org/web/20221218063101/https://web-payments.org/vocabs/security#publicKey&#34;&gt;the specification for the &lt;code&gt;publicKey&lt;/code&gt; field&lt;/a&gt; is
not only totally different from what I&#39;m observing in the wild, its one-sentence
specification is essentially useless: &amp;quot;A public key property is used to specify
a URL that contains information about a public key.&amp;quot; The example included
&lt;em&gt;doesn&#39;t even have a &lt;code&gt;publicKey&lt;/code&gt; field&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;language-json&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;&lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;@context&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;https://w3id.org/security/v1&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;@id&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;https://payswarm.example.com/i/bob/keys/1&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;@type&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;Key&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;owner&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;https://payswarm.example.com/i/bob&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;token property&#34;&gt;&#34;publicKeyPem&#34;&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;-----BEGIN PRIVATE KEY-----\nMIIBG0BA...OClDQAB\n-----END PRIVATE KEY-----\n&#34;&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay, so there&#39;s functionally no specification for the data format. That&#39;s fine,
I can probably reverse-engineer it from the live example in combination with the
spec for how to make authenticated requests. A spec which is &lt;a href=&#34;https://tools.ietf.org/html/draft-cavage-http-signatures-08&#34;&gt;handily linked&lt;/a&gt;
from that same wiki page. But nothing can be easy: that link has a prominent
sidebar which reads &amp;quot;This is an older version of an Internet-Draft whose latest
revision state is &#39;Replaced&#39;.&amp;quot;&lt;/p&gt;
&lt;p&gt;So is the ActivityPub authorization &amp;quot;specification&amp;quot; &lt;em&gt;intentionally&lt;/em&gt; using an
outdated version of HTTP signatures, or should I use the latest version instead?
The wiki page doesn&#39;t say, so I just have to guess. Presumably there are plenty
of implementations out there that use the version that was (I&#39;m assuming?)
current at the time the spec was written, so I&#39;ll start with that. It describes
how to link back to the actor&#39;s public key (although &lt;em&gt;not&lt;/em&gt; what format that key
should be in), which headers to sign, and how to create a signature given a
choice of algorithm.&lt;/p&gt;
&lt;p&gt;On the subject of algorithms, it says &amp;quot;Valid values for this parameter can be
found in the Signature Algorithms registry located at
&lt;a href=&#34;http://www.iana.org/assignments/signature-algorithms&#34;&gt;http://www.iana.org/assignments/signature-algorithms&lt;/a&gt; and MUST NOT be marked
&amp;quot;deprecated&amp;quot;.&amp;quot; An astute observer will note that that link is completely dead.
In fact, even the Internet Archive doesn&#39;t seem to have a real copy of it. As
far as I can tell, this spec is linking to a document that &lt;em&gt;never existed&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Okay, so much for the outdated HTTP signature specification. Fortunately, it was
eventually published as the real-ass &lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc9421.html&#34;&gt;RFC 9421&lt;/a&gt; which makes reference to the
real name of the IANA registry, &lt;a href=&#34;https://www.iana.org/assignments/http-message-signature/http-message-signature.xhtml&#34;&gt;&amp;quot;HTTP Message Signature&amp;quot;&lt;/a&gt;, although
inexplicably does not include a link to it. Unfortunately, the RFC&#39;s structure
for HTTP signatures is totally incompatible with the older draft&#39;s, so it&#39;s
still entirely unclear which one Mastodon instances want.&lt;/p&gt;
&lt;p&gt;At this point, I have two major outstanding questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;What is the correct format for the public key with which I&#39;m supposed to sign
requests?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Should I use the outdated draft HTTP Signature format, or the one from RFC
9421?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, I don&#39;t think there&#39;s any way to answer these questions other
than to read through an existing implementation&#39;s code, which is a treat I&#39;ll
save myself for some other day.&lt;/p&gt;
&lt;hr class=&#34;footnotes-sep&#34;&gt;
&lt;section class=&#34;footnotes&#34;&gt;
&lt;ol class=&#34;footnotes-list&#34;&gt;
&lt;li id=&#34;fn1&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;For those who are curious, the authorization scheme is essentially as
follows: when one ActivityPub server makes an authorized request to another,
it includes a cryptographic signature of some of that request&#39;s headers using
an actor&#39;s private key. The actor may be the signed-in user, but when
requesting public data it can also be an &amp;quot;instance actor&amp;quot; representing the
instance as a whole. This request also includes the URL of the actor so the
receiving instance can fetch its public key and verify the signature. &lt;a href=&#34;https://nex-3.com/blog/so-im-trying-to-add-support/#fnref1&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
  
</feed>

