Skip to content

mxilia/Quonet-frontend

Repository files navigation

Quonet

A forum web application that allows users to create, delete, and like or dislike posts. Users can also update their profile information, including their username and bio. The platform supports content moderation through an admin dashboard.

Alt text

typescript Go AWS Redis PostgreSQL Supabase TailwindCSS Next.js

πŸ“ Repositories

πŸ“„ Summary

The frontend is built with Next.js following Bulletproof Architecture, leveraging server-side rendering for fast initial page loads, TanStack for client-side caching, and Zustand for centralized state management.

Backend is built with Go using Clean Architecture and implements a RESTful API with Fiber v2. PostgreSQL is used for data persistence via GORM, Redis handles rate limiting, and images are stored using Supabase.

πŸ’» Tech Stack

  • Frontend: Next.js, ShadCN, Tailwind CSS, Zod, TanStack, Zustand
  • Backend: Go, Fiber, GORM, PostgreSQL, Redis
  • Service: AWS, Supabase

πŸš€ Getting started

Prerequisites

  • Node.js (v18 or later)
  • npm

Setting up

Run this to clone project:

git clone https://github.com/mxilia/Quonet-frontend.git

After that make sure your current directory is at the root of this project.

cd Quonet-frontend

Run this to download dependencies:

npm install

Environment Variables

Here is the variable list example:

DEV=true

NEXT_PUBLIC_API_URL=http://localhost:8000/api/v2
NEXT_PUBLIC_APP_URL=http://localhost:3000

Write your own values for corresponding variables.

Usage

To run this project, execute:

npm run dev

And there you go, the frontend is up and running.

🧱 Project Structure

