Home Menu ↓

Blog

Dot grid paper

I’ve added dot grid paper to the note paper page, in a handful of sizes:

A grid made up of dots

Colophon: I made these with JavaScript/Node, generating SVGs that I then converted into PDFs with Inkscape.


Reply via email

New daily goal charts

Inspired by Robert A. Caro’s planning calendar, I’ve redesigned my daily goal charts:

A daily goal chart

This time the chart doesn’t have a specific year baked in, so it’s reusable. (And there’s a variation for leap years.) It’s freely available as PDFs in both portrait and landscape. Currently just letter size, though maybe someday I’ll start including A4 and other sizes.

Colophon: I made these charts with HTML (it’s just a table), CSS, JavaScript (on page rather than via Node), and Firefox. The font is Avenir Next.


Reply via email

Links #66

Andrew J. Hawkins on cars rewiring our brains to ignore all the bad stuff about driving. I would love to not have to drive anymore. It’s fun, but too dangerous. I also don’t trust self-driving cars. (Yes, I realize the obvious answer is to move into a big city. Maybe someday.)

Andy Bell on the extremely loud minority when it comes to building for the web. I believe one of the reasons for WordPress’s dominance is the number of sites that are document-like rather than app-like (where React is maybe a somewhat better fit, though I still prefer more minimal solutions).

Type designer Mark Simonson on analog drawing and spending less time on screens. I need to do this more often.

Chris Coyier linking to more 2023 CSS wishlists.

Una Kravets on container queries landing in stable browsers. Awesome. Looking forward to being able to use this.

Matthias Ott on container queries.

Klint Finley on the history and future of CSS.

iOS has accessibility support for playing background sounds like rain and white noise. Had no idea!

Lincoln Michel on unnecessary things in art. I agree that art isn’t meant to be utilitarian.

Sébastien Lorber on adopting React in the early days. Anthropologically interesting.

Rerun, an SDK for logging computer vision. Pretty impressive demo.

Dave Karpf with his reverse-Scooby-Doo theory of tech innovation. A worthwhile corrective.

Local-first web development. Intriguing.

Kevin Schaul on replacing Mapbox with OSS for a Washington Post piece.

Kottke on Alex Hyner’s sky collages. So cool!

Jen Simmons and Brady Eidson on iOS supporting Web Push. In limited cases, but it’s something. And there are other nice changes included (badging, the screen wake lock API, etc.).

John Allsopp on the Webkit/Safari changes.

Openverse has more than 600 million creative works under Creative Commons licenses or in the public domain.

Neil Clarke of Clarkesworld on being bombarded by AI-written submissions. Being a publisher right now seems…really difficult.

Kevin Roose on chatting with Bing’s Sydney chatbot. I read the whole transcript and it’s bonkers. Clearly Sydney is not a person or some other kind of sentient being, but still, that was a crazy read.

Max Matza on foreign accent syndrome. I don’t have this, though my wife and kids might sometimes beg to differ. (The actual thing, though — wow!)

Curious Archive on the complex ecosystem of the indie game Rain World. I doubt the “most complex” hyperbole, but leaving that out, it’s fascinating! Especially the procedural animation.

CAD Sketcher is working on adding more CAD functionality to Blender. (Disclaimer: while I’m interested in CAD and occasionally link to it, I’ve never actually done any CAD.)

Eliot Peper interview with Ray Nayler. Relevant quote: “At no point between life’s starting point 3.7 billion years ago and my and your complex awareness right now has that chain of informational exchange and interpretation been interrupted. If it had been, you would not be here to think of that interruption’s consequences.” That blew my mind — that the ancestral chain of my physical body is unbroken all the way back (as evidenced by the fact that I’m here, and that intermediate links had to survive long enough to reproduce).

Christopher Slye on the end of Type 1 fonts. I haven’t used them in ages (since my desktop Linux days), but goodbye, Type 1!

Andy Bell on just posting (on blogs). Again, if any of y’all have a blog, let me know!

Scott Nedrelow’s Magic Sleeve desk organization system, made from merino wool. Looks cool.

Marc on accessibility being for everyone. Yes, yes, yes.

José M. Gilgado on creation happening in silence. While I can think of several exceptions, there are still some truths here.

Henrik Karlsson on the childhoods of exceptional people. Fascinating reading, even if I have no idea how reliable the conclusions are. As for me, I care a lot more about my children growing up to be good people, and don’t particularly care if they grow up to be exceptional, but doing some of the things listed in the post (within reason) seems like it might be interesting.


Reply via email

Recent nonfiction reads

  • The Soul of a New Machine, by Tracy Kidder. Really good! I especially enjoyed the technical details about building computers in the early 1980s. I’m grateful that debugging is so much easier now (with the caveat that I’m sure it’s probably harder for the engineers building today’s computers than it is for those of us building higher up the stack). While part of me wishes I could have been there to build a new computer, the overtime culture at Data General seemed unhealthy and management seemed immature, and that’s not worth it regardless of how innovative or interesting the work is.
  • In Praise of Slowness, by Carl Honoré. I felt like this could probably have been shorter (self-help isn’t really my thing, by the way), but still worth reading. I now drive the speed limit, which I didn’t expect to be an outcome of reading this book. I also find myself consciously acknowledging that things usually don’t need to be rushed, which has been helpful. The bit about playing classical music half as fast was fascinating, too.

Recent fiction reads

  • The Handmaid’s Tale, by Margaret Atwood. For some reason I thought this was going to be boring and stodgy (I knew basically nothing about it before reading it), but it was well crafted, eminently readable, with good prose. It felt modern, too — almost like it could have been written yesterday. But it was also uncomfortable and heavy and so, so sad. This reminded me once again that as a rule I don’t particularly like dystopian fiction. Also, I learned that mayday is a borrowing from the French m’aidez — “help me.”
  • Slaughterhouse-Five, by Kurt Vonnegut. I…didn’t really like it. Or get much out of it. (Even though I tried to.) For me it was kind of a rambly mess, and the humor didn’t do anything for me either. But I’m glad other people like the book. I did sort of like Cat’s Cradle, so Vonnegut’s not completely off the table for me, but I’m also in no rush to read the rest of his catalog.

Reply via email

Links #65

Saharan’s zoomable meta Game of Life. Cool. And trippy.

Jen Simmons on CSS nesting, now available in Safari Technology Preview. Come on, Firefox.

Mike Crittenden with a simple cron for cleaning up your downloads folder. I keep meaning to set something like this up.

Tom MacWright on adding circles to Placemark, and why geospatial circles aren’t as simple as they sound.

Jason Kottke on a new image of the Milky Way with 3.32 billion individual objects. Whew!

Hannah Docter-Loeb about some weird polar vortex off the north pole of the sun.

React.js: The Documentary. I haven’t watched it yet because I’m awful at making time for long videos.

Robin Wieruch on ten web development trends this year.

WHO says no level of alcohol consumption is safe for one’s health.

Turborepo and Turbopack, by Vercel. Supposedly Turbopack is way faster than Vite. Interesting.

Zach Leatherman has been collecting criticisms of React.

Laurie Voss’s rebuttal of Alex Russell’s Market for Lemons post. I can see his point — network effects are real — but I still think we can do better for end users.

Thomas F. Arciuolo and Miad Faezipour with an idea on tapping the Yellowstone supervolcano for energy. And to keep it from erupting. Color me intrigued.

Harry Spitzer on Ryan Dahl and Deno. Enjoyed reading this. I need to play around with Deno some more. And Bun.

Chris Coyier on CSS for spacing between elements. I didn’t know about margin-trim, but it seems like a great future alternative to gap in non-flex/non-grid settings.


Reply via email

Latin declensions chart update

I ported my Latin declensions chart from PlotDevice (which was Mac-only and thus not accessible to people without Macs) to HTML/CSS.

Some notes:

  • My goal with this was to make a chart that’s modifiable as easily as possible without building a full chart-generation app.
  • Because this HTML and CSS is intended for print and not at all for the responsive web, there are a few ways I did things that I probably wouldn’t have used on a web project.
  • I considered using on-page JavaScript to generate the table HTML, since right now there’s a lot of duplication, but I opted to stick with straight HTML to make it easier for non-technical people to modify.
  • The column widths are manually set so that things line up across tables. I could have done one big table instead, but the editing ergonomics would have been substantially worse.
  • Chrome still can’t print lines less than 1pt in width, so I used Firefox to export the PDF.
  • I wish custom properties worked in @page. I also plan to eventually refactor this so that more of the CSS is configurable via custom properties. (At this point it’s just column widths/gaps and colors.)
  • This 3.0 version of the chart changes the font from Museo Sans / Minion Pro to EB Garamond, so that the font is freely available. (EB Garamond also feels more appropriate to Latin than Museo Sans.)

