Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4e73a85
feat: update user table to prep for guest into full user pathway
dann-huang Jul 7, 2025
cd0ec8b
feat: add guest registerationw ith user names
dann-huang Jul 7, 2025
fbe4472
refactor: removed username/password login
dann-huang Jul 7, 2025
b5e213c
refactor: make last log in not optional
dann-huang Jul 7, 2025
c2a37da
feat: added guest account upgrade path via verifying email. Added res…
dann-huang Jul 7, 2025
65fc184
feat: added endpoint for adding password, also better format access-l…
dann-huang Jul 7, 2025
132dedd
chore: complete rename project
dann-huang Jul 10, 2025
6ba6471
feat: first draft on new landing page
dann-huang Jul 11, 2025
3efddd6
refactor: particle banner to be less bulky
dann-huang Jul 11, 2025
73f9dab
feature: particle banner now properly updates with theme
dann-huang Jul 11, 2025
3208683
feat: add logo and make landing page use it
dann-huang Jul 11, 2025
f9c0834
feat: better mobile nav bar
dann-huang Jul 11, 2025
6b4fa7e
feat: hero section for landing page
dann-huang Jul 11, 2025
88d2bcd
feat: fixed resizing on particleBanner via simply re-parsing on resize.
dann-huang Jul 11, 2025
9ffa362
refactor: standardized all custom hooks to be default exports, and mo…
dann-huang Jul 11, 2025
0efd1a9
WIP: bringing useUserStore up to date with auth package
dann-huang Jul 11, 2025
3023e7f
feat: fully furnished (hopefully) backend auth routes
dann-huang Jul 12, 2025
c26d555
refactor: hopefully have backend auth routes better structured
dann-huang Jul 12, 2025
9dd0c41
refactor: moved all token storing logic to KVManager. Also change use…
dann-huang Jul 12, 2025
e05d4c4
feat: guest user now only need to choose 1 name
dann-huang Jul 12, 2025
f071cfd
feat: corresponding methods on front end. Also refactored backend to …
dann-huang Jul 14, 2025
641593d
feat: added guest login for front end
dann-huang Jul 14, 2025
11c4423
feat: guest log in and live chat now working
dann-huang Jul 14, 2025
79ba9e0
fix: various broken hooks due to default imports, particle box blocki…
dann-huang Jul 14, 2025
38fa574
chore: update readme
dann-huang Jul 14, 2025
52df349
chore: update readme again
dann-huang Jul 14, 2025
cd78b8f
refactor: various linting issues
dann-huang Jul 14, 2025
ed9b82e
style: reduce overly large square
dann-huang Jul 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# These are probably fine
POSTGRES_DB=letsgo
POSTGRES_DB=gonext
NODE_ENV=development

# Maybe change these
JWT_ACCESS_SECRET=SneakySecret
POSTGRES_USER=pgUser
POSTGRES_PASSWORD=pgPass

# Production only
DOCKERHUB_NAME=
RESEND_KEY=
MAIL_FROM=

# Will be overridden by deploy script
TAG=latest
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/build-n-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ jobs:
file: ./frontend/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_NAME }}/letsgo-frontend:${{ steps.tag.outputs.version }}
${{ secrets.DOCKERHUB_NAME }}/letsgo-frontend:latest
${{ secrets.DOCKERHUB_NAME }}/gonext-frontend:${{ steps.tag.outputs.version }}
${{ secrets.DOCKERHUB_NAME }}/gonext-frontend:latest

- name: Build and push backend
uses: docker/build-push-action@v5
Expand All @@ -38,8 +38,8 @@ jobs:
file: ./backend/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_NAME }}/letsgo-backend:${{ steps.tag.outputs.version }}
${{ secrets.DOCKERHUB_NAME }}/letsgo-backend:latest
${{ secrets.DOCKERHUB_NAME }}/gonext-backend:${{ steps.tag.outputs.version }}
${{ secrets.DOCKERHUB_NAME }}/gonext-backend:latest

deploy:
needs: build
Expand Down Expand Up @@ -85,13 +85,13 @@ jobs:

echo "Cleaning up old deployment..."
docker compose -f docker-compose.yml down --remove-orphans || true
docker compose -p letsgo-prod -f docker-compose.prod.yml down --remove-orphans || true
docker compose -p gonext-prod -f docker-compose.prod.yml down --remove-orphans || true

echo "Pulling images..."
docker compose -p letsgo-prod -f docker-compose.prod.yml pull || { echo "❌ Docker compose pull failed"; exit 1; }
docker compose -p gonext-prod -f docker-compose.prod.yml pull || { echo "❌ Docker compose pull failed"; exit 1; }

