TL;DR: I built Tourgether, the social network for hiking, in the last month to participate in the recent Hackathon from PlanetScale and Hashnode. In this post I describe some of my decisions and key learnings. Check out the code on Github.
I love hiking! I live in Germany, so the alps are not too far away from home. The best parts about hiking is being in the nature and also to spend time with friends. One day on a hiking trip we had the idea to build the social network of hiking. We wanted a way to keep track of our tours and all the peaks we climbed. Further we would love to see our stats and compare and compete with our friends. The idea for Tourgether was born!
The main features for the application are:
- Uploading tours, including some stats of the tour and which peaks where climbed
- Add a GPS track of the tour
- View the tour on the map and show some graphs like height and speed profiles
- Connect with your friends to view their tours, give them likes or comments
- Discover different peaks and public tours of other users
First of all I had to pick my technology stack of choice. I am currently learning Typescript so the obvious choice for me was React. After doing some research I found a pretty interesting stack called the T3-Stack. It uses the following technologies:
- NextJS as a framework for the frontend as well as the backend
- tRPC which allows me to make type-safe API calls (this library is awesome!)
- Prisma as my ORM to talk to the PlanetScale database
- NextAuth which makes integrating authentication a charm
- Tailwind as a styling framework on the frontend side, as I am not a CSS expert 😎
This stack is pretty much all I need on the infrastructure side and is pretty easy to get started on:
Before diving into the coding I wanted to model my database schema. This helps me to get a overview of all the entities in my project and how they interact with each other. The first sketch looked like this:
Let's have a look on some key aspects. The core entity is the Tour. A User can have many Tours, but a Tour does always belong to a single User. Users can also Comment on tours or give them a Like. You can link a Tour with one or more Peaks. This way I can determine which User has climbed which Peaks. A User can mark peaks for his wish list. I modeled this with the WishlistItem entity. Finally, the User Entity is also connected to itself. This is the way of creating the friendship relation between users. This data model is not complete but gives a insight into the solution I am going to build.
Auth is hard. At least if you are trying to implement it yourself (which you shouldn't do btw.). Fo this reason I decided to use an existing authentication provider. My choice fell on Auth0, because it has a free tier and is very widely used. The T3 stack already comes with the NextAuth library, which makes it very easy to connect to Auth0. Using this library was so incredibly easy!
tRPC for type-safe communication
As an option within create-t3-app, there is a library called tRPC. I did not know this package before, but I loved it instantly when I first tried it out. The idea is simple: make API calls feel like you are calling any other TypeScript function. This means that our IDE knows exactly what input and output types the function needs.
tRPC allows you to easily build & consume fully typesafe APIs, without schemas or code generation.
tRPC is a bit hard to explain, so make sure to check out their website for some compelling examples!
I want to give the users the ability to upload the GPS tracks of their tour, as well as images. To achieve this, I needed a solution for my file storage. I just could put these files into the database, but this bloats the size of the db too much. For this reason I chose Amazons S3 service as my storage solution.
S3 stands for Simple Storage Service and is a service inside AWS (Amazon Web Services). S3 provides the ability to upload files and organize them in different folders. Using Amazons SDK it is also quite easy to integrate. After uploading the files to the storage service I am simply storing the files URL in the database for later access.
What I learned
By building this project I learned a lot of new stuff. Let's start with the tech stack. Before starting this application I had very limited knowledge of React. TypeScript, NextJS, Prisma and PlanetScale were completely new to me. Building real life apps like this is the best way to learn new technologies. I have to say I really loved this stack. Especially the combination of Prisma and tRPC make it so easy to fetch data from the API. You feel so productive!
Further I learned something about how social networks are built. I learned that the data models can be quite complex and that querying the correct data for the user is not an easy task. My biggest pain point was the Feed page and to figure out, which data should be displayed for the current user.
All in all I would call this project a big success for myself. I am confident to tackle other projects in TypeScript or NextJS in the future. I would definitely suggest everyone to try the T3 stack in your next project.
Todos for the future
While the app itself is in a pretty good state, there are some points I would like to tackle in the future.
First I want to integrate a mailing service. On the one hand I would like to send transactional mails like New Friend Request or New comment. Some marketing mails with a weekly newsletter of new exciting tours would be nice to have.
Furthermore I would love to have the ability to plan tours before walking them. This involves routing on a map from A to B as well as estimating the time, distance and difficulty. There already are some solutions that do something similar like Brouter. Integrating a solution like this would add a lot of value to the app.
Building this app was a lot of fun. It is absolutely great to see what you can build in just one month. Modern solutions like PlanetScale, Vercel and AWS can really help you to build complex solutions. This is especially true as a single developer.