Deploy and Host Advanced Customizations
The following guide will help you deploy your customized Universal Login screens to production and create a continuous integration and continuous delivery pipeline.
Set up your project
Prepare all your Screens to be uploaded and use the following file structure for your ACUL project:

Create a new Vite configuration
Add the following to a new file named vite.config.ts
:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';
// Screen definitions
const screens = [
{
name: 'login-id',
prompt: 'login-id',
screen: 'login-id'
},
{
name: 'login-password',
prompt: 'login-password',
screen: 'login-password'
},
{
name: 'mfa',
prompt: 'mfa-otp',
screen: 'mfa'
}
];
// Generate input object for all screens
const input = Object.fromEntries(
screens.map(screen => [
screen.name,
resolve(__dirname, `src/${screen.name}/main.tsx`)
])
);
export default defineConfig({
plugins: [react()],
build: {
rollupOptions: {
input,
output: {
// Ensure each screen gets its own directory
dir: 'dist',
entryFileNames: '[name]/index.js',
assetFileNames: '[name]/[name][extname]',
chunkFileNames: '[name]/chunks/[name]-[hash].js',
manualChunks: {
// Split React into a vendor chunk
'vendor-react': ['react', 'react-dom'],
// Split Auth0 SDK into a vendor chunk
'vendor-auth0': ['@auth0/auth0-acul-js']
}
}
},
// Generate sourcemaps for production debugging
sourcemap: true,
// Minify output
minify: 'terser'
}
});
Was this helpful?
Set up build scripts
Create scripts/build.ts
to run your Vite build:
import { build } from 'vite';
async function buildScreens() {
try {
await build();
console.log('Build completed successfully');
} catch (err) {
console.error('Build failed:', err);
process.exit(1);
}
}
buildScreens();
Was this helpful?
Build your AWS infrastructure
Create an S3 bucket and CloudFront distribution:
#Create bucket
aws s3 mb s3://your-acul-assets --region us-east-1
#Enable versioning
aws s3api put-bucket-versioning \
--bucket your-acul-assets \
--versioning-configuration Status=Enabled
#Create CloudFront distribution
aws cloudfront create-distribution \
--origin-domain-name your-acul-assets.s3.amazonaws.com \
--default-root-object index.html \
--default-cache-behavior '{"TargetOriginId":"S3Origin","ViewerProtocolPolicy":"redirect-to-https","AllowedMethods":{"Quantity":2,"Items":["GET","HEAD"]},"CachePolicyId":"658327ea-f89d-4fab-a63d-7e88639e58f6"}'
Was this helpful?
Configure CORS for Auth0
{
"CORSRules": [{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET"],
"AllowedOrigins": [
"https://*.auth0.com",
"https://your-custom-domain.com"
],
"MaxAgeSeconds": 3000
}]
}
Was this helpful?
Create a deployment script
Create scripts/deploy.ts
for AWS deployment:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { CloudFrontClient, CreateInvalidationCommand } from '@aws-sdk/client-cloudfront';
import { readFileSync } from 'fs';
import { resolve } from 'path';
// Screen definitions (keep in sync with vite.config.ts)
const screens = [
'login-id',
'login-password',
'mfa'
];
async function deploy() {
const s3 = new S3Client({ region: 'us-east-1' });
const cloudfront = new CloudFrontClient({ region: 'us-east-1' });
const bucket = process.env.S3_BUCKET;
const distributionId = process.env.CLOUDFRONT_ID;
for (const screen of screens) {
const distPath = resolve(__dirname, `../dist/${screen}`);
// Upload assets
const files = ['index.js', 'index.css', 'vendor-react.js', 'vendor-auth0.js'];
for (const file of files) {
try {
const content = readFileSync(`${distPath}/${file}`);
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: `${screen}/${file}`,
Body: content,
ContentType: file.endsWith('.js') ? 'application/javascript' : 'text/css',
CacheControl: 'max-age=31536000'
}));
} catch (err) {
console.warn(`Skipping ${file} for ${screen}: ${err.message}`);
}
}
}
// Invalidate cache
await cloudfront.send(new CreateInvalidationCommand({
DistributionId: distributionId,
InvalidationBatch: {
CallerReference: Date.now().toString(),
Paths: { Quantity: 1, Items: ['/*'] }
}
}));
}
deploy().catch(console.error);
Was this helpful?
Set up GitHub Actions workflow
Create .github/workflows/deploy.yml
:
name: Deploy ACUL Screens
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Dependencies
run: npm ci
- name: Build Screens
run: npm run build
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Deploy to CloudFront
run: npm run deploy
env:
S3_BUCKET: your-acul-assets
CLOUDFRONT_ID: ${{ secrets.CLOUDFRONT_ID }}
CLOUDFRONT_DOMAIN: ${{ secrets.CLOUDFRONT_DOMAIN }}
- name: Setup Auth0 CLI
run: npm install -g auth0-cli
- name: Configure Auth0 Screens
run: |
# Login to Auth0
auth0 login --token ${{ secrets.AUTH0_DEPLOY_TOKEN }}
# Configure each screen
for screen in login-id login-password mfa; do
# Generate settings file
cat > settings.json << EOF
{
"rendering_mode": "advanced",
"context_configuration": [
"screen.texts",
"branding.settings",
"organization.branding",
"tenant.name",
"tenant.friendly_name"
],
"head_tags": [
{
"tag": "script",
"attributes": {
"src": "https://${{ secrets.CLOUDFRONT_DOMAIN }}/${screen}/vendor-react.js",
"defer": true
}
},
{
"tag": "script",
"attributes": {
"src": "https://${{ secrets.CLOUDFRONT_DOMAIN }}/${screen}/vendor-auth0.js",
"defer": true
}
},
{
"tag": "script",
"attributes": {
"src": "https://${{ secrets.CLOUDFRONT_DOMAIN }}/${screen}/index.js",
"defer": true
}
},
{
"tag": "link",
"attributes": {
"rel": "stylesheet",
"href": "https://${{ secrets.CLOUDFRONT_DOMAIN }}/${screen}/index.css"
}
}
]
}
EOF
# Configure screen
auth0 ul customize \
--rendering-mode advanced \
--prompt ${screen} \
--screen ${screen} \
--settings-file settings.json
done
Was this helpful?
Finally, add these secrets to your GitHub repository:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
CLOUDFRONT_ID
CLOUDFRONT_DOMAIN
AUTH0_DEPLOY_TOKEN