This is an example project demonstrating Clean Architecture principles in Go. It is a simple blog application that allows you to create and retrieve blog posts. The project structure is designed to separate concerns and make the application easy to maintain and test.
The project is organized into the following layers:
- Entities: Core business logic.
- Use Cases (Interactors): Application-specific business rules.
- Interface Adapters: Adapters for the user interface, database, web controllers, etc.
- Frameworks and Drivers: Framework-specific code, like routing, databases, etc.
.
β .gitignore
β coverage
β go.mod
β go.sum
β gocleanarchitecture.exe
β GoCleanArchitecture.Md
β LICENSE
β README.Md
β
ββββ.vscode
β settings.json
β
ββββcmd
β blog.db
β blogposts.json
β gocleanarchitecture.exe
β main.go
β server.log
β
ββββconfig
β config.go
β
ββββentities
β blog_post.go
β
ββββerrors
β errors.go
β
ββββframeworks
β ββββdb
β β β in_memory_blog_post_repository.go
β β β
β β ββββsqlite
β β blog_post_repository.go
β β sqlite.go
β β
β ββββlogger
β β logger.go
β β
β ββββweb
β β router.go
β β
β ββββmiddleware
β logging.go
β recovery.go
β
ββββinterfaces
β blog_post_controller.go
β blog_post_repository.go
β
ββββtests
β ββββentities
β β blog_post_test.go
β β
β ββββerrors
β β errors_test.go
β β
β ββββframeworks
β β ββββdb
β β β in_memory_blog_post_repository_test.go
β β β sqlite_blog_post_repository_test.go
β β β
β β ββββlogger
β β logger_test.go
β β
β ββββinterfaces
β β blog_post_controller_test.go
β β
β ββββusecases
β blog_post_usecase_test.go
β
ββββusecases
blog_post_usecase.go
Clean Architecture promotes separation of concerns, making your codebase easier to maintain and test. Here are some benefits:
- Testability: Each layer can be tested independently.
- Maintainability: Changes in one layer have minimal impact on other layers.
- Scalability: Easily extend functionality by adding new layers or components.
- Flexibility: Swap out frameworks or tools with minimal changes to the overall architecture.
- CRUD operations for blog posts with author tracking and ownership validation
- User Authentication & Authorization: JWT-based authentication with secure password hashing
- Role-Based Access Control (RBAC): Admin and user roles with permission management
- Comments System: Hierarchical comments with replies on blog posts
- Real-time Updates: WebSocket support for live notifications of new posts and comments
- OAuth2 Social Login: Fully integrated with Google and GitHub
- Clean Architecture implementation
- Multiple Database Backends: SQLite, Supabase, In-Memory
- Custom error handling with domain validation
- Structured logging
- Middleware for logging, recovery, and authentication
- Rich domain model with business rules
- User profile management with avatar support
- Go 1.17 or higher
- Database Options:
- SQLite3 (default, no setup required)
- Supabase account and project (for cloud database)
- In-memory (for testing, no setup required)
-
Clone the repository:
git clone https://github.com/tomblanchard312/gocleanarchitecture.git cd gocleanarchitecture -
Install dependencies:
go mod tidy
-
Build the application:
cd cmd go build -o gocleanarchitecture.exe ./cmd -
Run the application:
./gocleanarchitecture.exe
-
The server will start on port 8080. You can test the endpoints using curl or any API testing tool.
POST /auth/register: Register a new user accountPOST /auth/login: Authenticate and receive a JWT tokenGET /auth/users/{username}: Get public user profile by username
GET /auth/profile: Get authenticated user's profilePUT /auth/profile: Update authenticated user's profilePOST /auth/change-password: Change user password
GET /blogposts: Retrieve all blog postsGET /blogposts/{id}: Retrieve a specific blog post
POST /blogposts: Create a new blog post (automatically assigned to authenticated user)PUT /blogposts/{id}: Update a blog post (only if you're the author)DELETE /blogposts/{id}: Delete a blog post (only if you're the author)
GET /blogposts/{blogPostId}/comments: Get all comments for a blog postGET /comments/{commentId}/replies: Get all replies to a specific comment
POST /blogposts/{blogPostId}/comments: Create a new comment on a blog postPUT /comments/{commentId}: Update your own commentDELETE /comments/{commentId}: Delete your own comment
GET /admin/users: List all usersGET /admin/users/{id}: Get detailed user informationPUT /admin/users/{id}/role: Update a user's role (admin/user)DELETE /admin/users/{id}: Delete a user account
GET /ws: WebSocket connection for real-time updates- Broadcasts new blog posts when created
- Broadcasts new comments when posted
GET /auth/google: Initiate Google OAuth loginGET /auth/google/callback: Google OAuth callbackGET /auth/github: Initiate GitHub OAuth loginGET /auth/github/callback: GitHub OAuth callback
Setup:
-
Create OAuth2 applications:
- Google: Google Cloud Console β APIs & Services β Credentials
- GitHub: GitHub Settings β OAuth Apps
-
Configure
.envfile:
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URL=http://localhost:8080/auth/google/callback
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
GITHUB_REDIRECT_URL=http://localhost:8080/auth/github/callbackUsage:
- Direct users to
http://localhost:8080/auth/googleor/auth/github - After authentication, the callback will return a JSON response with user and JWT token
- The app automatically creates a new user account or logs in an existing user
curl -X POST http://localhost:8080/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"john_doe","email":"[email protected]","password":"securepass123","full_name":"John Doe"}'curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email_or_username":"[email protected]","password":"securepass123"}'Response:
{
"user": {
"id": "uuid-here",
"username": "john_doe",
"email": "[email protected]",
"full_name": "John Doe"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}curl -X POST http://localhost:8080/blogposts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"ID":"1", "Title":"Test Title", "Content":"Test Content"}'curl http://localhost:8080/blogpostsTo run all tests:
go test ./...To run tests for a specific package:
go test ./tests/entities
go test ./tests/usecases
go test ./tests/interfaces
go test ./tests/frameworks/db
go test ./tests/frameworks/loggerTo run a specific test function:
go test ./tests/entities -run TestBlogPostCreation
go test ./tests/usecases -run TestCreateBlogPostTo run tests with verbose output:
go test -v ./tests/...To run tests and see coverage:
go test ./tests/... -coverprofile=coverage.out
go tool cover -html=coverage.outLogs are written to server.log for debugging purposes. Ensure the log file is writable and check it for any server-related errors. License
This project uses custom error types defined in the errors package. All errors are logged and appropriate HTTP status codes are returned to the client.
- Gorilla Mux for HTTP routing
- Gorilla WebSocket for WebSocket connections
- Viper for configuration management
- JWT-Go for JWT token generation and validation
- bcrypt for secure password hashing
- OAuth2 for social login integration
- godotenv for loading environment variables
- Google UUID for generating unique identifiers
- Supabase Go Client for Supabase integration
The application can be configured using environment variables. Copy .env.example to .env and configure:
SERVER_PORT: The port on which the server will run (default: ":8080")LOG_LEVEL: The logging level (default: "info")LOG_FILE: The path to the log file (default: "server.log")
DB_TYPE: Database type - "sqlite", "supabase", or "inmemory" (default: "sqlite")DB_PATH: The path to the SQLite database file (default: "./blog.db")
SUPABASE_URL: Your Supabase project URLSUPABASE_KEY: Your Supabase anon/public API keySUPABASE_USER: Database username (optional, for direct access)SUPABASE_PASS: Database password (optional, for direct access)
JWT_SECRET: Secret key for JWT token signing (change in production!)JWT_TOKEN_DURATION_HOURS: Token expiration time in hours (default: 24)
BASE_URL: Base URL for OAuth callbacks (default: "http://localhost:8080")GOOGLE_CLIENT_ID: Google OAuth2 Client IDGOOGLE_CLIENT_SECRET: Google OAuth2 Client SecretGOOGLE_REDIRECT_URL: Google OAuth callback URL (default: "http://localhost:8080/auth/google/callback")GITHUB_CLIENT_ID: GitHub OAuth2 Client IDGITHUB_CLIENT_SECRET: GitHub OAuth2 Client SecretGITHUB_REDIRECT_URL: GitHub OAuth callback URL (default: "http://localhost:8080/auth/github/callback")
The API is documented using OpenAPI 3.0 specification. You can find the complete API documentation in api-documentation.yaml.
To view the documentation:
- Using Swagger UI: Upload the
api-documentation.yamlfile to Swagger Editor - Using Swagger UI locally:
docker run -p 80:8080 -e SWAGGER_JSON=/api-documentation.yaml -v $(pwd):/usr/share/nginx/html swaggerapi/swagger-ui
Import the Go-Clean-Architecture-Blog.postman_collection.json file into Postman for easy API testing.
Setup:
- Import the collection into Postman
- The collection includes environment variables:
base_url: API server URL (default: http://localhost:8080)jwt_token: Auto-saved after login/registeruser_id: Auto-saved after authenticationpost_id: Auto-saved after creating a post
For detailed documentation on advanced features, see FEATURES.md:
- Role-Based Access Control (RBAC): Admin and user roles
- Comments System: Hierarchical comments with replies
- WebSocket Real-time Updates: Live notifications
- OAuth2 Social Login: Google and GitHub integration (framework)
- Go 1.17 or higher
- Database (SQLite, Supabase, or other PostgreSQL-compatible)
- SSL/TLS certificates (recommended)
- Reverse proxy (nginx or similar)
-
Build the application:
CGO_ENABLED=1 go build -o blog-api ./cmd/main.go
-
Create a production
.envfile:cp .env.example .env
-
Configure production settings:
DB_TYPE=sqlite DB_PATH=/var/lib/blog-api/blog.db SERVER_PORT=:8080 LOG_LEVEL=info LOG_FILE=/var/log/blog-api/server.log JWT_SECRET=your-super-secret-key-minimum-32-characters-long JWT_TOKEN_DURATION_HOURS=24
-
Run the application:
./blog-api
-
Set up as a systemd service (Linux):
Create
/etc/systemd/system/blog-api.service:[Unit] Description=Go Clean Architecture Blog API After=network.target [Service] Type=simple User=blog-api WorkingDirectory=/opt/blog-api ExecStart=/opt/blog-api/blog-api Restart=on-failure RestartSec=10 Environment="PATH=/usr/bin:/usr/local/bin" [Install] WantedBy=multi-user.target
Enable and start the service:
sudo systemctl enable blog-api sudo systemctl start blog-api sudo systemctl status blog-api
-
Set up Supabase project:
- Create a project at supabase.com
- Note your project URL and anon key
- Run the SQL scripts in Supabase SQL Editor (in order):
supabase_users_schema.sql(users table with RBAC)supabase_schema.sql(blog posts table)supabase_comments_schema.sql(comments table)
-
Build the application:
go build -o blog-api ./cmd/main.go
-
Configure for Supabase:
DB_TYPE=supabase SUPABASE_URL=https://your-project.supabase.co SUPABASE_KEY=your-anon-public-key SERVER_PORT=:8080 LOG_LEVEL=info LOG_FILE=/var/log/blog-api/server.log JWT_SECRET=your-super-secret-key-minimum-32-characters-long JWT_TOKEN_DURATION_HOURS=24
-
Deploy to a VPS or cloud platform
-
Create a
Dockerfile:FROM golang:1.21-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o blog-api ./cmd/main.go FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/blog-api . COPY --from=builder /app/.env.example .env EXPOSE 8080 CMD ["./blog-api"]
-
Create
docker-compose.yml(with SQLite):version: '3.8' services: api: build: . ports: - "8080:8080" environment: - DB_TYPE=sqlite - DB_PATH=/data/blog.db - JWT_SECRET=your-secret-key volumes: - ./data:/data - ./logs:/var/log/blog-api restart: unless-stopped
-
Build and run:
docker-compose up -d
Create /etc/nginx/sites-available/blog-api:
server {
listen 80;
server_name yourdomain.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# WebSocket support
location /ws {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}Enable the site:
sudo ln -s /etc/nginx/sites-available/blog-api /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx- Change
JWT_SECRETto a strong, randomly generated secret - Use HTTPS/TLS encryption
- Set appropriate CORS policies
- Enable rate limiting
- Use environment variables for all secrets
- Keep the
.envfile secure (never commit it) - Regularly update dependencies
- Set up monitoring and logging
- Configure firewall rules
- Use a strong database password (if applicable)
- Enable Supabase Row Level Security (RLS)
- Implement backup strategy
- Set up health check endpoints
Development:
DB_TYPE=inmemory
LOG_LEVEL=debugStaging:
DB_TYPE=sqlite
DB_PATH=./staging.db
LOG_LEVEL=infoProduction:
DB_TYPE=supabase
LOG_LEVEL=warn
JWT_TOKEN_DURATION_HOURS=24Consider adding health check endpoints and integrating with:
- Prometheus for metrics
- Grafana for dashboards
- ELK Stack for log aggregation
- Sentry for error tracking
A beautiful, modern frontend is available in the frontend/ directory!
- β¨ Stunning modern design with glassmorphism and gradients
- π Dark/Light mode with smooth transitions
- β‘ Real-time updates via WebSocket
- π± Fully responsive mobile-first design
- π Smooth animations powered by Framer Motion
- π JWT authentication with beautiful login/register pages
cd frontend
npm install
npm run devThen visit http://localhost:5173
See frontend/README.md and frontend/QUICKSTART.md for full documentation.
- React 18 + TypeScript
- Vite (lightning-fast builds)
- Tailwind CSS v3
- Framer Motion
- TanStack Query
- React Router
Contributions are welcome! Please feel free to submit a Pull Request.
- β
Add role-based access control (RBAC) for admin/user permissionsDONE - β
Implement blog post commentsDONE - β
Add WebSocket real-time updatesDONE - β
Add OAuth2 social loginDONE (Google & GitHub fully integrated) - Implement password reset via email
- Add blog post likes and reactions
- Add pagination for blog post and comment listings
- Implement full-text search for blog posts
- Add user follow/unfollow functionality
- Implement rate limiting for API endpoints
- Add email notifications for comments and replies
- Add image upload support for blog posts and user avatars
- Implement comment moderation for admins
- Add analytics and metrics tracking
This project is licensed under the MIT License. See the LICENSE file for details.
- The Clean Architecture by Robert C. Martin