macOS-style focus rings, union fields, new date handling and more

This week was a fruitful one and full of commits. I went through and polished literally every element of the user interface, added support for a feature I wasn’t sure would be possible and changed how Darkmatter works with dates.

Native-like focus rings

I used Electron to build Darkmatter, but I still want it to work and feel like a native macOS app. I made one more little step in that direction and implemented macOS-style focus rings for every focusable element in the user interface.


They have a unique scale-down effect that I’ve only seen on macOS. It’s a tiny detail that most won’t notice, but so are many other small things that make up a great looking design.

Having seen these focus rings so many times in native apps, Darkmatter definitely fits right in among them.

Union fields

Zod supports so called unions that say “this field can be string or a date”. When defining such a field in an Astro content collection, it looks like this:

const posts = defineCollection({
  schema: zod.object({
    title: zod.string(),
    date: zod
      .transform((value) => new Date(value)),

This way, date can be specified as a string or a date and it’ll be converted to date at the end.

I wasn’t sure how Darkmatter would handle this collection schema in the most user-friendly way. I imagined it would look at the current value and auto-detect the right field type to show for it. And if I wanted to, I could switch between the allowed types via dropdown.

Well, there’s no need to imagine this any longer, because everything I just described got shipped.



Every developer knows that dates and timezones are painful, and if they don’t know it yet, they will soon.

I faced a timezone issue myself this week, when I noticed that dates and times on my production website didn’t match what I saw on localhost. I edit all my website content in Darkmatter, which saves all fields as ISO 8601 timestamps.

date: 2023-08-12T17:44:16.114Z

In JavaScript, when you pass that string to a Date constructor, it’ll automatically convert to your local timezone. It all works well, as long as this happens in the browser.

However, I have a statically generated website powered by Astro, so all dates would convert to a server’s timezone, wherever it is located. To solve that issue, I explicitly formatted all dates in Europe/Kyiv timezone.

But then I kept thinking, how often do Astro users need to show the time, rather than just a date? Wouldn’t it be better if Darkmatter saved timeless calendar dates for fields by default?

date: 2023-08-12

I asked around and this simplified date format is a more popular one than a full timestamp. The best part, JavaScript doesn’t do any conversion here, so dates will always be displayed as they’re set in frontmatter.

I decided to ship this breaking change now, since there’s a lot less risk in breaking things before Darkmatter is publicly launched. Starting this week, fields are saved in 2023-08-12 format.

Next week I plan to ship an alternative solution for those who still want the ISO 8601 timestamp.

It’s a small improvement, but you can now search entries inside collections.


It doesn’t search the Markdown content of the entries yet, but it should still be useful when you need to quickly find a certain collection entry.

With everything that’s been shipping lately, Darkmatter becomes more mature, more stable and more ready to launch. Thanks to invaluable feedback from early adopters, I focused on the things that truly matter and postponed the ones that don’t.

There are few more open tasks left with an “important” label, which I really want to see in v1.0. I believe they will make Darkmatter even more appealing to people using Astro than it already is (wow, so humble, am I right?).

With that said, I don’t want to drag the launch out much further and I’m excited to publicly release it as soon as possible. Full steam ahead!

Follow the development

Darkmatter is in active development and may launch next month. Follow the updates, get early access and watch the building process.

If email is not your thing, read the blog or follow on Twitter.