What is Heaust?
I'd say my family is pretty traditional β we usually do the holiday family gatherings and other annual celebrations too. Time and time again, I see the issue of not knowing who was supposed to bring what to these events, caused by clear miscommunication that could've been averted. I wanted to build something to help my family since we host a lot of gatherings but realized this could actually help more people. I'm building Heaust
β a simple way to keep track of guests and what they bring to your next event. Simply create an event, share it with others, and view who all is coming and if they're bringing something!
The Tech Stack
Routing
You'll have to excuse my background in web development; my existing knowledge stems from static HTML sites straight to React so I never really heard about nested routes until now! Nested routing allows you to render components under a specific URL. That's how the web works currently but nested routes take it to another level β especially when it comes to dynamic data.
With nested routes, I can render a modal or a drawer by going to a specific URL! In this case, when someone goes to
/events/new
, a drawer pops out allowing them to create a new event; I find this to be so dope!
I really like nested routes because it gets me thinking about layout more than individual pages. Might sound weird but here's what I mean. For Heaust, there are multiple events, of course, but there are two main components to each event page: details and activity. Instead of worrying about rendering them both at the same time or having client-side state, I can take advantage of nested routing to conditionally render that specific UI.
Here's what it looks like: /events/event-id/details
renders only the details page and /events/event-id/activity
only renders the activity page. What's great about this approach is that all routes are server-side rendered so I can add authentication logic to block off requests to certain routes! This also means my queries live where my UI lives, which is colocation (a term I've recently learned and like a lot). All this talk about routes and queries is a perfect segue into the next piece we all know and love, data fetching!
Data Fetching
Simply put, Remix gives you a loader
function where you can run whatever queries and business logic you need, on the server. You then consume your data on the client with a nice hook Remix gives to you called useLoaderData()
. Combine this with nested routes and you'll only fetch data for that particular route.
Navigating to
/events/event-id/details
will only fetch data for the details page and never the activity page β this is major!
Prisma
I'm so glad Prisma is a thing; SQL and I don't necessarily match so it's nice that I can execute SQL queries from a type-safe API! I've never heard of an ORM (object-relational mapping) until Prisma but through building queries and mutations, I have a better understanding of what that really means. What's interesting is my Prisma schema would have more fields than what my PlanetScale database has (image below) and that confused me at first but then I realized that Prisma handles the relationships that you specify (hence, the term ORM and my low SQL knowledge).
PlanetScale
Who would've thought I'd break the hold Firebase had on me and start using a SQL database again?! I've been wanting to try the infamous Prisma-PlanetScale combo for a while now and I'm glad I finally tried it out! PlanetScale is dope because it brings familiar git concepts (branching and pull requests) into the realm of databases. With a free account, you get 3 branches for your project and this is pretty nice because you can use them for your main
branch, a shadow
branch (I'm still learning it's purpose), and the 3rd would be for your deploy requests (like pull requests but for your database schema) so you can easily test out changes.
Here's a nice walkthrough of working with Prisma and PlanetScale.
Some Cool Nuggets
- Remix fetches all assets and bundles for only the nested routes that are being used. For example, with the following file structure:
routes/
events/
$id.tsx
new.tsx
events.tsx
index.tsx
When navigating to /events/new
, Remix will run the loaders (data fetching) for both /events
and /events/new
.
- You know how the
useState
hook is for keeping track of data in React applications? Apparently, the web already does this for you...withFormData
. Simply add aname
attribute to your<input />
and you can access it's value like so:
const body = new FormData(form);
const email = body.get("email");
BTW, Remix does a good job of this when submitting forms in your routes.
- Prisma queries allow you to
include
relations in what is returned to you! Kinda reminds me of GraphQL, how you can structure the response to your specific needs.
Final Thoughts
Using this tech stack for Heaust has been really fun and insightful! This stack allows me to move more freely and quickly so I can cut down on engineering time, which is always a plus! My plan of action with Heaust is to make it mobile responsive and do a little bit of touching up so it has a dope UX (framer-motion might help with this) before I launch it. If you want to know when Heaust goes live, let me know!
Hopefully this was a good read and provided some value to you! Be sure to follow me on Twitter for more nuggets!