I started the actual web app a while back, before I decided a developer's log was a good idea. In that case, for my first Log Entry I should write down the highlights of what has already taken place.
The first step in the project was the research into the technology needed, and how it would all play together. I knew that I wanted to use Next.js and Graphql for the app. A quick google search proved that I could use the two together easily. The other technology I decided to use was Postgres for the database layer.
With those pieces in place, I needed to research a few areas; My hosting solutions, GraphQL libraries, and User Authentication libraries.
Of these three I started with GraphGL. I needed to answer:
- What GraphQL Library works well with Next.js?
- How do I connect GraphQL to the Postgres Database?
As all developers do, I started with a google search. Most, if not all of the search results kept pointing to Apollo Graphql and Prisma. It was evident that these were the preferred solutions for Next.js. Reading a few tutorials, I learned I could use NexusJS to simplify the management of the GraphQL and Prisma schemas, and easily integrate the two.
This meant that I needed to use TypeScript. I have never really found a problem that I felt TypeScript uniquely solved. I always seem to get the impression it was forcing a solution, where there are simpler solutions available. But I can't ignore that TypeScript is growing and its adoption rate is climbing. I decided to take the chance to try it out and be able to judge fairly, after I have worked with it.
CI/CD Pipeline and Hello World
With the key pieces of tech in place, I could start building a simple hello world Next.Js application. The key to this whole project is to take small iterative steps, and make sure that there is continual progress.
Part of this first milestone would be to make sure I have a solid CI/CD pipeline. This would include:
- Listing and Code Style
- ESLint AirBnB Standard
- Prettier Formatting
- Jest Testing with React Testing Library
- Cypress.io testing for integration testing
- StoryBook.js for documentation and component development
- Semantic Release for release automation and changelings
- This would also include using conventional commits enforced with commit-lint
I use Test Driven Development with any project I work on. I want to ensure all my features work as expected any time I make a change. Being a single developer on the project, I can easily catch any bugs before they make it to production. The lint and testing tools help enforce well maintained and tested code. The automation tools like semantic release help keep my releases small and remove human error from the release process. It's just less manual work for me to do and gives me a bit of a security blanket for when I do mess up.
The setup of these tools was very straightforward and easily. The Next.js, Jest, and Storybook were well documented for setting up and integrating with Github Actions. With these in place, I just needed to figure out the hosting for the deployments.
I was initially thinking of using Heroku's Hobbyist tier, but since I was using Next.js by Vercel, I looked at their hosting tool. They had a free tier and it took me only a few clicks to setup automatic deployment of both my main branch, and all my pull requests to preview urls. This was an obvious choice.
I had my simple Next.js starter app running in production and working through the pipeline, my next steps was to create the GraphQL Hello World API.
I started with a simple endpoint that returned hardcoded data in the app. This way I knew that GraphQL and Apollo Server worked in isolation. Next, I added a basic Prisma and Nexus connection. Using example data models, I was had a end to end working application API layer. This completed my hello world app. Next is to add actual functionality.
The first step in my app was to create User Accounts and Authentication. Most folks would argue that this should be the last thing to add and they would be correct. The reason I decided to do User Auth first was because of my lack of experience. All of my app would be centered around user roles and permissions. So I needed to figure this out first, to figure out the rest of my app.
My initial requirements for an auth solution were:
- Allow for third party authorization (Google, Facebook, etc)
- Good documentation for integration with Next.js
- The Simpler to implement the better
- Make sure I can easily change auth solutions later if I need to
My first thoughts were to look at the major providers and compare their solutions. I knew of Auth0 and was recommended Firebase as potential solution. I started with AuthO, and fournd the with official NPM modules and tutorials for integrating Auth0 with Next.js.
Following the tutorials kept running into various issues and bugs since I was using Next.js v12 which had just released and was brand new. Auth0 hadn't updated their packages yet to fix these small bugs.
I saw see that I would be potentially locked into Auth0's solution, and wouldn't be able to easily refactor if I needed to. With this I pivoted to Firebase, but it had the same issue of lock-in too. Luckily, a general google search of "Next.js Authorization" pointed me to Next Auth
Reading NextAuth's documentation, I soon saw the potential. It didn't prescribe to one auth solution, and supported both Auth0, Firebase and many other authorization providers. This would allow me to easily migrate the authentication. It took care of the UI, api's and integrations with the DB as part of the package. It checked all the boxes!
I began integrating NextAuth, which was tricky at some points, but Next Auth's documentation easily led me through. I was able to easily integrate with Google OAuth, Discord OAuth, and the builtin Email SignOn. Using SendGrid for an emailer solution, I was set up for user accounts.
With this in place, I am ready to start creating the user profiles.
The user profiles were the first piece that was unique data to my application, I would have to create the profiles in the database and graphql schema. This was the first time I would need to learn Prisma Schemas, Migrations, Graphql Queries and Mutations through NexusJS.
With plenty of tutorials and readmes in my chrome tabs, I stepped through each piece of adding in the APIS for these new fields. Like all new tech, there was a lot of stumbling at first (especially figuring out TypeScript typings). Once I got through one new table and field, adding the rest to the api was easy. I now had a working user API in place. (At some point I should secure those endpoints...)
Next steps will be to add the UI to allow users to manage their profiles!