Podium is a comprehensive web application designed to streamline the college band recruitment process, connecting high school students with college band programs.
- Features
- Prerequisites
- Technology Stack
- Getting Started
- Configuration
- Health Checks
- Security
- API Documentation
- Contributing
- License
- Student Profiles: High school students can create comprehensive profiles with performance videos
- Band Program Management: College bands can showcase their programs
- Recruitment Tools: Advanced search and filtering for band directors
- Video Uploads: Support for performance video uploads with transcoding
- Scholarship Management: Track and manage scholarship offers
- Real-time Notifications: SignalR-based notifications
- Event Management: Coordinate auditions and recruitment events
- Guardian Access: Parents/guardians can manage student profiles
Podium uses GitHub Actions for continuous integration and deployment. The pipeline ensures code quality, runs automated tests, builds Docker images, and deploys to staging and production environments.
graph LR
A[Code Push] --> B[Backend CI]
A --> C[Frontend CI]
B --> D[Build Docker Images]
C --> D
D --> E[Push to GHCR]
E --> F[Deploy to Staging]
F --> G{Manual Approval}
G -->|Approved| H[Deploy to Production]
G -->|Rejected| I[End]
H --> J[Health Checks]
J --> K[Deployment Complete]
- Triggers: Push to
main, Pull Requests, Manual dispatch - Jobs:
- Run unit tests with coverage reporting
- Build .NET application with NuGet caching
- Build and push Docker image to GitHub Container Registry
- Features: Test result annotations, code coverage reports in PRs
- Triggers: Push to
main, Pull Requests, Manual dispatch - Jobs:
- Lint Angular codebase with ESLint
- Run unit tests with coverage
- Build production bundle with size checks
- Build and push Docker image to GitHub Container Registry
- Features: Bundle size warnings (>2MB), artifact uploads
- Triggers: Push to
main, Manual dispatch - Jobs:
- Pull latest Docker images from GHCR
- Run database migrations
- Deploy to staging environment
- Execute smoke tests
- Send deployment notifications
- Features: Automatic rollback on failure
- Triggers: Manual dispatch only
- Jobs:
- Pre-deployment checks (image availability, configuration validation)
- Deploy with manual approval gate
- Database migrations with automatic rollback
- Post-deployment health checks
- Cache warming and monitoring updates
- Features: Manual approval required, comprehensive error handling
All Docker images are stored in GitHub Container Registry (GHCR) and tagged with:
latest- Latest build from main branchsha-{commit}- Specific commit SHApr-{number}- Pull request builds
Image Locations:
- Backend:
ghcr.io/jfenderson/podium/podium-backend - Frontend:
ghcr.io/jfenderson/podium/podium-frontend
To trigger a manual deployment:
-
Staging Deployment:
- Go to Actions → Deploy to Staging
- Click "Run workflow"
- Select branch (typically
main) - Click "Run workflow"
-
Production Deployment:
- Go to Actions → Deploy to Production
- Click "Run workflow"
- Enter the Docker image tag (e.g.,
latestorsha-abc1234) - Optionally skip health checks
- Click "Run workflow"
- Approve the deployment in the Environments section
See .github/GITHUB-SECRETS.md for detailed information on all required secrets and how to configure them.
Key Secrets:
DATABASE_CONNECTION_STRING- Database connectionJWT_SECRET- JWT signing key (32+ characters)AZURE_STORAGE_CONNECTION_STRING- File storageGITHUB_TOKEN- Automatically provided for GHCR access
- Backend: NuGet packages cached by
packages.lock.jsonhash - Frontend:
node_modulescached bypackage-lock.jsonhash - Docker: Build cache using GitHub Actions cache
- Workflow status badges displayed at the top of this README
- Deployment summaries posted to GitHub Actions
- Health check endpoints:
- Backend:
/healthand/ready - Frontend:
/health
- Backend:
- .NET SDK 8.0+: Required for backend development
- Node.js 20+ and npm 10+: Required for frontend development
- SQL Server 2022 or LocalDB: Database server
- Git: Version control
- Docker 20.10+: Container runtime
- Docker Compose 2.0+: Multi-container orchestration
- Framework: ASP.NET Core 8.0
- ORM: Entity Framework Core 8.0
- Database: SQL Server 2022
- Authentication: JWT (JSON Web Tokens)
- Background Jobs: Hangfire
- Logging: Serilog
- API Documentation: Swagger/OpenAPI
- Framework: Angular 21
- UI Library: Tailwind CSS
- Real-time: SignalR client
- Charts: Chart.js
- Containerization: Docker
- Orchestration: Docker Compose
- Web Server (Production): Nginx (for frontend)
- Storage: Azure Blob Storage or AWS S3
-
Clone the repository:
git clone https://github.com/JFenderson/Podium.git cd Podium -
Create environment file:
cp .env.example .env
-
Configure environment variables: Edit the
.envfile and set your configuration values:# Database ConnectionStrings__DefaultConnection=Server=localhost;Database=PodiumDb;Trusted_Connection=true;MultipleActiveResultSets=true # JWT JWT__Secret=your-super-secret-key-at-least-32-characters-long JWT__Issuer=PodiumAPI JWT__Audience=PodiumClient # Storage (choose Azure or AWS) StorageProvider=Azure AzureStorage__ConnectionString=your-azure-connection-string # Email SendGrid__ApiKey=your-sendgrid-api-key
Important: Never commit the
.envfile to version control!
-
Navigate to the Backend directory:
cd Backend/Podium -
Restore NuGet packages:
dotnet restore
-
Update database:
cd Podium.API dotnet ef database update -
Run the application:
dotnet run
The API will be available at:
https://localhost:5001orhttp://localhost:5000
-
Navigate to the Frontend directory:
cd Frontend/podium-frontend -
Install dependencies:
npm install
-
Start the development server:
npm start
The application will be available at:
http://localhost:4200
-
Ensure
.envfile is configured (see Environment Setup) -
Build and start all services:
docker-compose up -d
This will start:
- SQL Server database on port
1433 - Backend API on port
5000 - Frontend on port
80
- SQL Server database on port
-
View logs:
docker-compose logs -f
-
Stop all services:
docker-compose down
-
Stop and remove volumes (
⚠️ deletes data):docker-compose down -v
Backend:
cd Backend
docker build -t podium-backend .
docker run -p 5000:5000 --env-file ../.env podium-backendFrontend:
cd Frontend
docker build -t podium-frontend .
docker run -p 80:80 podium-frontendSee .env.example for a complete list of environment variables.
| Variable | Description | Example |
|---|---|---|
ConnectionStrings__DefaultConnection |
Database connection string | Server=db;Database=PodiumDb;User Id=sa;Password=YourPass123!;TrustServerCertificate=true |
JWT__Secret |
JWT signing key (min 32 chars) | your-super-secret-key-min-32-characters |
AzureStorage__ConnectionString or AWS__AccessKey |
Storage provider credentials | (depends on chosen provider) |
| Variable | Description | Default |
|---|---|---|
JWT__ExpirationMinutes |
JWT token lifetime | 60 |
Video__MaxFileSizeMB |
Max video upload size | 500 |
RateLimit__PermitLimit |
API rate limit per window | 10 for auth, 60 for general |
SecurityHeaders__EnableHSTS |
Enable HSTS header | false (dev), true (prod) |
Serilog__MinimumLevel__Default |
Logging level | Information |
Rate limiting is configured in appsettings.json:
{
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"HttpStatusCode": 429,
"IpRateLimitPolicies": {
"IpRules": [
{
"Endpoint": "*/api/auth/login",
"Period": "1m",
"Limit": 10
}
]
}
}
}Endpoint Limits:
- Authentication endpoints (
/api/auth/*): 10 requests/minute - General API endpoints: 60 requests/minute
- Health check endpoints: Unlimited (whitelisted)
Security headers are automatically applied to all responses:
X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockStrict-Transport-Security(production only)Content-Security-PolicyReferrer-Policy: strict-origin-when-cross-origin
Configure via environment variables:
SecurityHeaders__EnableHSTS=true
SecurityHeaders__HSTSMaxAge=31536000
SecurityHeaders__EnableCSP=trueStructured logging is implemented with Serilog:
Console Output:
- Format:
[HH:mm:ss Level] Message - Outputs to Docker logs
File Output:
- Location:
logs/podium-{Date}.log - Rolling: Daily
- Retention: 7 days
Configuration:
Serilog__MinimumLevel__Default=Information
Serilog__MinimumLevel__Override__Microsoft=WarningLog Levels:
Verbose: Most detailedDebug: Internal system eventsInformation: General application flow (default)Warning: Abnormal or unexpected eventsError: Errors and exceptionsFatal: Critical errors causing shutdown
The application provides health check endpoints for monitoring:
Returns 200 OK if the application is running.
Response:
{
"status": "Healthy",
"timestamp": "2026-01-15T08:44:13Z",
"service": "Podium API"
}Usage:
curl http://localhost:5000/healthReturns 200 OK if the application is ready to serve traffic (checks database connectivity).
Response (Healthy):
{
"status": "Ready",
"timestamp": "2026-01-15T08:44:13Z",
"service": "Podium API",
"checks": {
"database": "Connected"
}
}Response (Unhealthy):
{
"status": "NotReady",
"timestamp": "2026-01-15T08:44:13Z",
"service": "Podium API",
"checks": {
"database": "Disconnected"
},
"error": "Unable to connect to database"
}Returns 503 Service Unavailable if dependencies are not available.
Usage:
curl http://localhost:5000/readyHealth checks are automatically configured in Docker:
- Backend: Checks
/healthevery 30 seconds - Frontend: Checks nginx
/healthendpoint every 30 seconds - Database: Checks SQL Server connectivity every 30 seconds
View health status:
docker-compose psSecurity is a top priority. See SECURITY.md for:
- Vulnerability reporting process
- Security best practices
- Authentication & authorization details
- Secrets management guidelines
- Dependency management
Key Security Features:
- JWT-based authentication
- Role-based access control (RBAC)
- Rate limiting on API endpoints
- Security headers (CSP, HSTS, etc.)
- Encrypted database connections
- Secrets stored in environment variables
- Regular dependency updates
- Structured audit logging
Interactive API documentation is available in development mode:
- URL:
http://localhost:5000/swagger - Provides interactive API testing
- Shows all available endpoints, request/response schemas
Most API endpoints require authentication using JWT tokens.
1. Register a new user:
POST /api/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "SecurePass123!",
"firstName": "John",
"lastName": "Doe",
"role": "Student"
}2. Login:
POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "SecurePass123!"
}Response:
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "def50200a1b2c3d4...",
"expiresAt": "2026-01-15T09:44:13Z",
"userId": "abc-123-def",
"email": "user@example.com"
}3. Use the token:
GET /api/students
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...POST /api/auth/register- Register new userPOST /api/auth/login- Authenticate userGET /api/students- List students (Band Staff/Director)POST /api/videos/upload- Upload performance videoGET /api/scholarships- List scholarship offersGET /api/bands- List college bandsPOST /api/events- Create recruitment event
- Set
ASPNETCORE_ENVIRONMENT=Production - Generate strong
JWT__Secret(32+ characters) - Configure HTTPS/TLS certificates
- Enable HSTS (
SecurityHeaders__EnableHSTS=true) - Set up production database with backups
- Configure production storage (Azure/AWS)
- Set up email service (SendGrid)
- Configure production
AllowedOriginsfor CORS - Set up monitoring and alerting
- Configure log aggregation
- Review and tighten security headers
- Perform security scan
- Load test the application
- Set up CI/CD pipeline
- Web Server: Nginx or IIS as reverse proxy
- SSL/TLS: Let's Encrypt or commercial certificate
- Database: Azure SQL Database or AWS RDS
- Storage: Azure Blob Storage or AWS S3
- Monitoring: Application Insights, CloudWatch, or Datadog
- Container Orchestration: Kubernetes or Azure Container Apps (for scale)
- Use managed database services for reliability
- Implement caching (Redis) for frequently accessed data
- Use CDN for static assets
- Configure auto-scaling for containers
- Separate read and write database operations
- Implement queue-based video processing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow C# and Angular coding conventions
- Write unit tests for new features
- Update documentation as needed
- Ensure all tests pass before submitting PR
- Keep commits atomic and well-described
[Add your license information here]
- Issues: GitHub Issues
- Security: See SECURITY.md
- Email: [support@podiumapp.com]
Made with ❤️ for the college band community