Reply via email

Learning WebAssembly, part 1

I’m having so much fun learning Elixir that I’ve decided to do a similar thing with web technologies I haven’t used yet. Similar to the 12in23 posts, these will be long and informal and more stream-of-consciousness, and I will say “interesting” and “looks like” far too often.

First up: WebAssembly. Other things I’m looking forward to trying out afterwards: WebGPU, WebRTC, WebGL (I’ve used Three.js on several projects but haven’t used WebGL directly if I recall correctly), WebSockets, service workers, web components, and a number of smaller things (primarily CSS features I haven’t yet used).

So, Wasm. I’ve read bits and pieces about it over the years but haven’t yet actually tried it on anything. I’m going to start arbitrarily with AssemblyScript. Later on I’ll use Rust, and I want to try writing the Wasm text format manually, too.

To begin, I’m going through the AssemblyScript Book.

Getting started

I generated a new AS project with asinit and have been exploring the files it produced, starting with release.js (to get a feel for how the Wasm code gets pulled in). This sample project just adds two numbers together, by the way. The actual AssemblyScript source is straightforward.

In release.js, I initially wasn’t sure what compile meant (in this context) since the example is compiling release.wasm which is already a binary. Looked up the compile page, which explained that the Wasm binary needs to be compiled into a Module, which the MDN key concepts page tells me is executable machine code. And it’s stateless. Okay, that makes sense.

I also wasn’t sure what instantiate did in this particular context. Found the instantiate page, which said it turns a Module into a stateful Instance. That also makes sense now. I imagine the reason one might want to instantiate a Wasm module more than once would be splitting the work up across workers, but I haven’t verified that. Also, looks like instantiateStreaming is now preferred, which simplifies things a little, so you don’t need both compile and instantiate. (That won’t matter for this AssemblyScript experimentation since I’ll be writing AssemblyScript and not finagling with the final JS unless I really can’t resist.)

Looking now at release.wat, because I’m intrigued and I also sometimes like to go in blind and figure things out on my own.

I completely forgot that the Wasm text format is Lispy.

Hmm, I see the $i32_i32_=>_i32 type defined. (By the way, seeing a type defined in an assembly language that looks like Lisp is kind of trippy but also quite cool.) I don’t see that type being used anywhere, though. Must be implicit. I imagine it applies to the exported function. If there’s more than one exported function, maybe they apply in order?

There’s a memory being exported alongside the add function. Interesting. I imagine this gives access to the memory the Wasm script is being executed in (the sandbox), but I’m not entirely sure why — what the host would use it for, I mean. Something to look into when I get back to the text format later.

The function definition itself looks fairly straightforward. Arguments and result type followed by the body of the function. Based on the i32.add instruction not taking any arguments, I’m guessing local.get pushes things onto a stack which i32.add then pops from.

I’m excited to dive deeper into the text format! But back to AssemblyScript proper.

Using the compiler

Okay, looks like memory can be both imported and exported, and the size can be specified as well. Interesting that this is set here (where the AssemblyScript is being compiled into a Wasm binary) rather than in the host when the Wasm is instantiated. My mental model of WebAssembly is more patchy than I realized — it’s been a while since I read an intro — but I’m having fun figuring things out archaeologically right now, so I’ll keep going like this for a bit longer.

Looks like there are several small runtimes that can be compiled in, some with garbage collection. Interesting, didn’t know that. (Looks like it’s a WIP.) And there are threads now. Wow.

Ooh, the compiler API can be used programmatically. I guess I shouldn’t be surprised.

Looks like it’s still just low-level data types that can be passed across module boundaries. Nice that AssemblyScript generates bindings for strings, arrays, and objects, though. That makes it far more usable.

Transforms are intriguing. Probably not useful for most projects, but still intriguing.


