Deploy the website
Build the React app with your API address baked in and upload it to the S3 bucket.
About 20 min · Verified 8 October 2026
The website is a build artifact: Vite compiles the React source into a folder of static files (dist/). You will build it on your computer and upload it to S3 once, by hand. In the CI/CD guide the same build and upload are done by AWS for you on every push.
The one thing that trips everyone up#
Vite reads VITE_API_BASE_URL while it builds and writes its value into the JavaScript files. It is not read when the page loads. So:
- Set the variable before you build.
- If you change the API address later, you must rebuild and upload again.
- The value is visible to anyone who views the page source. Never put a secret in a
VITE_variable.
Build and upload#
Install the dependencies#
From the root of your clone on your computer:
npm --prefix shortlink-web ciBuild with your API address#
The value is your load balancer's address: <API_URL>. No trailing slash.
VITE_API_BASE_URL=<API_URL> npm --prefix shortlink-web run buildReplace <API_URL> with your own value (or fill in the known ones once under My values at the top of the page).
$env:VITE_API_BASE_URL = "<API_URL>"
npm --prefix shortlink-web run buildReplace <API_URL> with your own value (or fill in the known ones once under My values at the top of the page).
dist/ (an index.html and an assets/ folder) and ends with ✓ built in ….Confirm the address really was baked in:
grep -rl "<ALB_DNS>" shortlink-web/dist/assets | head -n 3Replace <ALB_DNS> with your own value (or fill in the known ones once under My values at the top of the page).
Select-String -Path shortlink-web/dist/assets/*.js -Pattern "<ALB_DNS>" -List | Select-Object -First 3 PathReplace <ALB_DNS> with your own value (or fill in the known ones once under My values at the top of the page).
You should see at least one .js file. No result means the variable was not set when you built; set it and build again.
Upload the contents of dist/#
Upload the contents of dist, so that index.html sits at the root of the bucket. --delete removes files from earlier builds that no longer exist.
aws s3 sync shortlink-web/dist/ s3://<WEB_BUCKET>/ --delete --region ap-south-1Replace <WEB_BUCKET> with your own value (or fill in the known ones once under My values at the top of the page).
Then give index.html a no-cache header so browsers always fetch the newest copy (the other files have content hashes in their names and are safe to cache):
aws s3 cp shortlink-web/dist/index.html s3://<WEB_BUCKET>/index.html \
--cache-control 'no-cache' --content-type 'text/html' --region ap-south-1Replace <WEB_BUCKET> with your own value (or fill in the known ones once under My values at the top of the page).
Open the website#
Open <WEB_URL> in your browser.
Check it from the command line too#
curl -sI <WEB_URL>/ | head -n 3
aws s3api head-object --bucket <WEB_BUCKET> --key index.html --region ap-south-1 \
--query '{type:ContentType,cache:CacheControl,modified:LastModified}'Replace <WEB_URL> <WEB_BUCKET> with your own value (or fill in the known ones once under My values at the top of the page).
HTTP/1.1 200 OK, ContentType: text/html, CacheControl: no-cache.Next: verify everything end to end.
Found a mistake? Edit this page on GitHub.