Hey folks! I hope everyone’s week has been going well. I’ve enjoyed the little conversations some of us have been having through the week.

Today I’d like to announce a small little project I’m working on: HashUp.


I’ve always been dissastisfied with the physical act of writing: with pen and paper it’s slow and requires a fair amount of concentration to write smoothly, and with computers… well, there’s What-you-see-is-what-you-get style editors like , which I dislike: I’m not trying to typeset a document to be printed, I’m trying to write! Unfortunately, most non-WYSIWYG editors and formatting languages like are similar in the same fundamental way: they exist to facilitate visual formatting, not help an author encode semantic meaning.

I pretty much never want to, when I’m writing, record that a certain word is italicized. I want to, maybe, record that it’s emphasized: modern HTML has at least come that far, letting handle the styling past that semantic.But more likely, as a writer, I want to say, “this is a foreign term,” or “this is a character’s internal monologue,” or, “this is emotional.” All of those are usually conveyed by adding emphasis through italics, that’s not guaranteed, and beside, emphasis isn’t nearly as precise.

When I was using -mode, I got in the habit of using its macros to wrap text that might otherwise be emboldened or emphasized, so that it could also be, say, if the document was being exported as , changed to link directly to my website.

But that was clunky, and by now I’ve drifted rather far from Org-mode, and I’m not even using , the only text-editor Org-mode works in, right now! HashUp is my solution to my current problem, of “I don’t know how to format the text I write in a way that makes it useful to me, later.”

It’s influenced by a lot: what I talked about above, but also using social media and other programming languages.

At its most basic, it’s simple: start using hashtags in your writing, and the HashUp processor will replace them with whatever string you’ve configured. If you want to do something special with that hashtag, throw a pair of {} after

the word, and fill them in with the arguments to the relevant processor function. (If there’s no relevant function, the text is untouched.)

It has a bunch of limitations: there’s no nesting or scope-awareness, so any opened block needs to be closed, for example. And it requires either writing your own processor functions, or me writing a standard set and publishing that.

But! It’s definitely a lot closer to what I want than Markdown, even after just an afternoon tinkering.

Has anyone else tried their hand at a custom markup format? If so, I’d love to see what you came up with!

I’ve just begun teaching myself about website development, but I’m already beginning to form opinions:

If you’re going to release your CSS stylesheet(s) as a theme, intended for use on more than a single website, you should prioritize following industry standards and guidelines. I understand, for a single site that might get a hundred visitors, make things pretty however works.

But if you intend to distribute the theme, or use it on a site of any popularity, you need to think about how that amplifies any shortcut or oversight you’ve made.

I started thinking about this when learning to use the [Gutenberg static site generator](https://getgutenberg.io) and looking at the themes available for it. (And later, for Hugo and Jekyll.)

A lot of them are really bad in this regard. Many don’t use semantic tags like <header> and <section>

Frankly, I don’t see the excuse. It’s trivial to type id=”{{page.slug}}” or add in conditionals for ograph data. Just… do it. I’m a novice, and I am.

I’m on a rant now so just ignore me if you want, but for real, no one with their priorities straight gives a shit if your website builds in 200ms or 2 seconds. They don’t even really know what “build” means. They’ll give you the inch of agreeing to use markdown to write their pages. They’ll even learn to do weird {{ shortcodes }}. But then you have to make sure their images and descriptions show up right on Facebook shares, and they can drop in their SaaSy widgets.

This is why I’m so in love with Netlify at the moment – I haven’t been using them long enough and I’m too ignorant to know about the tech, but their marketing really does a good job of hitting the market’s pain points and resolving them. And what they’re offering isn’t much different than what a bunch of other folk offer. But it’s different enough that they just fit into the market better.

Brutstrap is a CSS theme based on David Bryant Copeland’s “Guidelines for Brutalist Web Design,” which advocates “raw content true to its construction.”


  • The website people see is the website in the HTML file. As David Byant Copeland says in his definition, brutalist websites should be “raw content, true to [their] construction.” Here, that means the content is represented as a single column, flowing left to right and top to bottom.
  • Only links, inputs and buttons should respond to interaction. A website should allow two points of interaction: a hyperlink that brings you to a destination, and form which submits information to a server. Those elements, and only those elements, should respond to being clicked, focused, or hovered-over.
  • Components should be named what they are. Classes should be named what they are, not what they’re for.
  • Design should be helpful. Styling should be to help reinforce the context that your content has.


Brutstrap‘s stylesheet is available at ./build/brutstrap/brutstrap.css, but please don’t hotlink to it. You can also view the stylesheet under the “Complete Stylesheet” section.


NOTE: Because I use Org-mode, this CSS is written with rules compatible with its naming scheme.

Document Framing

body {
  position: relative;
  background-color: ;
  color: #444;
  font-family: serif;
  margin: 0 auto;
  padding-bottom: 6rem;
  min-height: 100%;
  font-size: 1.4em;
Header & Title
header, h1 {
  font-family: sans-serif;
  text-align: center;
  width: 100%;
  overflow: hidden;
  font-family: sans-serif;
.title { font-size: 3.2rem; }
.subtitle { font-size: 2.2rem; }
Content Container
main,  {
  width: 75vw;
  max-width: 40em;
  margin: 0 auto;
  line-height: 1.6;
  margin-bottom: 8rem;
footer,  {
  padding: 1em 0;
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;

Block Design

section {
  border-bottom: 0.1em solid #444;
  margin-bottom: 1em;
blockquote {
  padding: 0.5rem;
  border-left: 0.1em solid #444;
table {
    border-collapse: collapse;
    border-spacing: 0;
    empty-cells: show;
    border: 0.1em solid #444;
thead { font-family: sans-serif; }
td {
  padding: 0 0.3em;
  border: 0.01em solid #444;


h2, h3, h4, h5, h6 {
  font-family: sans-serif;
  margin: 0.5em;
a {
  text-decoration: none;
  color: ;
  display: inline-block;
  position: relative;
  border-bottom: 0.1rem dotted;
  line-height: 1.2;
  transition: border 0.3s;
a:hover {
  color: ;
  outline-style: none;
  border-bottom: 0.1rem solid;
a:visited { color: ; }
a:visited:hover { color: ; }
a:focus {
  outline-style: none;
  border-bottom: 0.1rem solid;

State Rules

Selection Rules
::selection { background-color: #777; color: ; }
a::selection { background-color: ; }

Class Rules

Code Block Rules
pre, .src {
  padding: 0.5em;
  border: 0.1em solid #444;
  white-space: pre-wrap;
  overflow-x: scroll;
  text-overflow: clip;