Chirpy is a backend API service for a Twitter-like social platform where users can post short messages called "chirps". Built with Go, it provides user authentication, data persistence, and premium membership features.
- Go 1.16 or newer
- PostgreSQL
- Environment variables properly configured
-
Clone the repository:
git clone https://github.com/yourusername/chirpy.git cd chirpy -
Set up environment variables:
# Create a .env file JWT_SECRET=your_secret_key DATABASE_URL=postgres://username:password@localhost:5432/chirpy POLKA_API_KEY=your_api_key -
Initialize the database:
# Run PostgreSQL migrations goose -dir sql/schema postgres "postgres://username:password@localhost:5432/chirpy" up -
Build and run:
go build ./chirpy
-
Create a user account:
curl -X POST http://localhost:8080/api/users \ -H "Content-Type: application/json" \ -d '{"email":"[email protected]","password":"securepassword"}' -
Login:
curl -X POST http://localhost:8080/api/login \ -H "Content-Type: application/json" \ -d '{"email":"[email protected]","password":"securepassword"}'Save the returned JWT token and refresh token.
-
Create a chirp:
curl -X POST http://localhost:8080/api/chirps \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"body":"Hello, Chirpy!"}' -
Get all chirps:
curl http://localhost:8080/api/chirps
Chirpy is built using:
- Go's standard library
net/httppackage - PostgreSQL database for data persistence
- JWT authentication system
- RESTful API design
The PostgreSQL database consists of the following tables:
-
Users
- UUID primary key
- Email (unique)
- Hashed password
- Created/updated timestamps
- Chirpy Red membership status
-
Chirps
- UUID primary key
- Message content (max 140 characters)
- User ID (foreign key)
- Created/updated timestamps
-
Refresh Tokens
- Token string primary key
- User ID foreign key
- Created/updated/expiry timestamps
- Revoked timestamp for invalidation
- Passwords hashed using bcrypt
- JWT tokens with 1-hour expiry
- Refresh token system for extended sessions
- Bearer token authentication for protected endpoints
- API key validation for webhook endpoints
- Endpoint:
POST /api/users - Request Body:
{ "email": "string", "password": "string" } - Response (201 Created):
{ "id": "uuid", "created_at": "timestamp", "updated_at": "timestamp", "email": "string", "is_chirpy_red": boolean }
- Endpoint:
POST /api/login - Request Body:
{ "email": "string", "password": "string" } - Response (200 OK):
{ "id": "uuid", "created_at": "timestamp", "updated_at": "timestamp", "email": "string", "token": "string", "refresh_token": "string", "is_chirpy_red": boolean }
- Endpoint:
PUT /api/users - Auth: Bearer token
- Request Body:
{ "email": "string", "password": "string" } - Response (200 OK):
{ "id": "uuid", "created_at": "timestamp", "updated_at": "timestamp", "email": "string", "is_chirpy_red": boolean }
- Endpoint:
POST /api/refresh - Auth: Bearer token (refresh token)
- Response (200 OK):
{ "token": "string" }
- Endpoint:
POST /api/revoke - Auth: Bearer token (refresh token)
- Response: 204 No Content
- Endpoint:
POST /api/chirps - Auth: Bearer token
- Request Body:
{ "body": "string" // Max 140 characters } - Response (201 Created):
{ "id": "uuid", "created_at": "timestamp", "updated_at": "timestamp", "body": "string", "user_id": "uuid" } - Note: Profanity filter replaces words like "kerfuffle", "sharbert", "fornax" with "****"
- Endpoint:
GET /api/chirps - Query Parameters:
author_id: (optional) Filter by author UUIDsort: (optional) "asc" or "desc" to sort by creation time
- Response (200 OK):
[ { "id": "uuid", "created_at": "timestamp", "updated_at": "timestamp", "body": "string", "user_id": "uuid" } ]
- Endpoint:
GET /api/chirps/{chirpID} - Response (200 OK):
{ "id": "uuid", "created_at": "timestamp", "updated_at": "timestamp", "body": "string", "user_id": "uuid" }
- Endpoint:
DELETE /api/chirps/{chirpID} - Auth: Bearer token (must be creator of chirp)
- Response: 204 No Content
- Endpoint:
GET /api/healthz - Response: 200 OK
- Endpoint:
GET /admin/metrics - Response: Site metrics
- Endpoint:
POST /admin/reset - Response: 200 OK
- Endpoint:
POST /api/polka/webhooks - Auth: API key
- Request Body:
{ "event": "string", "data": { "user_id": "string" } } - Response: 204 No Content
- Note: Handles "user.upgraded" event to update premium membership status
- Profanity Filter: Automatically replaces forbidden words with asterisks
- Chirpy Red: Premium membership tier activated through Polka webhooks
- Metrics: Tracking of application access
- Secure Token Management: JWT creation and validation
- Data Persistence: All data stored in PostgreSQL
- PostgreSQL
- JWT
- bcrypt
- UUID
- godotenv
- sqlc for SQL query generation
- goose for database migrations