Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
With Twitter on shaky ground, there’s a sudden interest in open social platforms and protocols as well as a return to hosting traditional web sites and blogs. But because we’ve become accustomed to low-friction publishing workflows (type a bit in a box, click Tweet), routinely writing real blog posts can feel daunting.
This video provides a brief overview of one way to organize a personal blog that’s structurally similar to daringfireball.net—allowing for short-and-sweet posts—but with modern architecture of Hugo for static site generation, Tailwind for styling, and Netlify (plus NetlifyCMS) for hosting and on-the-go publishing—enabling very low-friction publishing.
Resources
- Hugo
- Tailwind
- Netlify
- NetlifyCMS
- Justin’s CSS overrides to make NetlifyCMS more mobile-friendly
- Static CMS - a maintained fork of NetlifyCMS (see this issue for more background)
[00:00] (ethereal music)
[00:02] - Hello friends, I woke up this morning
[00:04] and I decided that even though I've got a cold,
[00:06] and even though I've done very little
[00:08] to prepare for this,
[00:10] I've been working on something I'd like to share
[00:11] with you and talk through it.
[00:12] Because, I don't know if you feel this way,
[00:15] but with the impending implosion of twitter.com,
[00:20] I feel, suddenly, like,
[00:22] a renewed sense that maybe I should own
[00:25] a bigger portion of the parts of the internet
[00:28] that I contribute to,
[00:30] which leads to the classic programmer
[00:32] who is dangerous enough with website stuff,
[00:36] a conundrum of building a blog
[00:38] over the course of a weekend,
[00:39] with the hope that maybe I'll start blogging.
[00:43] In this case, because I'd been down that road a bunch,
[00:46] I wanted to take a turn that would allow me
[00:49] to publish much more effortlessly.
[00:53] Like, the reason I was always tweeting so much
[00:55] was that I was, like, really easy to just,
[00:57] you know, fire them off from my phone.
[00:59] And so, I needed a workflow that allowed me
[01:00] to write quick and dirty posts for my phone,
[01:03] as well as a permission structure
[01:06] to write very, very short posts.
[01:07] Whereas, I typically can write way too much.
[01:11] And so, my inspiration right out of the gate
[01:13] was "Daring Fireball".
[01:15] It's one of my favorite blogs.
[01:16] John Gruber is, you know,
[01:18] just sort of an institution with blogging.
[01:21] But weirdly enough, his linkblog style of blogging
[01:25] is not very well understood,
[01:26] and not very, you know, often imitated these days.
[01:30] So if you're not familiar,
[01:30] just to walk through the information architecture
[01:32] of like, what "Daring Fireball" is,
[01:33] is there are posts, but not very many of them.
[01:36] If you go to the archive, you know,
[01:37] maybe he turns out 2, 3, 4 real posts a month.
[01:42] You go in, it's like,
[01:42] "Okay this's his Apple Watch Ultra post."
[01:45] You know, it is a permalink,
[01:47] you look at the RSS and this's the alternate link,
[01:50] this's the canonical link for that.
[01:52] But most of the stuff that he posts're just, like,
[01:54] links to other stuff.
[01:55] So like, in this instance, this's a link
[01:58] to, you know, a third-party website
[02:00] and its article.
[02:01] And what he's just doing is providing color commentary,
[02:04] or giving his take on something,
[02:05] usually with pull quotes.
[02:08] And if you want to, you know,
[02:10] share the "Daring Fireball" link,
[02:13] the permalink, here,
[02:15] is just available on this little star.
[02:17] And then you can go and...
[02:18] Now the URL is, you know,
[02:19] updated to have that full thing.
[02:21] So I've always really liked this approach,
[02:24] because it seems like something that if I could do that,
[02:27] then I would have...
[02:30] I would more fluidly share things that I'm thinking
[02:33] instead of just, like, texting them to a friend
[02:35] or tweeting them into the ether.
[02:38] So I undertook a little bit of a journey, here.
[02:42] And I had an existing app,
[02:46] at justin.searls.co,
[02:48] that was written in Hugo.
[02:49] And Hugo's a great, super-fast static-site generator.
[02:52] It's a very basic blog.
[02:53] Basically, it was just (chuckles)
[02:55] dealing with medium.com's impending implosion,
[02:58] and pulling down all of my posts
[02:59] as quickly as possible into markdown,
[03:01] and grabbing their images, and so forth,
[03:03] so that I could have a place for them to live
[03:05] in the event that Medium went away.
[03:06] Medium didn't go away, which, you know,
[03:08] probably says something about whether we should
[03:10] be predicting the literal demise of Twitter
[03:12] or just its, you know, descent.
[03:15] But I had the bones of a site there,
[03:18] so I'd already kind of gone
[03:18] through some of the motions.
[03:20] And Hugo is also very flexible.
[03:22] You know, I'm not going to explain
[03:23] how to build a Hugo app here,
[03:24] because it's written in Go lang.
[03:26] Like, a lot of the configuration
[03:28] is kind of arcane, to be honest.
[03:32] And the community forums can sometimes seem hostile
[03:34] to users asking questions.
[03:36] But otherwise, it's really fast and really good.
[03:38] I know I'm really selling it.
[03:40] But it's very future rich,
[03:41] it's very flexible for doing things like,
[03:44] in this exact case, we have two kinds of posts.
[03:47] We have two different content sections.
[03:49] And we have a main feed that needs to be able
[03:52] to merge them together nicely,
[03:53] and we also need to be able to use those data types
[03:56] to build things like an Atom XML RSS feed.
[04:00] All right, so that was the first piece.
[04:01] Second piece was I had written that original site
[04:04] with a particular style, lightweight,
[04:07] nothing too fancy, in SAS,
[04:10] and just raw SAS and light,
[04:11] I got really, like, bent out of shape
[04:14] with a lot of confusing, overly-complex selectors.
[04:18] And every time I changed anything, you know,
[04:20] it was just the Peter Griffin blinds GIF happening on me.
[04:24] My friend, Derek Briggs, over from PlanetScale.
[04:28] He paired with me on Tailwind
[04:29] just enough, for an afternoon,
[04:31] for me to see the light,
[04:33] and realize that the locality of writing
[04:35] in utility classes and scoping them
[04:37] down as I work through a page
[04:39] allows me to think
[04:40] outside-in about how the page is structured
[04:42] in a way that I was never able to do
[04:43] when I was balancing a CSS file and a markup page.
[04:46] So the first order of business
[04:49] when I was doing this work
[04:51] was to throw away all the original styles
[04:53] and restyle it from the ground up,
[04:54] even though it looks very similar in Tailwind.
[04:57] And amazingly, it took, like, an hour and a half.
[05:00] Which is a level of productivity
[05:02] that in, you know,
[05:03] 20 years of tootling around on the web,
[05:06] I've never experienced before.
[05:07] So, you haven't played with Tailwind yet.
[05:09] check it out.
[05:11] For hosting, for static sites,
[05:13] I really like Netlify.
[05:14] Normally I use Heroku for running a lot of my apps,
[05:18] and simple SaaS services.
[05:19] Because like, you know, the managed Postgres is amazing.
[05:22] As awesome as Heroku's managed Postgres is,
[05:25] it provides no CDN story out of the box.
[05:28] So like, you know, edge network delivery of content
[05:31] in a cached and performant way
[05:32] that's not going to completely obliterate your server
[05:34] if you ever get, you know, fireballed,
[05:38] or linked to from "Hacker News", or something.
[05:41] Netlify is the opposite.
[05:43] Where Netlify is highly optimized
[05:45] for static-site delivery,
[05:47] and everything that you post up to it
[05:49] goes into a CDN right away.
[05:51] So, here's what the site ends up looking like.
[05:55] You know, you can see, instead of a star,
[05:57] I've got, like, a little salt shaker. (laughs)
[06:00] So this's like my first link post of commentary
[06:03] on Meta's very flawed Quest Pro product.
[06:08] And if I click in here,
[06:10] I apparently stopped my server.
[06:11] So that's...(laughs)
[06:13] I'm on my local host.
[06:15] So let's go ahead and start that up.
[06:17] So script/server.
[06:22] and that'll do things.
[06:24] I always turn caching off 'cause it's so fast.
[06:26] I'd rather have the confidence to know
[06:28] everything was from scratch.
[06:30] So I click in here,
[06:32] and now I'm at the permalink URL.
[06:34] But if I go back to this page, you know,
[06:36] you can see I scroll
[06:38] back and I'm back in March,
[06:39] 'cause I don't blog here very often.
[06:41] But I'm hoping to write more soon,
[06:43] and you can see there's links on the side
[06:45] that just show me the posts,
[06:47] and then just show me,
[06:48] like, the link posts, the linkblog.
[06:50] An About page, the RSS feed,
[06:52] which I learned RSS 2 is not a particularly great spec.
[06:57] And so, if you want to write this kind of blog,
[06:59] you actually need to use an Atom XML feed,
[07:01] because it allows you to specify both a alternate,
[07:06] which is like the real page link tag,
[07:09] as well as a related link tag.
[07:11] And that's what this is.
[07:13] So it allows RSS readers to be able to link
[07:15] to both your permalink of your post
[07:17] as well as to the source link
[07:20] when you're writing a linkblog-style post.
[07:22] And then, of course, other links over here.
[07:26] If you haven't gotten on the Mastodon train yet,
[07:29] or if you're about to,
[07:31] I encourage you to do it.
[07:32] It's less of a ghost town than you'd think.
[07:34] Again, I'm really good at sales.
[07:36] I am searls@mastodon.social,
[07:39] and I hope that you'll be my friend.
[07:42] People are really hopping on this week,
[07:44] so that's exciting.
[07:45] All right, so, right.
[07:48] So here's, you know, where it lives on GitHub.
[07:50] Everything that I do just pushes up to here.
[07:53] And we're going to just make a quick change.
[07:56] Oh, I guess before I do that,
[07:58] was there anything else I wanted to show you?
[07:59] So I got into the link posts.
[08:02] Oh yeah, so responsiveness was important, right?
[08:04] Because, like, most of the stuff
[08:05] is happening on my phone.
[08:07] I love Safari's responsive editor for stuff like this.
[08:10] So here I am.
[08:11] Even though it hasn't been updated
[08:12] since the iPhone 8 was the new phone,
[08:15] it's an easy, quick way for me to be able to see,
[08:17] "Okay, so here's what it looks like on a phone."
[08:19] You can see that the nav just simplifies
[08:21] to just post links about the important stuff.
[08:24] And you can scroll through.
[08:27] The other thing that this can do
[08:30] is you can actually size dynamically,
[08:32] just like skoshing it up a little bit, up and down.
[08:35] So even if it doesn't fit
[08:36] a particular, exact size of a device.
[08:40] Or, you know, I can pick an iPad mini,
[08:41] you can click here and it can, you know,
[08:43] do the split-screen thing
[08:44] or do what it looks like in portrait mode.
[08:47] So if I just play with this,
[08:49] you can sort of see the break points are,
[08:50] it's like, full screen 'cause you don't have
[08:51] a lot of screen space.
[08:52] And then it kind of becomes a page on the screen.
[08:54] And, in fact, one of my little touches
[08:56] is the page curl animates as the page loads.
[08:59] And you scroll a little bit further, and then,
[09:01] or you widen the view port a little bit more.
[09:03] And then, the navigation shifts
[09:05] from the top of the screen over to the side,
[09:06] 'cause now there's enough room to render that.
[09:09] So I work in this mode all the time,
[09:11] and it's one way for me to consistently be switching
[09:14] between 2x and 1x view ports
[09:18] of point density
[09:20] as well as, you know,
[09:21] big and small view port sizes.
[09:26] So that's that.
[09:29] And then, also, light and dark mode.
[09:31] So I'm going to use Raycast, here,
[09:33] 'cause Raycast is a spotlight-like app
[09:35] that makes it very easy to switch
[09:36] between light and dark mode,
[09:37] which I've been doing constantly
[09:38] for the last few days.
[09:40] Okay, so here you can see
[09:43] that light mode and dark mode,
[09:44] the color schemes all transfer, you know,
[09:46] it's just a matter of taste.
[09:48] The shadows and all that,
[09:50] you know, they, they adjust.
[09:51] So Tailwind makes that, again,
[09:54] absurdly easy to show you
[09:55] what that, like, configuration looks like,
[09:57] is it's really just all CSS variables,
[10:00] which I think is really kind of cool.
[10:02] So here at the top of the CSS file,
[10:04] I just have, you know, a handful of colors.
[10:06] Those purple accent colors,
[10:07] background, border, text.
[10:09] And so, in light mode,
[10:10] this's those RGB values, space delimited.
[10:14] And then in dark mode,
[10:14] here's all of those same values,
[10:16] again, space delimited and just eyeballed.
[10:19] The reason that they're RGB and space delimited
[10:22] is this's sort of a new thing in Tailwind,
[10:27] but you can actually apply alpha modifiers
[10:30] to these values if you set them
[10:32] up in your theme a particular way.
[10:34] So in this case, you can see, you know,
[10:37] BG primary, that's actually getting, ah...
[10:39] I wrote a (laughs) premature abstraction.
[10:42] I wrote a variable, or a function,
[10:44] to extract this out.
[10:45] But like, basically you take the variable name here,
[10:47] and then you divide by the alpha value.
[10:51] You just give it that magical string,
[10:52] and then all of a sudden,
[10:53] all of these colors are usable
[10:55] in every single Tailwind construct really easily
[10:57] between light and dark mode with.
[10:59] And that's the last time
[11:00] that I really had to think about dark mode
[11:01] when I was making this.
[11:03] All right, so that's a little bit
[11:04] what the site looks like.
[11:04] Let's make a quick edit
[11:06] to show you what the publishing workflow looks
[11:08] like when I'm writing from my computer.
[11:10] So let's make a quick change to this post.
[11:14] You know, there's a traditional, kind of like,
[11:15] you know, YAML-style front matter
[11:17] at the top of the markdown file.
[11:19] Let's just change this
[11:20] from 10 minutes to five minutes.
[11:24] And then, we'll hop over here into this view,
[11:27] and we will just say, "All right, change the..."
[11:34] I don't know, I never know.
[11:37] When I'm writing prose, like,
[11:38] my commit messages don't matter.
[11:40] I'll just commit it, whatever.
[11:41] And then update prod.
[11:45] When I do that, of course, you know,
[11:46] it goes into GitHub.
[11:48] We're very used to stuff going into GitHub.
[11:50] So you can see that prose link came.
[11:53] Now, here I am in Netlify's backend
[11:56] and I want to look at the deploys, right?
[11:57] So I go into production deploys,
[11:59] you can see it's already building pros.
[12:00] And we'll see how long this takes.
[12:02] It'll be long enough for me to wait on, I hope,
[12:05] because it's surprisingly quick.
[12:07] I mean, you can look at the historical speeds.
[12:09] It's about 20 seconds to launch,
[12:11] which is, like, a lot faster than I'm used to.
[12:13] Especially considering that, like,
[12:15] it's installing a bunch of NPM stuff,
[12:16] it's running Hugo.
[12:19] Alright, so if we're here, our real page, now,
[12:22] I'm going to switch to light mode real quick.
[12:24] We're at our real page.
[12:27] And now, it's just five minutes.
[12:29] Okay, so that, like, that was reflected.
[12:31] Now that's great.
[12:32] I don't know why I decided to switch to light mode.
[12:33] It's dark, it's morning, I'm getting over a cold.
[12:37] I need to keep things chill.
[12:39] That's me, I'm super chill.
[12:42] (laughs) And also have had
[12:45] too much cold medicine this week.
[12:47] So, here's the thing.
[12:52] All of this is great.
[12:54] All of this is a fun little project,
[12:56] but it requires me sitting at my computer
[12:59] and kind of treating blogging as work.
[13:03] Which it is very much not work,
[13:05] it's just a thing that I like to do
[13:08] when I've got some spare time.
[13:09] And, like, the idea of spending, you know,
[13:11] time after hours, or time on weekends,
[13:13] just kind of holed up into a, you know,
[13:16] like, a work-like posture just because I want to share
[13:19] something quickly on my blog
[13:21] is all kinds of no fun to me.
[13:23] So what I did was I adopted this thing
[13:26] called Netlify CMS.
[13:28] So Netlify published an open-source CMS
[13:30] that is not technically tightly coupled to Netlify,
[13:32] but is totally kind of much easier
[13:34] if you roll with the Netlify server-side stuff.
[13:40] And all I did was add
[13:41] a static admin folder over here,
[13:44] with a index html file that simply sprinkles
[13:48] in, you know, their CDN link to...
[13:52] So basically, this whole page is like a bookmarklet.
[13:56] It'll just kind of take over the whole UI.
[13:59] And then I wrote some mobile overrides,
[14:00] because it's actually, surprisingly and sadly,
[14:03] not a responsive app.
[14:05] And so, when I'm on a phone,
[14:06] I just kind of hijack all the styles
[14:08] and make sure that they contort
[14:10] to the viewport,
[14:13] which I can share in a gist after this's done.
[14:17] All right, and then, additionally,
[14:19] the only real kind of configuration
[14:20] is just for it to learn a little bit
[14:22] about the file structure.
[14:23] That's the Netlify proper,
[14:25] where is the
[14:31] YAML, it's a config YAML file.
[14:33] Static admin, I scrolled right past it.
[14:35] All right, so like, it uses Git,
[14:37] it wants to know where to upload things.
[14:39] It converts slugs, it has, like,
[14:42] you know, separate collections, right?
[14:44] So like, the links pages and how those look,
[14:46] and then the post pages and how those look,
[14:48] and then what parameters you need.
[14:50] So that's the setup.
[14:52] And additionally, for identity,
[14:53] you can use Netlify's own identity thing.
[14:56] So I'm going to go ahead and unlock here.
[14:59] So I'm logging in here with my Netlify account
[15:01] against my own, you know, URL.
[15:04] But it's all happening over JavaScript
[15:06] via, you know, XHRs.
[15:08] And so, now I can see
[15:10] I've got, you know, my link posts.
[15:13] So posts are here,
[15:15] and linkblog posts are here.
[15:18] You know, I can go in,
[15:19] I can edit any of this stuff and click Publish,
[15:21] it'll commit to Git right away.
[15:24] So just kind of walk through what that feels like,
[15:26] and what ends up resulting on the file system.
[15:30] Let's make a quick post now.
[15:31] So I've got a post that I drafted
[15:35] that's sitting on my second screen.
[15:38] And this's a link to a really cool blog.
[15:40] I don't know how to pronounce this blog, "Salooned"?
[15:44] But this blogger has produced
[15:45] some very, very good blog post
[15:47] about the Ruby programming language
[15:49] over the last few years.
[15:50] And it is starting to take over the Google PageRank
[15:52] because it's just so accurate and informative.
[15:56] And he just wrote a post,
[15:58] or they just wrote a post about Ruby 3.2
[16:01] adding a new data class.
[16:03] So here's a post, I'm just going to blat it in there,
[16:06] that I wrote in advance,
[16:07] about why I'm excited about this data class
[16:09] as an alternative to struct.
[16:11] Here you can see I've got, like,
[16:12] my first code example ever on this blog,
[16:15] so we'll see what that looks like.
[16:17] All right, so when I have all this stuff ready,
[16:19] Draft is just going to skip it from,
[16:21] you know, being shown a prod.
[16:23] But we're, we're going to just go straight to prod
[16:25] and hope this works.
[16:26] 'Kay, so I'm going to hit Plug, Publish.
[16:29] When publish happens,
[16:30] it should immediately update GitHub
[16:32] so we can see it's got one new commit.
[16:36] The new commit has a conventionally-built file name,
[16:40] so I don't have to think about file names.
[16:41] It's just year, month, date.
[16:42] And then a slugified version of the the title
[16:46] that I gave it.
[16:48] And if I ever change that title,
[16:49] I can hard code the URL so it doesn't change.
[16:51] And then, if I...
[16:53] Well this, okay, I'll hit Refresh on this page.
[16:56] And it's already published.
[16:59] So I refresh the page now, and here it is.
[17:01] And you can see I've got,
[17:03] syntax highlighting and all that
[17:04] is handled very easily by Hugo.
[17:06] There's a couple manual steps to do,
[17:08] but it's not hard to figure
[17:08] out when you're reading the docs.
[17:10] And I kind of enjoy this sort of, like,
[17:12] cut out view of the code,
[17:13] because it looks like it's sitting
[17:15] right underneath, like, the document paper.
[17:18] 'Cause it's the cool code,
[17:19] it's underneath the covers.
[17:21] And then, you know,
[17:22] got different code syntax highlighters
[17:25] for light and dark mode.
[17:27] So yeah, that's what I've been,
[17:30] you know, up to in this, you know,
[17:33] the beginning of the aftertime,
[17:37] with not being so reliant
[17:39] on Twitter anymore.
[17:43] And I'm also starting to get excited
[17:44] about other means of distribution.
[17:46] Like, so, for example, I showed off Mastodon a minute ago.
[17:50] Mastodon, like, implements a thing called ActivityPub.
[17:52] And I don't really know what ActivityPub looks like,
[17:54] except it seems to be a neato way
[17:57] to both publish, and consume,
[17:59] and subscribe to content
[18:00] from heterogeneous types of sources.
[18:02] So instead of just following Mastodon users,
[18:05] you could presumably, like, follow a blog
[18:10] that implemented ActivityPub appropriately.
[18:12] And so, that's the next thing
[18:13] I'm going to look into, is try to figure
[18:14] out whether or not I can make
[18:16] more things that I'm doing on the internet,
[18:19] sort of, passively be subscribable
[18:21] through anything that adheres to Activity Pub.
[18:24] And I have no idea if it's just like the next XHTML
[18:27] and we're all going to forget about it,
[18:28] or if it's actually going to become, like, you know,
[18:31] the plumbing for, you know,
[18:33] a new, more open set of of tools
[18:36] and experiences on the web.
[18:38] So anyway, exciting times if you, like me,
[18:41] are getting the itch to start blogging more,
[18:43] or owning your portion of the internet
[18:47] and it means that you control a little bit more
[18:49] rather than being beholden
[18:50] to the social media companies.
[18:52] I hope that this was a little bit of inspiration.
[18:54] And then check out the description notes,
[18:56] and I'll share some links
[18:58] for how to get started, yourself.
[19:00] All right, I'll catch you later.