conuko / guest-and-chat-book

Home Page:https://the-guestbook.vercel.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The Guest and Chatbook

This is a T3 Stack project bootstrapped with create-t3-app.

This project is a guestbook / twitter clone. It allows users to create, like, and comment posts.

Table of Contents

  1. Features
  2. Get Started
  3. Application Overview
  4. Architecture
  5. API Design
  6. Database
  7. Deployment
  8. Built With

Features

  • Authentication with Discord and GitHub.
  • Create, read, edit, and delete posts: You can edit a post by clicking on the post. Edit and delete are only possible on your own posts.
  • Like and unlike posts (only possible on other users posts).
  • Comment on posts (only possible on other users posts), delete comments (only the author of the comment can delete it).
  • Visit your user profile (by clicking on your username). (/user route)
  • Add an address to your profile.
  • Subscribe to a paid plan to unlock the ability to post messages (by clicking on the "Subscribe" button in the /user route). The subscription is handled by Stripe. The subscription is cancelled after 30 days. You can use the test credit card nuumber to test the subscription (see Stripe Local Setup below).

Get Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.

Prerequisites

Installation

  1. To get started, clone the repository and run npm install in the root.
  2. Copy .env.example, rename it to .env.
  3. DATABASE_URL is the connection string to your database. Just use DATABASE_URL=mysql://root:password@localhost:3306/testdb for now.
  4. For authentication paste your Discord client ID and secret in DISCORD_CLIENT_ID and DISCORD_CLIENT_SECRET (same goes for GitHub). You can get these from the Discord Developer Portal.
  5. Run npm run docker:up to start the database.
  6. Run npx prisma db push to push the schema to your database and generate the TypeScript types for the Prisma Client based on your schema. Make sure to restart the TS Server after this step so that it can detect the generated types.
  7. Run npm run db:seed to seed the database (OPTIONAL).
  8. Run npm run dev to start the development server.
  9. Install and run Stripe by following Stripe Local Setup below (OPTIONAL).
  10. Open http://localhost:3000 with your browser to see the result.
  11. Run npx prisma studio to open the Prisma Studio to view your database.
  12. Run npm run docker:down to stop the database when you’re done. This will also delete all the data in your database.

Stripe Local Setup

  1. Install the Stripe CLI by running npm install -g stripe.
  2. Run stripe login and follow the prompts to connect your Stripe account.
  3. Run npm run stripe:listen to start the Stripe CLI.
  4. In your .env file, add the following environment variables:
    • STRIPE_PK
    • STRIPE_SK
    • STRIPE_WEBHOOK_SECRET - The webhook secret provided by the Stripe CLI.
    • STRIPE_PRICE_ID - The price ID of your Stripe product.
  5. To test Stripe you can use the following test card numbers:
    • 4242 4242 4242 4242 - A successful payment.
    • For more test card numbers, refer to the Stripe documentation.

Testing

  1. Before running the tests, make sure you have the database running with npm run docker:up. Also make sure you have the database seeded with npm run db:seed.
  2. Run npm run test to run the tests.

Application Overview

libs

The libs folder contains shared libraries for mocking and testing the backend (prisma and tRPC).

prisma

The prisma schema. It contains the database schema and migrations. It also contains the seed data.

public

Static assets.

src/components/

React components.

src/env/

Validation for environment variables.

src/pages/

All the pages of the website.

src/pages/api/

Next.js API routes.

src/pages/api/auth/[...nextauth].ts

The NextAuth.js authentication slug route. This is used to authenticate users with Discord and GitHub (more providers can be added).

src/pages/api/trpc/[trpc].ts

The tRPC API entrypoint. This file is here to handle all the API requests.

src/server/

The backend, which is a tRPC server. It contains the tRPC router, context, and the prisma client.

src/server/common/get-server-auth-session.ts

A helper function to get the user session from the NextAuth.js session.

src/server/db/client.ts

The prisma client. It is used to initialize the Prisma client at global scope and to query the database.

src/server/stripe/

The Stripe API. It contains the Stripe API client and the Stripe API routes. It also contains the Stripe webhook handler. The Stripe API routes are used to create a Stripe checkout session and to retrieve the Stripe customer.

src/server/trpc/

It contains the tRPC router with the tRPC queries and mutations. The tRPC router is used to initialize the tRPC router at global scope. The tRPC router is also used to handle the tRPC queries and mutations. The tRPC queries and mutations are used to retrieve and update data in the database. The tRPC queries and mutations are also used to retrieve and update data in the Stripe API.

src/styles/*

Global CSS files, but we use Tailwind CSS for most of our styles.

src/types/*

Next Auth type declarations.

src/utils/*

Utility functions.

src/utils/trpc.ts

This file is the main front-end entrypoint to tRPC

Architecture

guestbook_flowchart

Frontend

The frontend is built with Next.js. It uses Tailwind CSS for styling. It uses tRPC for data fetching and state management. It uses NextAuth.js for authentication.

Backend

The backend is built with tRPC and Typescript. It uses Prisma as an ORM with Zod as schema validation. It uses Tanstack Query for declarative, always-up-to-date and auto-managed queries and mutations. It uses Stripe for payments. It uses NextAuth.js for authentication. It also uses Docker to quick and easy run the database locally.

The whole Next.js application is deployed at Vercel. The MySQL database is deployed at Planetscale.

tRPC

tRPC enables the creation of end-to-end typesafe APIs while eliminating code generation and runtime bloat. It takes advantage of TypeScript's excellent inference capabilities to deduce your API router's type definitions, providing complete typesafety and autocompletion when calling API procedures from your frontend.

Prisma

Prisma is a modern database toolkit. It replaces traditional ORMs and makes database access easy with an auto-generated query builder for TypeScript & Node.js. By generating types from a Prisma schema, you can use Prisma Client to access your database inside your application’s TypeScript code with guaranteed type-safety and autocompletion.

Zod

Zod is a schema validation library built on top of Typescript. Write a schema that represents a single source of truth for your data, and Zod will ensure that your data is valid throughout your application, even across network boundaries and external APIs.

Stripe

Stripe is a payment processing platform. It is used to process payments for the website.

NextAuth.js

NextAuth.js is a complete open source authentication solution for Next.js applications. It is used to authenticate users with Discord and GitHub (more providers can be added) with a complex and secure OAuth flow. NextAuth.js also provides a session management system with support for JWT and database sessions (Prisma is used for database sessions).

API Design

tRPC is used for the API. It is a typesafe API framework for TypeScript. It is used to create an API router with queries and mutations. It is also used to create an API client to call the API router from the frontend.

tRPC API Routers

post

  • Query #1: post.getAllMessages - Get all the posts.
  • Query #2: post.getAllComments - Get all comments.
  • Mutation #1: post.postMessage - Create a new post.
  • Mutation #2: post.deleteMessage - Delete a message.
  • Mutation #3: post.updateMessage - Edit a message.
  • Mutation #4: post.likeMessage - Like a message.
  • Mutation #5: post.unlikeMessage - Unlike a message.
  • Mutation #6: post.addComment - Comment on a post.
  • Mutation #7: post.deleteComment - Delete a comment.

user

  • Query #1: user.subscriptionStatus - Get the user's subscription status.
  • Query #2: user.getUserAddress - Get the user's address.
  • Mutation #1: user.addUserAddress - Create the user's address.
  • Mutation #2: user.updateUserAddress - Update the user's address.

stripe

  • Query #1: stripe.createCheckoutSession - Create a Stripe checkout session.
  • Query #2: stripe.createBillingPortalSession - Create a Stripe billing portal session.

auth

  • Query #1: auth.getSession - Get the user's session.
  • Query #2: auth.getSecretMessage - Get the secret message.

Database

The database is defined in the prisma/schema.prisma file. The Prisma Schema is the single source of truth for the database. It is used to generate the Prisma Client, which is used to access the database from the backend. It is also used to generate the TypeScript types for the database schema, which is used to access the database from the frontend.

The database is a MySQL database. It is hosted on Planet Scale.

Use Cases

For all use cases check out the API Design chapter.

Design Choices

  • I made the decision that a post can have multiple likes but one user can like one specific post just once. If the user likes the post again, the like will be removed. This is done to prevent spamming likes by one user. If a user deletes a post, all likes on that post will be deleted as well.
  • A user can only have one single address. If the user adds a new address, the old address will be overwritten. This is done to prevent spamming addresses. If a user deletes their account, the address will be deleted as well.
  • I made the decision that a user can only have one single subscription. If the user subscribes again, the old subscription will be overwritten. If a user deletes their account, the subscription will be deleted as well.
  • One or more posts can have one or more categories (many-to-many relationship). I decided to implement this many-to-many relation as an explicit m-n-relation. It consists now of two models with m-n-relation (Post and Category) and one additional model that represents the relation table of the two models (CategoriesOnPost).

guestbook-db-new

Deployment

This project is deployed on Vercel. Here is a step by step guide on how to deploy the project to Vercel:

  1. Create a new project on Vercel and link it to your GitHub repository.
  2. Add the following environment variables to your Vercel project:
    • DATABASE_URL - Your database connection string (You can use Planet Scale to get a free online MySQL database in under 5 minutes.)
    • DISCORD_CLIENT_ID - Your Discord client ID.
    • DISCORD_CLIENT_SECRET - Your Discord client secret.
    • NEXTAUTH_SECRET - A secret for NextAuth.js.
    • GITHUB_SECRET - A GitHub client secret.
    • GITHUB_ID - A GitHub client ID.
  3. Deploy your project to Vercel.
  4. Create a .env.production file in the root of your project and add the DATABASE_URL environment variable of your production database (e.g. the database url from your database hosted on Planet Scale).
  5. Run npx prisma migrate dev to to create a new migration.
  6. You can now run npm run prisma:migrate:deploy:prod to apply the latest migration to your production database.

Please refer to the Vercel documentation for more information on how to deploy your Next.js project to Vercel.

Built With

About

https://the-guestbook.vercel.app/


Languages

Language:TypeScript 96.9%Language:JavaScript 2.8%Language:CSS 0.3%