{
  "path": "/astrojs-first-impressions",
  "site": "at://did:plc:zviscnpwyvj6y32agi5davn5/site.standard.publication/3me4txfib342s",
  "tags": [
    "astro",
    "zod"
  ],
  "$type": "site.standard.document",
  "title": "Astro: First impressions",
  "bskyPostRef": {
    "uri": "at://did:plc:zviscnpwyvj6y32agi5davn5/app.bsky.feed.post/3lafszk4cjj2n"
  },
  "description": "My first impressions of Astro, a web framework for content-driven websites.",
  "publishedAt": "2024-11-07T00:00:00.000Z",
  "textContent": "Hey all! This is the first post I've written in a while, and the first that'll\nbe published on my personal site instead of a site like Medium. I have found\nthat I barely get anything from posting on Medium, and it's too gamified to\nreally enjoy posting there anyway. Hopefully having something low-stress like\nthis site will help me post more.\n\nWhen I was first trying to get my personal site up and running, I was looking\nat frameworks like Gatsby or [Jekyll][jekyll]. However,\n[Gatsby looks like it's about dead][gatsby-dead] and I wasn't really looking to\nuse GitHub pages for Jekyll, as I don't know Ruby and don't really want to\nlearn. I came across a relatively new framework called [Astro][astro] in my\nsearch and after getting things how I like them, I'm enjoying using it quite a\nlot.\n\nThe Astro component format is interesting\n\nAs someone who is more used to client-side components libraries,\n[Astro's components][astro-components] are a novelty to me. Essentially, all of\nthe JavaScript functionality in Astro components is gated to the server side;\nyou cannot have client-side interactivity in Astro components as by default\nAstro doesn't ship _any_ JavaScript. This isn't great for building UIs, but it\ndoes have the benefit that it's harder to leak server-side secrets to your\nfrontend.\n\nThankfully, Astro makes it really easy to use third-party component libraries\nlike [React][react] or [Svelte][svelte] to provide client-side interactivity.\nThink of Astro components as strictly server side logic and HTML templating and\nyou should have a good time.\n\nHere's an example from this site:\n\nAs you can see, all our real logic happens in the fenced code section - and\nthat's literally fenced, as you can see with the --- on either side. Outside\nof that, we only get logic-less JSX (excluding what you import as client-side\ncomponents, like NotePage.svelte).\n\nContent collections are really cool\n\nI really love Astro's content collections. Rather than have pages fully defined\nand routed like you normally might in a bespoke static site like this, you can\nplace your content in a designated folder at /src/content. You keep different\ntypes of data in different folders, kinda like tables in a relational database,\nand this data can be markdown files or just plain data in YAML or JSON.\n\nIf you're familiar with Obsidian's [Dataview][dataview] plugin, content\ncollections allow you to interact with your content in a very similar manner.\nAstro bundles in a nice schema generation system called [Zod][zod] that lets\nyou define the schema for your content's frontmatter (or data if it's not a\nmarkdown file). For example, here's the schema definition for this very note:\n\nI've done a decent amount of wrapping around collections to get them feeling\njust right for me. You'll see a bit of what I've done here in this next\nsection.\n\nZod is a lot handier than I expected\n\nI'm writing everything in this project in TypeScript, so having static types\nfor everything is nice. Normally, I would find myself just writing types for\neverything, like for example a query to get notes:\n\nI'd then use this as the type of the query parameter in my function, inserting\nany defaults as needed:\n\nHowever, this can get kind of tedious, as you could potentially forget to set\ndefault values for certain properties. Instead, I've been using Zod for\ndeclaring this, as I can do something really special:\n\nThat's right. I can define my static type, runtime validation, and default\nvalues in one statement. Isn't that neat?! I ended up writing a wrapping\nfunction that makes it easier to write this stuff over and over again:\n\nThis just takes in the schema I built earlier and a function that expects a\nvalidated query as input. With this, getRecentNotes becomes something simple:\n\nI get to use this pattern everywhere, don't have to think about validation, and\nI am in love. I will probably be using Zod in other projects from now on.\n\nConclusion\n\nAstro is really cool so far! I'm still figuring out some of the quirks of the\nframework, but all in all I'm quite impressed. It's been a lot easier to do\nwhat I want than I was anticipating, and I'll definitely be sticking with it\nfor the foreseeable future.\n\n[astro]: https://astro.build\n[astro-components]: https://docs.astro.build/en/basics/astro-components/\n[dataview]: https://blacksmithgu.github.io/obsidian-dataview\n[gatsby-dead]: https://github.com/gatsbyjs/gatsby/issues/38696\n[jekyll]: https://jekyllrb.com\n[react]: https://react.dev\n[svelte]: https://svelte.dev\n[zod]: https://zod.dev",
  "canonicalUrl": "https://isaaccorbrey.com/notes/astrojs-first-impressions"
}