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.
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.
- Frontend: Next.js, ShadCN, Tailwind CSS, Zod, TanStack, Zustand
- Backend: Go, Fiber, GORM, PostgreSQL, Redis
- Service: AWS, Supabase
- Go 1.25.2
- Docker
- Docker Compose
Run this to clone project:
git clone https://github.com/mxilia/Quonet-backend.gitAfter that make sure your current directory is at the root of this project.
cd Quonet-backendRun this to download Go package:
go mod downloadMake sure you use .env.dev when development and .env.production in production. Here is the variable list example:
ENV={dev or production}
DOMAIN=localhost
DB_HOST=localhost
DB_PORT=5432
DB_NAME=db_name
DB_USER=db_user
DB_PASSWORD=db_password
OWNER_EMAIL=xyz@email.com
OWNER_HANDLER=owner_handler
JWT_SECRET=nono22
FRONTEND_URL=https://localhost:3000
FRONTEND_OAUTH_REDIRECT_URL=http://localhost:3000
GOOGLE_CLIENT_ID=4567.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=4567
GOOGLE_OAUTH_REDIRECT_URL=http://localhost:8000/auth/google/callback
SUPABASE_URL=
SUPABASE_KEY=
BUCKET_NAME=
REDIS_ADDR=http://localhost:0000
REDIS_PASSWORD=Write your own values for corresponding variables.
To run this project, you need to first open Docker Desktop then after that run this in terminal:
docker compose up --buildThen after that run:
go run cmd/app/main.goAnd there you go, the backend is up and running.
π /internal/app/server.go
6 | db, storage, _, rateLimiter, cfg, err := setupDependencies(CURRENT_ENV)
Make sure to replace CURRENT_ENV according to your environment:
- Set
CURRENT_ENV = "production"for a production environment. - Set
CURRENT_ENV = "dev"for a development environment.
.
βββ .github
β βββ workflows
β βββ cicd.yml
βββ .vscode
β βββ settings.json
βββ cmd
β βββ app
β βββ main.go
βββ internal
β βββ app
β β βββ app.go
β β βββ server.go
β βββ announcement
β β βββ dto
β β β βββ mapper.go
β β β βββ request.go
β β β βββ response.go
β β βββ handler
β β β βββ rest
β β β βββ handler.go
β β βββ repository
β β β βββ announcement_repository.go
β β β βββ gorm_announcement_repository.go
β β βββ usecase
β β βββ interface.go
β β βββ usecase.go
β βββ comment
β β βββ dto
β β β βββ mapper.go
β β β βββ request.go
β β β βββ response.go
β β βββ handler
β β β βββ rest
β β β βββ handler.go
β β βββ repository
β β β βββ comment_repository.go
β β β βββ gorm_comment_repository.go
β β βββ usecase
β β βββ interface.go
β β βββ usecase.go
β βββ entities
β β βββ announcement.go
β β βββ comment.go
β β βββ like.go
β β βββ post.go
β β βββ session.go
β β βββ thread.go
β β βββ user.go
β βββ like
β β βββ dto
β β β βββ mapper.go
β β β βββ request.go
β β β βββ response.go
β β βββ handler
β β β βββ rest
β β β βββ handler.go
β β βββ repository
β β β βββ like_repository.go
β β β βββ gorm_like_repository.go
β β βββ usecase
β β βββ interface.go
β β βββ usecase.go
β βββ post
β β βββ dto
β β β βββ mapper.go
β β β βββ request.go
β β β βββ response.go
β β βββ handler
β β β βββ rest
β β β βββ handler.go
β β βββ repository
β β β βββ post_repository.go
β β β βββ gorm_post_repository.go
β β βββ usecase
β β βββ interface.go
β β βββ usecase.go
β βββ session
β β βββ dto
β β β βββ mapper.go
β β β βββ request.go
β β β βββ response.go
β β βββ handler
β β β βββ rest
β β β βββ handler.go
β β βββ repository
β β β βββ session_repostiory.go
β β β βββ gorm_session_repository.go
β β βββ usecase
β β βββ interface.go
β β βββ usecase.go
β βββ thread
β β βββ dto
β β β βββ mapper.go
β β β βββ request.go
β β β βββ response.go
β β βββ handler
β β β βββ rest
β β β βββ handler.go
β β βββ repository
β β β βββ thread_repository.go
β β β βββ gorm_thread_repository.go
β β βββ usecase
β β βββ interface.go
β β βββ usecase.go
β βββ transaction
β β βββ interface.go
β β βββ gorm_tx_manager.go
β βββ user
β βββ dto
β β βββ mapper.go
β β βββ request.go
β β βββ response.go
β βββ handler
β β βββ rest
β β βββ handler.go
β βββ repository
β β βββ user_repository.go
β β βββ gorm_user_repository.go
β βββ usecase
β βββ interface.go
β βββ usecase.go
βββ pkg
β βββ apperror
β β βββ apperror.go
β βββ config
β β βββ config.go
β βββ database
β β βββ db.go
β β βββ storage.go
β βββ middleware
β β βββ fiber.go
β β βββ jwt.go
β β βββ require_admin.go
β β βββ rate_limit
β β βββ key.go
β β βββ policy.go
β β βββ rate_limit.go
β βββ redisclient
β β βββ client.go
β β βββ kv.go
β βββ responses
β β βββ error_response.go
β β βββ message_response.go
β βββ routes
β β βββ not_found_route.go
β β βββ private_routes.go
β β βββ public_routes.go
β βββ token
β βββ claims.go
β βββ jwt_maker.go
βββ utils
β βββ format
β βββ format.go
βββ .dockerignore
βββ .env.dev
βββ .env.example
βββ .env.production
βββ .gitignore
βββ docker-compose.yml
βββ Dockerfile
βββ go.mod
βββ go.sum
βββ LICENSE
βββ README.md
| Route | Auth Requirement | Params | Description |
| GET /me | Authenticated | - | Returns current user's info. |
| GET /auth/google/login | Public | - | Redirects user to Google OAuth Page. |
| GET /auth/google/callback | Public | - | Handles Google OAuth callback. |
| POST /auth/logout | Authenticated | - | Delete current user's session. |
| GET /threads | Public | title, page | Returns threads that match params. |
| GET /threads/:id | Public | id | Returns a thread with specified id. |
| POST /threads | Admin | - | Creates a new thread. |
| DELETE /threads/:id | Admin | - | Delete a thread with specified id. |
| PATCH /sessions/:email | Admin | Patch a session with specified id. | |
| GET /users | Public | - | Returns all users. |
| GET /users/:id | Public | id | Returns a user with specified id. |
| GET /users/handler/:handler | Public | handler | Returns a user with specified handler. |
| GET /users/email/:email | Public | Returns a user with specified email. | |
| PATCH /users/:id | Authenticated | - | Update user with specified id. |
| DELETE /users/:id | Authenticated | - | Delete user with specified id. |
| GET /posts | Public | page, author_id, thread_id, title | Returns posts that match params. |
| GET /posts/:id | Public | id | Returns a post with specified id. |
| GET /posts/top/like | Public | limit | Returns a limited number of posts sorted by like count in descending order. |
| GET /posts/private | Authenticated | page, author_id, thread_id, title | Returns private posts that match params. |
| GET /posts/private/:id | Authenticated | id | Returns a private post with specified id. |
| POST /posts | Authenticated | - | Creates a new post. |
| PATCH /posts/:id | Authenticated | id | Update a post with specified id. |
| DELETE /posts/:id | Authenticated | id | Delete a post with specified id. |
| GET /likes | Public | page, parent_type, owner_id, parent_id | Returns likes that match params. |
| GET /likes/:id | Public | id | Returns a like with specified id. |
| GET /likes/attributes/count | Public | parent_type, parent_id, owner_id | Return a list of number representing entities' like count that match params. |
| GET /likes/attributes/state | Authenticated | parent_type, parent_id | Return current user like state for the given parent. |
| POST /likes | Authenticated | - | Create a new like. |
| GET /comments | Public | root_id, parent_id, owner_id | Returns comments that match params. |
| GET /comments/:id | Public | id | Returns a comment with specified id. |
| POST /comments | Authenticated | - | Create a new comment. |
| PATCH /comments/:id | Authenticated | - | Update a comment with specified id. |
| DELETE /comments/:id | Authenticated | - | Delete a comment with specified id. |
| GET /announcements | Public | page | Returns announcements that match params. |
| POST /announcements | Admin | - | Create a new announcement. |
| DELETE /announcements | Admin | id | Delete an announcement with specified id. |
