Skip to content
/ anon Public

A platform to share literature anonymously, built with Next.js, Typescript, Prisma, Supabase/Postgres, TailwindCSS

Notifications You must be signed in to change notification settings

stevkim/anon

Repository files navigation

Anon

Table of Contents

Table of Contents
  1. about
  2. tech stack
  3. features
  4. endpoint design

About

Anon is a platform designed for anonymous sharing of literature. It allows users to share their work without revealing their identity, creating a safe and open environment for writers to express themselves freely.

Anon is a platform that provides features similar to those of social media platforms. It allows its users to like, save, and share posts, just like they can on other social media platforms.

Tech Stack

Next JS TypeScript React Context-API Prisma Supabase TailwindCSS

Other tech

Features

  • Complete user account and user authentication process - Supabase
  • Google OAuth - Supabase
  • Custom content validation and data integrity - Prisma, Zod
  • Mutli-layer caching for improved performance - Nextjs, Tanstack Query
  • Notion-style Rich text editor - novel.sh & Tiptap
  • Custom Infinite scroll - Tanstack Query, React Hooks
  • Light/Dark theme - next-themes
  • SSR for improved performance - Nextjs
  • Custom hooks (localstorage, throttle) - React

Endpoint Design

Legend

  • Types of endpoints: GET request badge POST request badge DEL request badge
  • - flag for post if the user has liked this post
  • - flag for post if the user has saved this post
  • - authorId is set to 'author' if the user is the author

Endpoints

GET request badge - /api/auth/callback

Callback endpoint to authenticate user from an external provider (Google OAuth)
Redirects the user to /

GET request badge - /api/post?page={page}
params: { page: number }

Returns the page of posts, each page is limited to 50 posts
Page is defaulted to 0 if param doesn't exist

Return data:

  {
     id: string,
     createdAt: Date,
     content: JsonValue(object),
     likes: number,
     reports: number,
     authorId: string,
     liked?: string | null,
     saved?: string | null
  }[]

Below endpoints are only accessible to authenticated users
Request will error if authenticated user does not exist

/api/post
POST request badge - /api/post

Creates a post
Req.body:

  {
     content: JsonValue(object)
  }
  
  # JsonValue is the content value derived from tiptap/novel.sh - expected format: { type: 'doc', content: [] }

The other fields are defaulted by the database.

DEL request badge - /api/post?id={postId}
params: { id: string }

Deletes a post, must be the author of the post to delete.
Params must contain the id of the post to delete, the author and params is validated on the client-side.

/api/post/like
POST request badge - /api/post/like/[id]

Creates a like record and increments the likes field for post with postId
Return data:

  {
     id: string,
     userId: string,
     postId: string,
     createdAt: Date
  }
  
  # will revalidatePath('/', 'layout') to refetch on next reload

DEL request badge - /api/post/like/[id]?record={recordId}
params: { record: string }

Deletes the record of the like and decrements the likes field for post with postId

  # recordId is the id of the record when a user 'likes' a post

/api/post/report
POST request badge - /api/post/report/[id]

Creates a record of a report for a post
Req.body:

  {
     reason: string
  }
  
  # Reports are unique, a user may only report a unique post once. @@unique [userId, postId]
  # will revalidatePath('/', 'layout') to refetch on next reload

/api/user
GET request badge - /api/user?page={page}
params: { page: number }

Returns the page of posts that the user has created, each page is limited to 50 posts
Page is defaulted to 0 if param doesn't exist

Return data:

  {
     id: string,
     createdAt: Date,
     content: JsonValue(object),
     likes: number,
     reports: number,
     authorId: 'author',
     liked?: string | null,
     saved?: string | null
  }[] 
  # authorId is defaulted here to 'author' because all posts are expected to be the user's

/api/user/saved
GET request badge - /api/user/saved?page={page}
params: { page: number }

Returns the page of posts that the user has saved, each page is limited to 50 posts
Page is defaulted to 0 if param doesn't exist

Return data:

  {
     id: string,
     createdAt: Date,
     content: JsonValue(object),
     likes: number,
     reports: number,
     authorId: string,
     liked?: string | null,
     saved?: string | null
  }[]         

POST request badge - /api/user/saved/[id]

Creates a record for a saved post
Return data:

  {
     id: string,
     userId: string,
     postId: string,
     createdAt: Date
  }
  # saved records are unique, a user may only save a post once. @@unique [userId, postId]

DEL request badge - /api/user/saved/[id]?record={recordId}
params: { record: string }

Deletes the record of the saved post

  # recordId is the id of the record when a user 'saves' a post

About

A platform to share literature anonymously, built with Next.js, Typescript, Prisma, Supabase/Postgres, TailwindCSS

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •