Local Development Setup
This guide covers setting up a complete PhotoFlow development environment.
Prerequisites
Required Software
Software | Version | Purpose |
|---|
.NET SDK | 9.0+ | Backend development |
Node.js | 22.x LTS | Frontend build tooling |
Docker Desktop | Latest | Container runtime |
PostgreSQL | 16+ | Database |
JetBrains Rider | 2024.3+ | Recommended IDE |
VS Code | Latest | Alternative IDE |
Tool | Purpose |
|---|
Azure Data Studio | Database management |
Postman | API testing |
ngrok | Webhook testing |
k9s | Kubernetes monitoring |
Repository Structure
/pfl/
├── pfl01y25-be-app/ # Backend .NET 9 Solution
│ ├── src/
│ │ ├── BuildingBlocks/ # Shared libraries
│ │ └── Services/ # Microservices
│ └── PFL.sln
├── pfl01y25-fe-web/ # Angular Admin Portal
├── photoflow/ # Angular Marketing Site
├── pfl01y25-doc/ # Writerside Documentation
└── devops/ # CI/CD & Infrastructure
Backend Setup
1. Clone Repository
git clone https://gitlab.thontm.site/photoflow/pfl.git
cd pfl/pfl01y25-be-app
2. Restore Dependencies
dotnet restore
Create appsettings.Development.json in each API project:
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Port=5432;Database=pfl-dev;Username=postgres;Password=yourpassword"
},
"Authentication": {
"JwtSecret": "your-development-secret-key-minimum-32-characters",
"Issuer": "PhotoFlow.Development",
"Audience": "PhotoFlow.Api"
},
"Google": {
"ClientId": "your-google-client-id",
"ClientSecret": "your-google-client-secret",
"ServiceAccountEmail": "your-service-account@project.iam.gserviceaccount.com"
},
"SignalR": {
"Enabled": true
},
"Cors": {
"AllowedOrigins": [
"http://localhost:4200",
"http://localhost:4201"
]
},
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Information"
}
}
}
4. Apply Database Migrations
# From pfl01y25-be-app directory
dotnet ef database update \
--project src/Services/Photoflow/Photoflow.Infrastructure \
--startup-project src/Services/Photoflow/Photoflow.API
dotnet ef database update \
--project src/Services/Storage/Storage.Infrastructure \
--startup-project src/Services/Storage/Storage.API
dotnet ef database update \
--project src/Services/Identity/Identity.Infrastructure \
--startup-project src/Services/Identity/Identity.API
dotnet ef database update \
--project src/Services/Organization/Organization.Infrastructure \
--startup-project src/Services/Organization/Organization.API
5. Run Services
Option A: Run all services (recommended):
dotnet run --project src/Services/AppGateway/AppGateway.API
dotnet run --project src/Services/Photoflow/Photoflow.API
dotnet run --project src/Services/Storage/Storage.API
dotnet run --project src/Services/Identity/Identity.API
dotnet run --project src/Services/Organization/Organization.API
dotnet run --project src/Services/Provider/Provider.API
dotnet run --project src/Services/Sender/Sender.API
Option B: Use Docker Compose:
docker-compose up -d
Service Ports
Service | HTTP Port | HTTPS Port |
|---|
AppGateway | 5000 | 5001 |
Photoflow | 5010 | 5011 |
Storage | 5020 | 5021 |
Identity | 5030 | 5031 |
Organization | 5040 | 5041 |
Provider | 5050 | 5051 |
Sender | 5060 | 5061 |
Frontend Setup
Admin Portal (pfl01y25-fe-web)
cd pfl01y25-fe-web
npm install
npm start
Access at: http://localhost:4200
Marketing Site (photoflow)
cd photoflow
npm install
npm start
Access at: http://localhost:4201
Environment Configuration
Create src/environments/environment.development.ts:
export const environment = {
production: false,
apiBaseUrl: 'http://localhost:5000/api',
signalRUrl: 'http://localhost:5000/hubs',
google: {
clientId: 'your-google-client-id'
}
};
Docker Development
Build Images
# Backend services
docker build -t photoflow-api:dev -f src/Services/Photoflow/Photoflow.API/Dockerfile .
docker build -t storage-api:dev -f src/Services/Storage/Storage.API/Dockerfile .
# Frontend
docker build -t photoflow-fe:dev -f pfl01y25-fe-web/Dockerfile pfl01y25-fe-web
Docker Compose Stack
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: pfl-dev
POSTGRES_USER: postgres
POSTGRES_PASSWORD: development
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
photoflow-api:
build:
context: ./pfl01y25-be-app
dockerfile: src/Services/Photoflow/Photoflow.API/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__DefaultConnection=Host=postgres;Port=5432;Database=pfl-dev;Username=postgres;Password=development
ports:
- "5010:80"
depends_on:
- postgres
- redis
volumes:
postgres_data:
Database Management
PostgreSQL via Docker
docker run -d \
--name pfl-postgres \
-e POSTGRES_DB=pfl-dev \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=development \
-p 5432:5432 \
postgres:16-alpine
Seed Data
dotnet run --project src/Services/Photoflow/Photoflow.API -- seed
Database Reset
# Drop and recreate
dropdb pfl-dev
createdb pfl-dev
# Re-apply migrations
dotnet ef database update --project src/Services/Photoflow/Photoflow.Infrastructure --startup-project src/Services/Photoflow/Photoflow.API
IDE Configuration
JetBrains Rider
Open PFL.sln
Configure Run Configurations for each service
Enable hot reload: Preferences → Build → On Run → Build only modified projects
VS Code
Install recommended extensions:
C# Dev Kit
REST Client
Docker
PostgreSQL
Launch configuration (.vscode/launch.json):
{
"version": "0.2.0",
"configurations": [
{
"name": "Photoflow API",
"type": "coreclr",
"request": "launch",
"program": "${workspaceFolder}/src/Services/Photoflow/Photoflow.API/bin/Debug/net9.0/Photoflow.API.dll",
"args": [],
"cwd": "${workspaceFolder}/src/Services/Photoflow/Photoflow.API",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
]
}
Debugging
API Debugging
Set breakpoints in Visual Studio / Rider
Attach debugger to running process
Use curl or Postman for requests
SignalR Debugging
Enable detailed logging:
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.SignalR": "Debug",
"Microsoft.AspNetCore.Http.Connections": "Debug"
}
}
}
Database Query Logging
{
"Logging": {
"LogLevel": {
"Microsoft.EntityFrameworkCore.Database.Command": "Information"
}
}
}
Common Issues
Port Already in Use
# Find process using port
lsof -i :5010
kill -9 <PID>
Migration Errors
# Reset migrations
dotnet ef migrations remove --project src/Services/Photoflow/Photoflow.Infrastructure --startup-project src/Services/Photoflow/Photoflow.API
dotnet ef migrations add Initial --project src/Services/Photoflow/Photoflow.Infrastructure --startup-project src/Services/Photoflow/Photoflow.API
CORS Issues
Verify appsettings.Development.json includes frontend origin:
{
"Cors": {
"AllowedOrigins": ["http://localhost:4200"]
}
}
Google API Authentication
Create OAuth 2.0 credentials in Google Cloud Console
Add redirect URIs: http://localhost:5000/api/auth/callback
Enable Drive API
Testing
Running Unit Tests
dotnet test PFL.sln
Running Integration Tests
dotnet test PFL.sln --filter "Category=Integration"
API Testing with REST Client
Create .http files for API testing:
### Get Albums
GET http://localhost:5010/api/albums
Authorization: Bearer {{token}}
### Create Album
POST http://localhost:5010/api/albums
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "Test Album",
"providerId": "{{providerId}}"
}
Last modified: 25 February 2026