This guide explains how to configure and manage the EduLift deep link system across different environments. The system uses a three-tier fallback strategy to ensure reliable URL generation for mobile app deep linking and web fallbacks.
- Development: Local development with custom protocol
- E2E Testing: Automated testing environment
- Staging: Pre-production testing on real infrastructure
- Production: Live production environment
- DEEP_LINK_BASE_URL: Primary deep link URL for mobile apps
- FRONTEND_URL: Web fallback URL
- Emergency Fallback: localhost URL for development
Purpose: Local development and testing
Configuration:
# .env.development
NODE_ENV=development
DEEP_LINK_BASE_URL=edulift://
FRONTEND_URL=http://localhost:3000Behavior:
- Uses
edulift://custom protocol for mobile app deep linking - Falls back to
http://localhost:3000for web access - Enables debug logging for URL generation troubleshooting
Use Cases:
- Local development with mobile app simulator
- Testing deep link functionality
- Debugging URL generation logic
Purpose: Automated end-to-end testing
Configuration:
# .env.e2e
NODE_ENV=e2e
DEEP_LINK_BASE_URL=edulift://
FRONTEND_URL=http://localhost:3000Behavior:
- Same as development for consistency in automated tests
- Optimized for CI/CD pipeline integration
- Mock mobile app behavior for testing
Use Cases:
- Automated testing of deep link flows
- CI/CD pipeline integration
- Regression testing
Purpose: Pre-production testing on real infrastructure
Configuration:
# Generated by Ansible
NODE_ENV=staging
DEEP_LINK_BASE_URL=https://transport.tanjama.fr:50443/
FRONTEND_URL=https://transport.tanjama.fr:50443Behavior:
- Uses HTTPS with custom port (50443) for staging
- Real infrastructure testing with production-like setup
- Allows testing on physical mobile devices
Use Cases:
- User acceptance testing (UAT)
- Mobile device testing on real hardware
- Performance and load testing
Purpose: Live production deployment
Configuration:
# Generated by Ansible
NODE_ENV=production
DEEP_LINK_BASE_URL=https://transport.tanjama.fr/
FRONTEND_URL=https://transport.tanjama.frBehavior:
- Standard HTTPS on port 443
- Optimized for production mobile app experience
- Enhanced security validation
Use Cases:
- Live user interactions
- Production mobile app deep linking
- Real-world usage scenarios
File: deploy/ansible/templates/_url_macros.j2
The deep link URLs are generated dynamically using Jinja2 macros:
{% macro deep_link_url(environment) -%}
{% if environment in ['development', 'e2e'] %}
edulift://
{% elif environment == 'staging' %}
{{ protocol }}://{{ base_domain }}:50443/
{% elif environment == 'production' %}
{{ protocol }}://{{ base_domain }}{% if https_port != 443 %}:{{ https_port }}{% endif %}/
{% endif %}
{%- endmacro %}Usage in Environment Template:
{# deploy/ansible/templates/env.j2 #}
{% set deep_link_base_url = url.deep_link_url(deployment_environment) %}
DEEP_LINK_BASE_URL={{ deep_link_base_url }}File: inventory/group_vars/all.yml
edulift_deployment:
urls:
deep_link_base: "https://custom.example.com/"
frontend: "https://custom.example.com"
backend: "https://api.custom.example.com"
traefik_dashboard: "https://traefik.custom.example.com"Priority: Manual overrides take precedence over generated URLs
File: .env.local
# Override for local testing
DEEP_LINK_BASE_URL=https://dev.example.com/
FRONTEND_URL=https://dev.example.comUse Case: Temporary local testing with specific configuration
The system uses a three-tier fallback approach:
- Primary:
DEEP_LINK_BASE_URL(environment-specific) - Secondary:
FRONTEND_URL(web fallback) - Tertiary:
http://localhost:3000(emergency fallback)
// BaseEmailService.generateUrl()
protected generateUrl(path: string, params?: URLSearchParams): string {
const candidateUrls = [
process.env.DEEP_LINK_BASE_URL,
process.env.FRONTEND_URL,
'http://localhost:3000'
];
// Try each URL until finding a valid one
for (let i = 0; i < candidateUrls.length; i++) {
const candidateUrl = candidateUrls[i];
if (candidateUrl && this.validateDeepLinkUrl(candidateUrl)) {
urlSource = i === 0 ? 'DEEP_LINK_BASE_URL' :
i === 1 ? 'FRONTEND_URL' :
'localhost fallback';
return this.buildUrl(candidateUrl, path, params);
}
}
}All URLs undergo comprehensive security validation:
// Security checks performed
- Protocol validation (http, https, edulift)
- Hostname security validation
- Private IP blocking in production
- XSS and injection pattern detection
- Format validationDevelopment/E2E:
- Allows localhost and private IPs
- Relaxed security for local testing
- Debug logging enabled
Staging/Production:
- Blocks private IP addresses
- Enhanced hostname validation
- Suspicious pattern detection
- Production logging only
File: backend/src/services/__tests__/BaseEmailService.test.ts
describe('Deep Link URL Generation', () => {
test('generates correct URLs for each environment', () => {
// Test development URLs
process.env.DEEP_LINK_BASE_URL = 'edulift://';
const devUrl = emailService.generateUrl('groups/join', params);
expect(devUrl).toBe('edulift://groups/join?code=ABC123');
// Test staging URLs
process.env.DEEP_LINK_BASE_URL = 'https://staging.example.com/';
const stagingUrl = emailService.generateUrl('groups/join', params);
expect(stagingUrl).toBe('https://staging.example.com/groups/join?code=ABC123');
});
});Test Environment Setup:
# Set up test environment
export NODE_ENV=test
export DEEP_LINK_BASE_URL=https://test.example.com/
export FRONTEND_URL=https://test.example.com
# Run integration tests
npm run test:integrationSymptoms:
- Mobile app doesn't open when clicking deep links
- Links open in web browser instead of app
Solutions:
- Verify app association with
edulift://protocol - Check universal link configuration for HTTPS URLs
- Ensure mobile app is properly installed
- Test with different mobile devices
Verification Commands:
# Test deep link URL format
curl -I "edulift://groups/join?code=TEST123"
# Test HTTPS deep link
curl -I "https://transport.tanjama.fr/groups/join?code=TEST123"Symptoms:
- Primary deep link fails but fallback doesn't work
- Broken links in email notifications
Solutions:
- Verify
FRONTEND_URLconfiguration - Check network connectivity to fallback URLs
- Test URL validation logic
- Verify Ansible template generation
Debug Steps:
# Check environment variables
echo $DEEP_LINK_BASE_URL
echo $FRONTEND_URL
# Test URL generation
npm run test:unit -- --testNamePattern="generateUrl"Symptoms:
- URLs rejected by security validation
- Console warnings about invalid URLs
Solutions:
- Review URL format and protocol
- Check for suspicious patterns in hostname
- Verify environment-specific security rules
- Update validation rules if needed
Debug Logging:
// Enable debug logging
process.env.NODE_ENV = 'development';
// Check console for validation details# Show current configuration
echo "Node Environment: $NODE_ENV"
echo "Deep Link Base URL: $DEEP_LINK_BASE_URL"
echo "Frontend URL: $FRONTEND_URL"
# Test URL generation
node -e "
const { BaseEmailService } = require('./dist/services/base/BaseEmailService');
console.log('Generated URL:', new TestEmailService().generateUrl('test'));
"# Test template generation
ansible-playbook -i inventory/test playbooks/deploy.yml \
--tags=debug \
--extra-vars="deployment_environment=staging"
# Show rendered environment file
cat .generated/env-staging.txtOld Configuration:
# Legacy system
PLATFORM=fcm
INVITE_BASE_URL=https://app.example.com/inviteNew Configuration:
# New deep link system
DEEP_LINK_BASE_URL=https://app.example.com/
FRONTEND_URL=https://app.example.comMigration Steps:
- Update Ansible templates
- Modify environment configuration files
- Update application code to use
generateUrl() - Test all deep link flows
- Update documentation
- v1.x: Legacy platform-based system
- v2.x: Current deep link system with fallbacks
- v3.x: Future enhancements (planned)
- Use Ansible Templates: Avoid hardcoded URLs
- Environment-Specific: Different configurations per environment
- Override Support: Allow manual overrides when needed
- Validation: Always validate URLs before deployment
- Protocol Validation: Only allow approved protocols
- Hostname Security: Block suspicious hostnames
- Environment Isolation: Different security rules per environment
- Regular Audits: Review URL validation rules
- Unit Tests: Test URL generation logic
- Integration Tests: Test end-to-end flows
- Environment Testing: Test all environments
- Mobile Testing: Test on real mobile devices
- URL Generation Logs: Monitor URL source and validation
- Error Tracking: Track failed URL generation
- Performance: Monitor URL generation performance
- Usage Analytics: Track deep link usage patterns
- URL Macros:
deploy/ansible/templates/_url_macros.j2 - Environment Template:
deploy/ansible/templates/env.j2 - Base Email Service:
backend/src/services/base/BaseEmailService.ts - Unit Tests:
backend/src/services/__tests__/BaseEmailService.test.ts
| Variable | Purpose | Example |
|---|---|---|
DEEP_LINK_BASE_URL |
Primary deep link URL | edulift:// |
FRONTEND_URL |
Web fallback URL | https://app.example.com |
NODE_ENV |
Environment identifier | production |
https_port |
HTTPS port configuration | 443 |
base_domain |
Base domain name | transport.tanjama.fr |
# Generate configuration for specific environment
ansible-playbook -i inventory/production playbooks/configure.yml \
--extra-vars="deployment_environment=production"
# Test URL generation locally
npm run test:unit -- --testNamePattern="Deep Link"
# Validate Ansible templates
ansible-playbook -i inventory/test playbooks/deploy.yml \
--check --diff --tags=templates