I’m going to stop here for this post, to try to keep things from going on too long in any given post. Looking forward to working through the concepts chapter next!


Reply via email

Thoughts on a little language for generative art

I’ve been thinking about resurrecting the Marks idea, partly because I’d like to use it for my art and partly because I want to have my 12in23 project (for at least some of the languages) be a simplified Marks parser. (And a little bit because my dad’s name was Mark.)

As a refresher: Marks is going to be a DSL for generative art. In its newest incarnation, it could also be used more generally for composition, but generative art is the focus.

The current plan is to have a number of types of top-level blocks: layers, brushes, path profiles, color definitions, functions, and properties, and probably a few others I haven’t fully thought through yet. A rough draft, which still needs a lot of refining, and which doesn’t yet include a lot of the ideas I’ll include in the notes below:

size 7500x7500
background white
color black #000
color red hsl(0 50% 50%)
seed 24601

brush circles {
  random.xy0(num: 50).each {
    circle(x, y, r: random(0.1), fill: black)
  }
}

pathprofile mytaper {
  0.0
  1.0
  0.8
  0.6
  0.4
  0.2
  0.1
}

layer.svg some shapes {
  subtract {
    circle(x: $width/2, y: $height/2, r: $height/2*.8, fill: red)
    rectangle(x: random.x, y: random.y, w: random($width - $x), h: 50, fill: red.lighten(0.2))
  }
  mask {
    line(x1: random.x, y1: random.y, x2: random.x, y2: random.y, strokeWidth: random(5, 20), brush: circles)
  }
  blend soft-light
}

layer.raster noise {
  xy.each {
    red.jitter(hue: 0.2)
  }
  blend soft-light
  opacity 0.2
}

Notes, acknowledging that this is mostly brainstorming and not a final, consolidated list:

  • Layers are the fundamental block, in that nothing gets output if there aren’t any layers.
  • Layers can be SVG (which then gets rendered to raster once the layer is done) or raster.
  • The background property adds a bottom layer filled with the color (leaving it out allows for transparency).
  • There’s a debug flag that exports each layer to a file individually (minus blending mode and opacity), so you can see what happened.
  • SVG layer commands include CSG booleans.
  • The “some shapes” and “noise” bits on the layers are layer names.
  • This isn’t shown here, but layers can be different sizes and can be positioned.
  • I’m leaning towards having Marks be as purely declarative as possible, though I suspect I’ll still need some imperative support (a random walk, for example, would be more difficult to do declaratively) (though I’m still going to see if I can make it work somehow). I’m thinking the top-level function blocks would be where imperative code happens, maybe.
  • random.x would get a random X coordinate within the canvas.
  • Layers can be masked, and within the mask there can be any rendering commands (still working on nomenclature here) that are available for the current layer type (which mostly means raster commands aren’t available on SVG layers except in places where an image is expected).
  • For SVG layers, the layer blending mode and opacity only apply after rasterization.
  • The xy variable returns an array of all the coordinates of the rasterized canvas.
  • Numbers and colors have a jitter method that allows for jittering within a set range .
  • The brush block allows using rendering commands to create a brush that can then be used to stroke paths or fill shapes.
  • The pathprofile block needs (a lot of) work, but the idea is to have some way to describe the profile of a path, so you can have paths with the width varying along the stroke. Ideally, this would support both relative percentage-based profiles (leading to different effects for short paths vs. long paths) and absolute profiles (so the effect is the same for any length of path that matches the values) and possibly a mix of both (absolute for the first 50px and then relatively fade out for the rest, however long that is, for example).
  • Good support for path navigation and manipulation. Be able to easily work with points every 20px along the path, for example, or every control point, or fifty random points along the path. Also be able to get normals and tangents for any points along the path.
  • Importing images from disk will of course be included.
  • This is a lower priority for me: animation support. There would be access to a frame variable. Each frame could use the same global random seed (with each layer getting seeded individually to try to preserve behavior) or could use a different seed.
  • This is moving more into pie in the sky territory, but I’ve become enamored of the idea of having Marks support 3D, including programmatic generation of the canvas texture in 3D and being able to layer paint (and then scrape some off to see layers underneath) and get impasto effects and all that. This would also support moving the camera around and creating/modifying 3D models to some extent. I like this a lot and I think it fits conceptually, but it may be a bit Too Much. (Part of me thinks it would make far more sense to do this separately as something in Blender, where you get so many 3D features for free.)
  • Marks files can import other Marks files.
  • Custom fill functions can be written, where you provide some code that then generates the content for whatever polygon is filled (clipped to the polygon boundary).
  • Shape packing helpers are planned, too, so you can fill a polygon with circles or any other shape. I’d like this to be programmatic, so that each shape could be different.
  • Layer filters will be included, too — blur, threshold, erosion/dilation, etc. — and these will apply to masks as well.
  • Colors can be defined in the usual formats (HSL, RGB, hex) and also LCH, and they can be modified dynamically (lightened, darkened, etc.).

