DevJournal: converting my Astro website for custom link slugs - Astro(SSR), Vercel, PlanetScale, DrizzleORM

PiyushPiyush
5 min read

Hey fellas o/. In this blog, we are going to tinker around with a new stack, something I wanted to try for quite some time. A few months ago, I created a new home for myself on the internet (yet again) - pycz.dev. It's been a long time, but I still obsess over getting a new website, and spin up a raw project with all the hyped things in the market, and take it to a drive. For this website, it was Astro. I was surprised how simple it was to scaffold and ship a project so fast, plus the DX is chef's kiss.

The source code for this blog is available on Github: https://github.com/officialpiyush/pycz.dev

When I made the website, I added some links which would redirect to my socials

I could've just embedded direct links to my socials, but I felt having pycz.dev/twitter would be more cool~. For this, I used Vercel redirect rules, which run on the edge

vercel.json configuration showing redirect rules for routes

This is how the redirect rules looked. Yeah, some sneaky regex for the GitHub redirects.

💡 The idea

Everything was cool till recently, I wanted to share a few links, and thought it would be easy if I could just dynamically update the links. This gave me the idea for creating a simple dynamic URL generation service. Taking it a step forward, I decided to integrate it with my existing Astro website.

The Stack

I made a tweet about the project and the stack I'm using, so if you forgot to follow me there, why not do it now ;). As the title says, I am planning to use Astro (w/ SSR), PlanetScale for database, DrizzleORM for connecting to the database, and our good host Vercel for hosting it. I plan on making it run on the edge.

The Process

I begin by creating a new branch for the features we are working on. I'll call it custom-slugs. After creating the branch, let's first enable SSR in Astro, it's easy, just set output option to serverand voilà 🎉 we have now enabled SSR in Astro

Next, let's quickly head to PlanetScale and create a database instance.

PlanetScale provides MySQL database, so for it, we have three options, either MySQL node driver, PlanetScale official driver, SQL ORM/ODM. I plan on hosting it on the edge, so the first option goes out of the scope. The second option looks like a good fit, but it executes direct queries, and won't be type-safe, so we move on to the third option, ORM/ODM. There are plenty in the market for SQL, like Prisma ORM, Knex QB, etc.

However, Prisma takes a lot of time to start, and is slow with joins, so, we're going to try DrizzleORM, which is pretty awesome in my opinion, because it provides better speed over Prisma, but can also integrate with the official PlanetScale driver.

Setting up the database

For this, let's create a new branch from the custom-slugs branch, and name it custom-slugs-database. Now that we have moved to a new branch, let's quickly install the dependencies:

pnpm add drizzle-orm @planetscale/database dotenv 
pnpm add -D drizzle-kit @types/node

After this is installed, I quickly created the links table in Drizzle, it was as smooth as a breeze.

export const links = mysqlTable(
  "links",
  {
    id: text("id").primaryKey().default(nanoid()),
    key: text("key"),
    parent: text("parent"),
    description: text("description"),
    url: text("url"),
    createdAt: timestamp("created_at", { fsp: 2 }).notNull().defaultNow(),
    enabled: boolean("enabled").default(true),
  },
  (links) => ({
    keyIndex: uniqueIndex("key_idx").on(links.key),
  })
);

After this, I quickly created a PR from the current branch to the custom-slugs branch - https://github.com/officialpiyush/pycz.dev/pull/4

Debugging CD errors

After I had merged the PR, I had to set up a deployment adapter, which basically means that we are telling Astro that you would be deployed on this platform, build yourself accordingly. But, after setting up the vercel edge runtime adapter, the build was still continuously failing, and ESBuild prompted me to use platform='node'on every build. It was confusing because I was not using, nor doing anything which was dependent on the node runtime, everything was supposed to be edge safe.

After a lot of debugging, I came across the root issue, it was not a direct dependency, but rather an indirect dependency of astro-icon package which was causing the build to fail. Fortunately, I was using pnpm, so I was able to quickly patch and commit the package locally to remove the underlying code which was causing the issue. It can be found in this commit - https://github.com/officialpiyush/pycz.dev/pull/5/commits/96017e19d61d452291be063124561b9ca2496fc4

Setting up the API

This section is going to be quick. I am not going to add any hi-fi authentication mechanism, just a small token based authentication to protect the route, because it would just be me using the dashboard.

Moving forward, I'll now create another git branch with custom-slugs as the base branch, and this time I will name it custom-slugs-api. After this, I'm installing the required packages, and setting up the API structure. Here is the PR for API - https://github.com/officialpiyush/pycz.dev/pull/6

Merging it all together

After merging the PR, I had to sync my schema with the database, for this, I searched a lot, but there was no direct way of doing it in Drizzle like there was in Prisma. I asked about it, and Andrew from the Drizzle team told that the feature was there, but it was in an internal testing phase. I then switched my drizzle-kit version to the version he mentioned, and voilà, it was done!

After the API, I now have to make a dashboard to manage the links, so let's move forward and do that. I won't be creating another branch for it.

While I was creating the UI, I came across a roadblock, how to manage state and call our router. I tried same path POST request, but couldn't get it to work. Fortunately, Astro has framework adapters, and we would be using Preact for our dashboard UI.

After going back and forth, I created a dead simple UI for the dashboard.

Conclusion

Overall, it was a smooth experience working with these tools. I think I would start using them in my upcoming projects, because of how powerful they are, but also because of how easy they were to set up. I'm also excited to see how DrizzleORM matures.

Source Code

The source code for this blog is available on Github: https://github.com/officialpiyush/pycz.dev and the PR can be found here - https://github.com/officialpiyush/pycz.dev/pull/5

Connect with me on Linkedin and Twitter.

12
Subscribe to my newsletter

Read articles from Piyush directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Piyush
Piyush