A REST API for a learning management system built with Hono, Bun, and PostgreSQL.
- RESTful API with OpenAPI 3.0 specification
- Session-based authentication with HTTP-only cookies
- Role-based access control (Admin, Teacher, Student)
- User, course, category, and enrollment management
- Request/response validation with Zod schemas
- PostgreSQL database with Drizzle ORM
- Interactive API documentation with Scalar
- TypeScript for type safety
- Code quality tools (Biome for linting and formatting)
- Runtime: Bun
- Framework: Hono
- Database: PostgreSQL with Drizzle ORM
- Authentication: Session-based with HTTP-only cookies
- Authorization: Role-based access control
- Validation: Zod schemas
- Documentation: OpenAPI 3.0 with Scalar UI
- Code Quality: Biome (linting and formatting)
- Language: TypeScript
- Bun runtime
- PostgreSQL database
- Clone the repository:
git clone <repository-url>
cd lrnr- Install dependencies:
bun install- Set up your environment variables:
# Create .env file with your configuration
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USER=your_username
DATABASE_PASSWORD=your_password
DATABASE_NAME=lrnr
SESSION_SECRET=your-session-secret
PORT=3000
NODE_ENV=development- Run database migrations:
bun run db:migrate- Start the development server:
bun run devThe API will be available at http://localhost:3000 with interactive documentation at http://localhost:3000/reference.
| Command | Description |
|---|---|
bun run dev |
Start development server with hot reload |
bun run lint |
Check code with Biome |
bun run lint:fix |
Fix linting issues |
bun run format |
Check code formatting |
bun run format:fix |
Format code |
bun run check |
Run code quality checks |
bun run db:generate |
Generate database migrations |
bun run db:migrate |
Apply database migrations |
bun run db:push |
Push schema changes to database |
bun run db:studio |
Open Drizzle Studio |
The application requires the following environment variables:
# Server Configuration
PORT=3000
NODE_ENV=development
# Database Configuration
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USER=your_username
DATABASE_PASSWORD=your_password
DATABASE_NAME=lrnr
# Authentication Configuration
SESSION_SECRET=your-session-secretsrc/
├── app.ts # Application setup and route registration
├── index.ts # Server entry point
├── env.ts # Environment variable validation
├── db/
│ ├── index.ts # Database connection setup
│ ├── schema/ # Database schema definitions
│ │ ├── users.ts # User schema with roles
│ │ ├── sessions.ts # Session management schema
│ │ ├── courses.ts # Course schema
│ │ ├── categories.ts # Category schema
│ │ ├── enrollments.ts # Enrollment schema
│ │ └── enums/ # Database enums (roles, status)
│ └── migrations/ # Database migration files
├── hooks/
│ ├── auth.ts # Authentication middleware
│ └── pino-logger.ts # Request logging middleware
├── lib/
│ ├── create-app.ts # Hono app factory
│ ├── configure-openapi.ts # OpenAPI configuration
│ ├── constants.ts # Application constants
│ ├── types.ts # TypeScript type definitions
│ └── auth/ # Authentication utilities
│ └── index.ts # Session management and password hashing
└── routes/
├── index.route.ts # Root API route
├── auth/ # Authentication endpoints
├── users/ # User management endpoints
├── courses/ # Course management endpoints
├── categories/ # Category management endpoints
├── enrollments/ # Enrollment management endpoints
└── llms/ # LLM integration endpoints
The API supports two authentication methods:
- Session-based authentication - Uses HTTP-only cookies, ideal for web applications
- API key authentication - Uses Bearer tokens, ideal for programmatic access
Users have different roles that control access to various endpoints.
- STUDENT: Default role for new users
- TEACHER: Can manage courses and view enrollments
- ADMIN: Full access to all system resources
| Endpoint | Method | Description |
|---|---|---|
POST /auth/signup |
POST | Register a new user account |
POST /auth/signin |
POST | Sign in with email and password |
POST /auth/logout |
POST | Sign out and invalidate session |
| Endpoint | Method | Description |
|---|---|---|
GET /api-keys |
GET | List user's API keys |
POST /api-keys |
POST | Create a new API key |
GET /api-keys/{id} |
GET | Get specific API key details |
PATCH /api-keys/{id} |
PATCH | Update API key (name, expiration) |
DELETE /api-keys/{id} |
DELETE | Revoke an API key |
Most API endpoints require authentication. The following routes are public:
GET /- API root/health checkPOST /auth/signup- User registrationPOST /auth/signin- User authenticationGET /doc- OpenAPI specificationGET /reference- API documentation
- Sessions are valid for 15 days by default
- Sessions are automatically refreshed on API usage
- HTTP-only cookies are used for security
- Session data is stored in the database
- API keys are prefixed with
lrnr_for identification - Keys can have optional expiration dates
- Keys are hashed before storage (never stored in plain text)
- Last usage time is tracked for each key
- Keys can be revoked/deactivated at any time
Register a new user:
curl -X POST http://localhost:3000/auth/signup \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "[email protected]",
"password": "securepassword123",
"password_confirmation": "securepassword123"
}'Sign in (session-based):
curl -X POST http://localhost:3000/auth/signin \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{
"email": "[email protected]",
"password": "securepassword123"
}'Create an API key:
curl -X POST http://localhost:3000/api-keys \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"name": "My API Key"
}'Use session authentication:
curl -X GET http://localhost:3000/users \
-H "Content-Type: application/json" \
-b cookies.txtUse API key authentication:
curl -X GET http://localhost:3000/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer lrnr_your_api_key_here"The application implements standard security practices:
- Password hashing for user credentials
- HTTP-only cookies to prevent XSS attacks
- API key hashing (keys never stored in plain text)
- Input validation using Zod schemas
- Role-based access control for endpoints
- Parameterized database queries
- Environment variables for sensitive configuration
Interactive API documentation is available at:
/doc- OpenAPI JSON specification/reference- Scalar UI for testing endpoints
The documentation includes request/response schemas, authentication requirements, and example requests.
Database Connection Problems:
- Verify PostgreSQL is running
- Check database credentials in environment variables
- Ensure database exists and is accessible
Authentication Issues:
- Check that cookies are being sent with requests
- Verify session hasn't expired
- Ensure proper authentication headers
- Use
bun run db:studioto inspect database contents - Check server logs for detailed error information
- Visit
/referencefor interactive API testing
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-feature) - Make your changes
- Run tests and linting (
bun run check) - Commit your changes (
git commit -m 'Add new feature') - Push to the branch (
git push origin feature/new-feature) - Create a Pull Request
This project is licensed under the MIT License. See the LICENSE file for details.