echo "Docker composing..."
docker compose -p letsgo-prod -f docker-compose.prod.yml up -d --remove-orphans || {
docker compose -p gonext-prod -f docker-compose.prod.yml up -d --remove-orphans || {
echo "❌ Deployment failed"
if ! grep -q "^LAST_WORKING_TAG=" .env; then
echo "⚠️ No last working version"
Expand All @@ -101,7 +101,7 @@ jobs:
echo "Rolling back to last working version: $LAST_WORKING"
git checkout $LAST_WORKING
sed -i "s/^TAG=.*/TAG=$LAST_WORKING/" .env
docker compose -p letsgo-prod -f docker-compose.prod.yml up -d --remove-orphans
docker compose -p gonext-prod -f docker-compose.prod.yml up -d --remove-orphans
exit 1
}

Expand All @@ -121,7 +121,7 @@ jobs:
echo "Rolling back to last working version: $LAST_WORKING"
git checkout $LAST_WORKING
sed -i "s/^TAG=.*/TAG=$LAST_WORKING/" .env
docker compose -p letsgo-prod -f docker-compose.prod.yml up -d --remove-orphans
docker compose -p gonext-prod -f docker-compose.prod.yml up -d --remove-orphans
exit 1
fi
echo "Health check attempt $i failed, retrying in 10s..."
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v4

- name: Build frontend Docker image
run: docker build -t letsgo-frontend:test ./frontend
run: docker build -t gonext-frontend:test ./frontend

backend:
runs-on: ubuntu-latest
Expand All @@ -21,4 +21,4 @@ jobs:
- uses: actions/checkout@v4

- name: Build backend Docker image
run: docker build -t letsgo-backend:test ./backend
run: docker build -t gonext-backend:test ./backend
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# LetsGo: A Real-time Full-Stack Web Application
# GoNext: A Real-time Full-Stack Web Application based on Go and Next.js

[![GitHub Actions CI Status](https://github.com/dann-huang/letsGo/actions/workflows/pr-checks.yml/badge.svg)](https://github.com/dann-huang/letsGo/actions/workflows/pr-checks.yml)
[![GitHub Actions Deployment Status](https://github.com/dann-huang/letsGo/actions/workflows/build-n-deploy.yml/badge.svg)](https://github.com/dann-huang/letsGo/actions/workflows/build-n-deploy.yml)
[![GitHub Actions CI Status](https://github.com/dann-huang/gonext/actions/workflows/pr-checks.yml/badge.svg)](https://github.com/dann-huang/gonext/actions/workflows/pr-checks.yml)
[![GitHub Actions Deployment Status](https://github.com/dann-huang/gonext/actions/workflows/build-n-deploy.yml/badge.svg)](https://github.com/dann-huang/gonext/actions/workflows/build-n-deploy.yml)

LetsGo is a personal project and portfolio piece showcasing a full-stack web application designed for interactive, real-time experiences. It highlights expertise in modern backend (Go), frontend (Next.js), and robust containerized deployment with Docker, Nginx, PostgreSQL, and Redis.
GoNext is a personal project and portfolio piece showcasing a full-stack web application designed for interactive, real-time experiences. It highlights expertise in modern backend (Go), frontend (Next.js), and robust containerized deployment with Docker, Nginx, PostgreSQL, and Redis.

**Live Demo:** [https://daniel-h.ca](https://daniel-h.ca) (If actively deployed and available)

Expand Down Expand Up @@ -31,21 +31,24 @@ This project emphasizes real-time interactivity and robust architecture, demonst

* **Full-Stack Architecture:** A high-performance Go backend seamlessly integrated with a modern, reactive Next.js and TypeScript frontend.
* **Real-time Communication:** Custom WebSocket implementations power all interactive features.
* **Live Chat:** Instant, real-time text communication between users.
* **Text Chat:** Instant, real-time text communication between users.
* **Video Chat:** Integrating WebRTC for peer-to-peer video communication.
* **Collaborative Drawing Canvas:** A shared, interactive canvas where multiple users can draw together in real-time.
* **Singleplayer Games:** Currently just minesweeper, but more to come!
* **Multiplayer Games:** Implementing classic real-time board games like Chess or Connect Four.

* **User Authentication:** Secure user registration and login using JSON Web Tokens (JWT).
* **Containerized Environment:** The entire application stack (frontend, backend, database, cache, proxy) is orchestrated using Docker Compose for consistent local development and production environments.
* **Automated Deployment:** Features a robust CI/CD pipeline for automatic deployment to `daniel-h.ca`.

---

## Project Roadmap
GoNext is a continually evolving personal project. Planned enhancements include:

LetsGo is a continually evolving personal project. Planned enhancements include:

* **Multiplayer Board Games:** Implementing classic real-time board games like Chess or Connect Four.
* **Video Chat:** Integrating WebRTC for peer-to-peer video communication.
* **Expanded User Profiles & Social Features:** Building out more personalized user experiences.
* **More single player games:** Planning Sudoku incl. solver and variants
* **More multipleayer games:** Planning card and board games, once I bite the bullet and get the UX sorted out.
* **User Features:** Persistant user profiles, friend lists, more direct ways to play with them etc.

---

Expand Down Expand Up @@ -78,7 +81,7 @@ LetsGo is a continually evolving personal project. Planned enhancements include:

## Architecture

LetsGo employs a fully containerized, microservices-oriented architecture. Nginx serves as the entry point, routing requests to the Next.js frontend or the Go backend. The Go backend interacts with PostgreSQL for persistent data and Redis for real-time messaging and caching. All components are defined and orchestrated via Docker Compose.
GoNext employs a fully containerized, microservices-oriented architecture. Nginx serves as the entry point, routing requests to the Next.js frontend or the Go backend. The Go backend interacts with PostgreSQL for persistent data and Redis for real-time messaging and caching. All components are defined and orchestrated via Docker Compose.

---

Expand All @@ -96,16 +99,16 @@ This section provides instructions for setting up the project for local developm

1. **Clone the repository:**
```sh
git clone https://github.com/dann-huang/letsGo.git
cd letsGo
git clone https://github.com/dann-huang/gonext.git
cd gonext
```

2. **Run the application:**
```sh
docker-compose up --build
```

This will build the Docker images and start all services. The frontend will be available at `http://localhost:3000`.
This will build the Docker images and start all services. The frontend will be available at `http://localhost`.

---

Expand Down
54 changes: 0 additions & 54 deletions backend/cmd/migrate/main.go

This file was deleted.

65 changes: 42 additions & 23 deletions backend/cmd/web/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import (
"net/http"
"os"

"letsgo/internal/auth"
"letsgo/internal/config"
"letsgo/internal/db"
"letsgo/internal/external"
"letsgo/internal/game"
"letsgo/internal/live"
"letsgo/internal/mdw"
"letsgo/internal/repo"
"letsgo/internal/token"
"letsgo/pkg/jwt/v2"
"gonext/internal/auth"
"gonext/internal/config"
"gonext/internal/db"
"gonext/internal/external"
"gonext/internal/game"
"gonext/internal/live"
"gonext/internal/mail"
"gonext/internal/mdw"
"gonext/internal/repo"
"gonext/internal/token"
"gonext/pkg/jwt/v2"
"gonext/pkg/util/httputil"

"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
Expand All @@ -35,25 +37,38 @@ func main() {
panic(err)
}
defer postgres.Close()

store := repo.NewStore(postgres, redis)
mailer := mail.NewResendMailer(appCfg.Mail)
validator := httputil.NewValidator()

accessManager, err := jwt.NewManager(appCfg.Auth.AccSecret,
appCfg.Auth.AccTTL, appCfg.Auth.Issuer, appCfg.Auth.Audience, token.UserPayload{})
accessManager, err := jwt.NewManager(
appCfg.Auth.AccSecret,
appCfg.Auth.AccTTL,
appCfg.Auth.Issuer,
appCfg.Auth.Audience,
token.UserPayload{},
)
if err != nil {
panic(err)
}
authModule := auth.NewModule(store.User, store.KVStore, accessManager, appCfg.Auth)

const userCtxKey mdw.ContextKey = "userPayload"
userAccMdw := mdw.AccessMdw(accessManager, appCfg.Auth.AccCookieName, appCfg.Auth.AccTTL, userCtxKey)
kvMngr := token.NewRedisKVMngr(store.KVStore, appCfg.Token)
authMdw := mdw.AccessMdw(accessManager, appCfg.Auth.AccCookieName, appCfg.Auth.AccTTL)
authModule := auth.NewModule(
store.User,
kvMngr,
accessManager,
mailer,
appCfg.Auth,
authMdw,
validator,
)

r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)

gameReg := game.NewRegistry()
gameReg.RegisterAll()
gameRegistry := game.NewRegistry()
gameRegistry.RegisterAll()

r.Route("/api", func(api chi.Router) {
api.Get("/health", func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -65,14 +80,18 @@ func main() {
})

api.Mount("/auth", authModule.Router())
api.Mount("/live", live.Router(userAccMdw, userCtxKey, gameReg, appCfg.WS))

api.Group(func(protected chi.Router) {
protected.Use(authMdw)
protected.Mount("/live", live.Router(gameRegistry, appCfg.WS))
})
})

// static pages
r.Get("/stat/*", external.StaticPageHandler(appCfg.StaticPages))

// frontend
// r.Mount("/", external.FrontendRevProxy(cfg.FrontendUrl))
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
httputil.RespondErr(w, http.StatusNotFound, "Route not found", nil)
})

println("---Server start---")
if err := http.ListenAndServe(":3333", r); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion backend/go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module letsgo
module gonext

go 1.24.3

Expand All @@ -10,6 +10,7 @@ require (
github.com/google/uuid v1.6.0
github.com/lib/pq v1.10.9
github.com/redis/go-redis/v9 v9.9.0
github.com/resend/resend-go/v2 v2.21.0
golang.org/x/crypto v0.38.0
)

Expand Down
2 changes: 2 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.9.0 h1:URbPQ4xVQSQhZ27WMQVmZSo3uT3pL+4IdHVcYq2nVfM=
github.com/redis/go-redis/v9 v9.9.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/resend/resend-go/v2 v2.21.0 h1:8aZwFd5Mry5fcBXSuZYHyKhsbnQooj5+Q/ebyMtd3Rc=
github.com/resend/resend-go/v2 v2.21.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
Expand Down
Loading