There will undoubtedly be simplification along the way, since this is…a lot. The initial core implementation would (in my mind) be layers (both SVG and render, with a basic set of commands, excluding masks but including blending modes and opacity), colors, the random generator, debug mode, and exporting a final image. That’s enough base functionality for it to be usable.

I’m going to be working on a BNF grammar for this soon, once I get the syntax finalized enough that writing a parser is feasible.


Reply via email

Links #64

Marcin Wichary’s Kickstarter for his Shift Happens book. I backed this because man, I want that book. The livestream was fun to watch, too.

Nick Compton with an introduction on Tyler Hobbs, the generative artist.

Zach Watson’s writeup on his Arcadia generative art series. I love these types of things.

Tushar Sadhwani on adding C-style for loops to Python. Ha.

Stefan Schubert with a map showing the mean center of the U.S. population over time. Fascinating.

Johann Hari on the medium being the message and how it relates to television, social media, and books. A good way to look at it, I think.

Adam Roberts’ Tolkien reread. Good lit crit.

Kristin Houser on Shift Robotic’s new moonwalker shoes. I don’t know that I’d ever use these but they’re interesting!

Jay Hoffmann’s Vague, But Exciting… The Story of the World Wide Web. The first ten chapters are up.

Browsertech Digest, an interesting newish newsletter about modern browser technology: “We’re talking WebAssembly, WebRTC, WebGL, WebGPU, WebSockets, WebCodecs, WebTransport, Web-everything.” Right up my alley.

Womp, an in-browser 3D editor that uses signed distance fields instead of meshes. Fascinating! This was quite fun to play with. Also see the Browsertech issue where I learned about it.

Lunatic, an Erlang-inspired runtime for WebAssembly. Currently has libraries for Rust and AssemblyScript but can be used from any language that compiles to Wasm. The motivation page was worth reading.

Alex Russell with some strong words against the bigger JS frameworks. The footnotes were helpful for understanding things. I don’t know that I feel anywhere near as strongly about it as Alex does, but I very much agree that JS frameworks should be focused on the end user first and then the developer.

Eric Meyer’s 2023 CSS wishlist. Anchors sure would be nice. And from Dave Rupert’s wishlist, I very much want <selectmenu> and the View Transitions API for MPAs.

Richard Crossman reading part of the Scots edition of Harry Potter and the Philosopher’s Stane. (Yes, stane.) This was fun.


Reply via email

Learning Elixir, part 1

As my first 12in23 language, here’s my initial foray into learning Elixir. These notes will be informal and more stream of consciousness than anything. I have no idea if anyone will get any benefit from reading this, but I’m sure going to have fun writing it.

I’m starting out by working my way through the Elixir introduction. Once I finish that, I’ll start on a real project.

Basic types

Interesting that string concatenation is <> (which I’m used to meaning != in SQL and Excel/Google Sheets).

The naming of the div and rem functions makes sense. It also amuses me from an HTML/CSS perspective. (You could pull <> into this as well.)

Being able to drop the parentheses in function calls is nice (in that it’s cleaner), but I think the legibility gain from including them is probably worth it.

Ah, I think I’ve seen this kind of function identification (name + arity) somewhere before (maybe Haskell?). It’s a little different and reminds me vaguely of man pages, but I like it — nice to be able to tell at a glance how many arguments a function takes.

The built-in help in iex seems nice, and I’m liking the arity identification more and more as I continue to see it. Looking through the h/0 list now for a brief detour. Interesting that you can compile a file and export bytecode from the REPL. And hot dang, introspection with i is great. I don’t know what PIDs and ports are (in context of Elixir, that is). Okay, from the processes page it looks like PIDs are related to processes which are a fundamental Elixir concept — and not the same as OS processes. Also looks this processes page is a later section of the introduction, so I’ll set it aside for now. (At this point, I’m curious as to why you can set PIDs from strings or atoms or three integers, as opposed to having the system auto-assign them. Also intrigued by ports and references — in the languages I’ve used, ports are almost always ints.)

It’s been a while since I used a language with atoms (Ruby). Intrigued by aliases, looking forward to learning more about them later.

Nice to see string interpolation works as expected. (And in another brief detour I’m now wondering about the different syntaxes across languages. I’ve seen `${...}` in JavaScript and f"{...}" in Python. The "#{...}" here is interesting.) One thing I’m noticing is that there doesn’t seem to be an uninterpolated string. (Both JS and Python have those.) I wonder how much of a performance hit there is in Elixir from having all strings support interpolation. Probably not enough to matter most of the time.

Up next: anonymous functions. The fn and end feel a little noisy syntactically, but with syntax highlighting it’s probably fine. Interesting that invocation needs the . before the parentheses — so variables and functions appear to be in separate namespaces. I wonder if that’s actually true, and if there are other namespaces as well. Glad to see closures. (It would be weird not to, to be honest.)

Ah, list concatenation with ++ and --. One of the reasons I think it’s good to have broad experience with programming languages, by the way, is so your brain can fill up with multiple meanings for almost every symbol. I jest.

Interesting that a list of ASCII numbers automatically returns a charlist. And interesting that charlists are not strings. (Maybe this is the answer to the earlier comment about all strings being interpolated. I wonder if charlists are limited to ASCII.)

I’m realizing that this is going to take forever if I keep commenting on every last little thing. Attempting now to be more selective with comments.

Okay, lists and tuples. At this point I’m wondering if there are structs/records/objects/etc. Update: I did a quick look ahead and yes, there are maps and structs.

I like that the names for size and linear tell you if the operation is O(1) or O(n).

Basic operators

Ooh, the distinction between or/and/not and ||/&&/! is interesting. And here’s === again. Looks like it’s not quite the same as in JavaScript but is conceptually similar (stricter than ==).

Cross-data-type sorting is interesting.

Pattern matching

Ah, I love pattern matching. (I’ve mostly seen it in Rust so far.)

Good to see tuple and list destructuring. And I like how you can match as part of the destructuring. I don’t think I’ve seen that before. (But it’s been a little while since I’ve used Rust — you could say I’m getting rusty (I am so sorry) — and I can’t remember if it has this.)

Ooh, I like the [head | tail] matching. That’s cool.

The pin operator is new (to me) and interesting. Kind of a different way of doing immutability. And in matching, I like how it lets you use a variable without having to overwrite what’s in the variable (which would happen without pinning). I’m also thinking about how it’s the same operator for pinning version numbers in npm.

case, cond, and if

I like case. And guards. (Guards in Elixir, I mean. I’m not making a statement about guards out in the real world.)

Oh, now that’s interesting — anonymous functions can have multiple clauses (which I think I’ve seen in Haskell) but they can also have guards. That seems like a potentially cleaner way to handle main branches of logic within a function, maybe, but I don’t know — food for thought. And interesting that it’s restricted by arity, though in Elixir it appears that functions with different arity are considered different functions entirely. (Which is quite different from variadic functions in, say, JavaScript or Python.)

cond feels (to a degree) like a more powerful switch. Except in this case you can change the condition (both left- and right-hand sides!) for each branch. That’s intriguing. (Actually, giving it a few seconds’ more thought, case is much closer to a switch than cond is. Both of them are more flexible, though.) Playing around with cond feels kind of like having a superpower.

Happy to see unless. I haven’t used an unless since Perl a long, long time ago. I know it’s just syntactic sugar but I like it.

I love that if can return a value (as in Rust). It’s something I often find myself missing when I’m writing, say, JavaScript. Ternaries are the next best thing but not as ideal, in my opinion.


Okay, this is long enough for today. Looking forward to continuing through the tutorial soon! I’m really enjoying this.


Reply via email