Arivu deploy and static hosting
Auth and presigned zip API details stay in Arivu on Keystone, S3, and CloudFront.
GitHub Actions
Workflow: .github/workflows/deploy.yml. Trigger: workflow_dispatch (manual run).
Environment: staging on GitHub. Vars and secrets expected there include:
STAGING_AWS_REGION,STAGING_S3_BUCKET,STAGING_CLOUDFRONT_DISTRIBUTION_IDKNOWLEDGE_S3_BUCKET(target for the markdown zip)PUBLIC_API_BASE_URL,PUBLIC_COURSE_ID,PUBLIC_REDIRECT_PLATFORM_ID,PUBLIC_AUTH_APPLICATION,PUBLIC_APP_VERSION(injected atnpm run build)- AWS keys:
STAGING_AWS_ACCESS_KEY_ID,STAGING_AWS_SECRET_ACCESS_KEY
Steps (summary): checkout, Node 22, npm ci, npm run build, assert dist/ exists, aws s3 sync dist/ to the staging bucket with --delete, cloudfront create-invalidation on /*, wait until invalidation completes, zip knowledge_docs/ and aws s3 cp to s3://$KNOWLEDGE_S3_BUCKET/arivu/private/knowledge_docs_latest.zip.
Stale or wrong UI
Confirm the workflow finished and dist/ was synced. Run a CloudFront invalidation for /* if edge cache still serves old HTML or assets. Check cache headers if problems persist.
Pretty URLs and Astro output
Astro writes directory-style pages (e.g. login/index.html). S3 REST and CloudFront do not always map /login to that object. A 404 or 403 plus a custom error response that returns /index.html with status 200 will show the home page while the URL still says /login.
Fix: use a CloudFront viewer-request function (or equivalent) so paths without a file extension resolve to …/index.html. Set DefaultRootObject to index.html where appropriate. Avoid a blanket SPA fallback that serves /index.html for every missing path on this multi-page site.
Example viewer-request handler (validate against your distribution):
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.includes(".") || uri.startsWith("/_astro/")) return request;
if (uri === "/" || uri === "") {
request.uri = "/index.html";
return request;
}
if (uri.endsWith("/")) request.uri += "index.html";
else request.uri += "/index.html";
return request;
}