.
β”œβ”€β”€ .vscode/
β”‚   └── settings.json
β”œβ”€β”€ assets/
β”‚   └── quonet_page.png
β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ blue-chat.png
β”‚   β”œβ”€β”€ comment-icon.png
β”‚   β”œβ”€β”€ default-avatar.png
β”‚   β”œβ”€β”€ favicon.ico
β”‚   β”œβ”€β”€ feeds-icon.png
β”‚   β”œβ”€β”€ google-logo.png
β”‚   β”œβ”€β”€ home-icon.png
β”‚   β”œβ”€β”€ logo.svg
β”‚   └── settings-icon.png
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”‚   β”œβ”€β”€ not-found.tsx
β”‚   β”‚   β”œβ”€β”€ provider.tsx
β”‚   β”‚   β”œβ”€β”€ (group)/
β”‚   β”‚   β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ loading.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ admin/
β”‚   β”‚   β”‚   β”‚   └── dashboard/
β”‚   β”‚   β”‚   β”‚       └── page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ feed/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ loading.tsx
β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ posts/
β”‚   β”‚   β”‚   β”‚   └── [id]/
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ loading.tsx
β”‚   β”‚   β”‚   β”‚       └── page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ settings/
β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ threads/
β”‚   β”‚   β”‚   β”‚   └── [id]/
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ loading.tsx
β”‚   β”‚   β”‚   β”‚       └── page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ users/
β”‚   β”‚   β”‚   β”‚   └── [id]/
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ loading.tsx
β”‚   β”‚   β”‚   β”‚       └── page.tsx
β”‚   β”‚   β”‚   └── _components/
β”‚   β”‚   β”‚       β”œβ”€β”€ create-post-tab.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ navbar-layout.tsx
β”‚   β”‚   β”‚       └── skeletons/
β”‚   β”‚   β”‚           └── create-post-tab-skeleton.tsx
β”‚   β”‚   └── login/
β”‚   β”‚       β”œβ”€β”€ layout.tsx
β”‚   β”‚       β”œβ”€β”€ page.tsx
β”‚   β”‚       └── _components/
β”‚   β”‚           └── redirect-button.tsx
β”‚   β”œβ”€β”€ assets/
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ errors/
β”‚   β”‚   β”‚   └── main.tsx
β”‚   β”‚   β”œβ”€β”€ layouts/
β”‚   β”‚   └── ui/
β”‚   β”‚       β”œβ”€β”€ background/
β”‚   β”‚       β”‚   └── blur-background.tsx
β”‚   β”‚       β”œβ”€β”€ dropdown/
β”‚   β”‚       β”‚   └── dropdown-menu.tsx
β”‚   β”‚       β”œβ”€β”€ form/
β”‚   β”‚       β”‚   β”œβ”€β”€ error.tsx
β”‚   β”‚       β”‚   β”œβ”€β”€ field-wrapper.tsx
β”‚   β”‚       β”‚   β”œβ”€β”€ form.tsx
β”‚   β”‚       β”‚   β”œβ”€β”€ input.tsx
β”‚   β”‚       β”‚   β”œβ”€β”€ label.tsx
β”‚   β”‚       β”‚   β”œβ”€β”€ select.tsx
β”‚   β”‚       β”‚   └── textarea.tsx
β”‚   β”‚       β”œβ”€β”€ image-frame/
β”‚   β”‚       β”‚   └── image-frame.tsx
β”‚   β”‚       β”œβ”€β”€ notification/
β”‚   β”‚       β”‚   β”œβ”€β”€ notification.store.ts
β”‚   β”‚       β”‚   └── notification.tsx
β”‚   β”‚       └── skeleton/
β”‚   β”‚           └── skeleton.tsx
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ env.ts
β”‚   β”‚   └── path.ts
β”‚   β”œβ”€β”€ features/
β”‚   β”‚   β”œβ”€β”€ announcements/
β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ create-announcement.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ delete-announcement.ts
β”‚   β”‚   β”‚   β”‚   └── get-announcements.ts
β”‚   β”‚   β”‚   └── components/
β”‚   β”‚   β”‚       β”œβ”€β”€ announcement-box.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ announcements-list.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ create-announcement.tsx
β”‚   β”‚   β”‚       └── skeletons/
β”‚   β”‚   β”‚           β”œβ”€β”€ announcement-box-skeleton.tsx
β”‚   β”‚   β”‚           └── announcements-list-skeleton.tsx
β”‚   β”‚   β”œβ”€β”€ comments/
β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ create-comment.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ delete-comment.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-comment.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-comments.ts
β”‚   β”‚   β”‚   β”‚   └── update-comment.ts
β”‚   β”‚   β”‚   └── components/
β”‚   β”‚   β”‚       β”œβ”€β”€ comments-list.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ comments.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ create-comment.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ delete-comment.tsx
β”‚   β”‚   β”‚       └── update-comment.tsx
β”‚   β”‚   β”œβ”€β”€ likes/
β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ create-like.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ delete-like.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-like.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-like-count.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-like-state.ts
β”‚   β”‚   β”‚   β”‚   └── get-likes.ts
β”‚   β”‚   β”‚   └── components/
β”‚   β”‚   β”‚       β”œβ”€β”€ like-button.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ like-counter.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ like-modify.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ likes-list.tsx
β”‚   β”‚   β”‚       └── likes.tsx
β”‚   β”‚   β”œβ”€β”€ posts/
β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ create-post.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ delete-post.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-post.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-posts.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-private-post.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-private-posts.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-top-liked-posts.ts
β”‚   β”‚   β”‚   β”‚   └── update-post.ts
β”‚   β”‚   β”‚   └── components/
β”‚   β”‚   β”‚       β”œβ”€β”€ configure-post.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ create-post.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ delete-post.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ full-post.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ medium-post.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ posts-list.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ private-posts.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ private-posts-list.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ small-post.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ top-liked-post-list.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ update-post.tsx
β”‚   β”‚   β”‚       └── skeletons/
β”‚   β”‚   β”‚           β”œβ”€β”€ full-post-skeleton.tsx
β”‚   β”‚   β”‚           β”œβ”€β”€ medium-post-skeleton.tsx
β”‚   β”‚   β”‚           β”œβ”€β”€ posts-list-skeleton.tsx
β”‚   β”‚   β”‚           β”œβ”€β”€ small-post-skeleton.tsx
β”‚   β”‚   β”‚           └── top-liked-posts-list-skeleton.tsx
β”‚   β”‚   β”œβ”€β”€ threads/
β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ create-thread.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ delete-thread.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ get-thread.ts
β”‚   β”‚   β”‚   β”‚   └── get-threads.ts
β”‚   β”‚   β”‚   └── components/
β”‚   β”‚   β”‚       β”œβ”€β”€ create-thread.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ delete-thread.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ full-thread.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ select-thread.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ small-thread.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ threads.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ threads-list.tsx
β”‚   β”‚   β”‚       └── skeletons/
β”‚   β”‚   β”‚           β”œβ”€β”€ full-thread-skeleton.tsx
β”‚   β”‚   β”‚           β”œβ”€β”€ small-thread-skeleton.tsx
β”‚   β”‚   β”‚           └── threads-list-skeleton.tsx
β”‚   β”‚   └── users/
β”‚   β”‚       β”œβ”€β”€ api/
β”‚   β”‚       β”‚   β”œβ”€β”€ delete-user.ts
β”‚   β”‚       β”‚   β”œβ”€β”€ get-user.ts
β”‚   β”‚       β”‚   β”œβ”€β”€ get-users.ts
β”‚   β”‚       β”‚   └── update-user.ts
β”‚   β”‚       └── components/
β”‚   β”‚           β”œβ”€β”€ admin-users-list.tsx
β”‚   β”‚           β”œβ”€β”€ delete-user.tsx
β”‚   β”‚           β”œβ”€β”€ full-user.tsx
β”‚   β”‚           β”œβ”€β”€ small-user.tsx
β”‚   β”‚           β”œβ”€β”€ update-user-bio.tsx
β”‚   β”‚           β”œβ”€β”€ update-user-handler.tsx
β”‚   β”‚           β”œβ”€β”€ update-user-role.tsx
β”‚   β”‚           └── skeletons/
β”‚   β”‚               β”œβ”€β”€ full-user-skeleton.tsx
β”‚   β”‚               β”œβ”€β”€ small-user-skeleton.tsx
β”‚   β”‚               └── users-list-skeleton.tsx
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”œβ”€β”€ api-client.ts
β”‚   β”‚   β”œβ”€β”€ auth.ts
β”‚   β”‚   β”œβ”€β”€ authorization.ts
β”‚   β”‚   β”œβ”€β”€ react-query.ts
β”‚   β”‚   β”œβ”€β”€ redirect-client.ts
β”‚   β”‚   └── utils.ts
β”‚   β”œβ”€β”€ styles/
β”‚   β”‚   └── globals.css
β”‚   β”œβ”€β”€ types/
β”‚   β”‚   └── api.ts
β”‚   └── utils/
β”‚       β”œβ”€β”€ debounce.ts
β”‚       └── format.ts
β”œβ”€β”€ .env
β”œβ”€β”€ .env.example
β”œβ”€β”€ .env.production
β”œβ”€β”€ .gitignore
β”œβ”€β”€ .prettierignore
β”œβ”€β”€ .prettierrc
β”œβ”€β”€ components.json
β”œβ”€β”€ eslint.config.mjs
β”œβ”€β”€ LICENSE
β”œβ”€β”€ next-env.d.ts
β”œβ”€β”€ next.config.ts
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ package.json
β”œβ”€β”€ postcss.config.mjs
β”œβ”€β”€ README.md
└── tsconfig.json

About

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors