Skip to content

Local Development with Azure Preview

S5 local development connects directly to the Azure preview environment - no local Docker services required.

Architecture

┌─────────────────────────────────┐
│   Your Local Machine            │
│                                 │
│  ┌──────────────────────────┐   │
│  │  Web (uvicorn)           │   │
│  │  localhost:8080          │   │
│  └──────────────────────────┘   │
│                                 │
│  ┌──────────────────────────┐   │
│  │  Worker (celery)         │   │
│  └──────────────────────────┘   │
└─────────────────────────────────┘
         │ (connects to)
┌─────────────────────────────────┐
│   Azure Preview Environment     │
│                                 │
│  • PostgreSQL Database          │
│  • Redis Cache                  │
│  • Blob Storage                 │
│  • Azure AD                     │
└─────────────────────────────────┘

Prerequisites

  1. Python 3.11+ installed
  2. Access to Azure preview environment:
  3. Database connection credentials
  4. Redis connection credentials
  5. Azure Blob Storage credentials
  6. Azure AD application credentials
  7. slidefactory-core package (installed automatically)

Setup

1. Clone Repository

git clone <s5-slidefactory-repo-url>
cd s5-slidefactory
git checkout preview

2. Create Virtual Environment

python3.11 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

3. Install S5 Package

The S5 package automatically installs slidefactory-core as a dependency:

# Install S5 with Azure dependencies
pip install -e ".[azure]"

This will: - Install slidefactory-core from the local sibling directory (../slidefactory-core) - Install S5 branding package - Install Azure-specific dependencies (azure-storage-blob, azure-identity, etc.)

4. Configure Environment

Copy the Azure preview environment template:

cp .env.s5 .env

Edit .env with your Azure preview credentials:

# S5 Configuration
CLIENT_NAME="SportFive Slidefactory"
CLIENT_LOGO="/s5_branding/static/img/sportfive_logo.png"
CLIENT_PRIMARY_COLOR="#ee0000"

# Database (Azure PostgreSQL preview)
DATABASE_URL="postgresql://user:password@postgres-preview.postgres.database.azure.com:5432/slidefactory"

# Redis (Azure Cache for Redis preview)
REDIS_HOST="redis-preview.redis.cache.windows.net"
REDIS_PORT="6380"
REDIS_PASSWORD="your-redis-password"
REDIS_SSL="true"

# Storage (Azure Blob Storage preview)
STORAGE_PROVIDER="azure"
AZURE_STORAGE_ACCOUNT_NAME="slidefactorypreview"
AZURE_STORAGE_ACCOUNT_KEY="your-storage-account-key"

# Auth (Azure AD)
AZURE_TENANT_ID="your-tenant-id"
AZURE_CLIENT_ID="your-client-id"
AZURE_CLIENT_SECRET="your-client-secret"
AZURE_REDIRECT_URI="http://localhost:8080/auth/azure/callback"

# AI (Azure OpenAI or OpenAI)
AZURE_OPENAI_API_KEY="your-azure-openai-key"
AZURE_OPENAI_ENDPOINT="https://your-openai.openai.azure.com/"
# Or use OpenAI
OPENAI_API_KEY="sk-..."

# N8N Integration
N8N_API_URL="https://n8n-preview.example.com"
N8N_API_KEY="your-n8n-api-key"

# Jina AI (for document processing)
JINA_API_KEY="your-jina-api-key"

5. Initialize Database (First Time Only)

If the preview database is not initialized, run:

slidefactory init all

This will: - Check database connection - Run migrations (Alembic) - Create admin user (if needed)

Running Locally

Start Web Server

./start.sh

This script runs:

uvicorn slidefactory.app.main:app --host 0.0.0.0 --port 8080 --reload

Access: http://localhost:8080

Start Celery Worker

In a separate terminal:

source .venv/bin/activate  # Activate venv again
./start-worker.sh

This script runs:

celery -A slidefactory.app.celery_app worker --loglevel=info --concurrency=2 --autoreload

Development Workflow

1. Make Code Changes

Edit files in: - s5_branding/ - S5 branding assets (logos, CSS) - Any other S5-specific configuration files

Note: Core application code lives in slidefactory-core repository, not in S5 repo.

2. Test Locally

The web server automatically reloads when you change Python files (thanks to --reload flag).

For frontend changes (CSS, images), refresh browser to see changes.

3. Commit and Push to Preview

git add .
git commit -m "Description of changes"
git push origin preview

This triggers automatic deployment to Azure preview environment.

4. Test on Preview

After GitHub Actions completes (~5-10 minutes), test on: https://slidefactory-preview.sportfive.com

Common Tasks

View Logs

# Web server logs (terminal where start.sh is running)
# Celery worker logs (terminal where start-worker.sh is running)

Run Database Migrations

# Apply migrations
alembic upgrade head

# Create new migration (if you modified core models - rare for S5)
alembic revision --autogenerate -m "description"

Use CLI

# List users
slidefactory user list

# Create API key
slidefactory api-key create "Dev Key" --user-id 1

# Generate presentation
slidefactory presentation generate --template-id 123

Update Core Package

If slidefactory-core is updated:

# Pull latest core changes
cd ../slidefactory-core
git pull
cd ../s5-slidefactory

# Reinstall (will pick up core changes)
pip install -e ".[azure]" --force-reinstall

Troubleshooting

Issue: Cannot Connect to Database

Error: psycopg2.OperationalError: could not connect to server

Solutions: 1. Verify DATABASE_URL in .env is correct 2. Check if your IP is whitelisted in Azure PostgreSQL firewall rules 3. Test connection: psql "${DATABASE_URL}" 4. Verify database server is running in Azure Portal

Issue: Cannot Connect to Redis

Error: redis.exceptions.ConnectionError

Solutions: 1. Verify REDIS_HOST, REDIS_PORT, REDIS_PASSWORD in .env 2. Ensure REDIS_SSL=true for Azure Redis 3. Check if your IP is whitelisted in Azure Redis firewall rules 4. Test connection: redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT} -a ${REDIS_PASSWORD} --tls ping

Issue: Azure Blob Storage Access Denied

Error: azure.core.exceptions.ClientAuthenticationError

Solutions: 1. Verify AZURE_STORAGE_ACCOUNT_NAME and AZURE_STORAGE_ACCOUNT_KEY in .env 2. Check storage account access keys in Azure Portal 3. Verify storage account firewall rules allow your IP 4. Ensure storage account exists and is accessible

Issue: Import Errors for Core Package

Error: ModuleNotFoundError: No module named 'slidefactory.app'

Solutions: 1. Ensure you installed with pip install -e ".[azure]" 2. Verify virtual environment is activated: which python should show .venv/bin/python 3. Check if slidefactory-core sibling directory exists: ls ../slidefactory-core 4. Reinstall: pip install -e ".[azure]" --force-reinstall

Issue: Azure AD Login Fails Locally

Error: Redirect loop or authentication error

Solutions: 1. Ensure AZURE_REDIRECT_URI is set to http://localhost:8080/auth/azure/callback 2. Add http://localhost:8080/auth/azure/callback to Azure AD app registration redirect URIs 3. Verify AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET are correct 4. Check Azure AD app registration has proper API permissions

Issue: N8N Workflows Don't Execute

Error: HTTPError: 401 Unauthorized when triggering workflow

Solutions: 1. Verify N8N_API_URL and N8N_API_KEY in .env 2. Test N8N connection: curl -H "X-N8N-API-KEY: ${N8N_API_KEY}" ${N8N_API_URL}/workflows 3. Ensure N8N preview instance is running 4. Check N8N API key is valid (regenerate if needed)

Best Practices

  1. Always use preview environment for development - Don't connect to production resources
  2. Keep .env secure - Never commit .env to Git
  3. Use feature branches - Create branches from preview for new features
  4. Test thoroughly locally - Verify changes work before pushing to preview
  5. Monitor resource usage - Be mindful of Azure preview environment usage
  6. Coordinate with team - Let team know if you're using preview environment
  7. Clean up test data - Remove test presentations/templates after development

VS Code Configuration

Recommended .vscode/settings.json:

{
  "python.defaultInterpreterPath": ".venv/bin/python",
  "python.envFile": "${workspaceFolder}/.env",
  "python.linting.enabled": true,
  "python.linting.pylintEnabled": false,
  "python.linting.flake8Enabled": true,
  "python.formatting.provider": "black",
  "editor.formatOnSave": true,
  "[python]": {
    "editor.defaultFormatter": "ms-python.black-formatter"
  }
}