ShortRace Analytics Frontend is the dashboard layer of the ShortRace ecosystem. Built with Svelte 5 + Vite + TypeScript, it visualizes click-tracking analytics for shortened links ā rendering daily breakdowns and stat summaries in real time. Deployed on AWS as a fully static SPA served through CloudFront CDN with a private S3 backend. Every CI/CD step runs inside a Docker container to guarantee environment parity between local and GitHub Actions.
chart.js wrapped in a reusable LineChart.svelte component.dockerfile.ci image ā no environment drift between local and CI.node:22-alpine with aws-cli baked in covers type checks, test runs, and S3 deployments from the same base.index.html for client-side routing.develop, and executes the full Deploy chain on main.aws s3 sync --delete replaces only changed files, followed by an automatic CloudFront cache invalidation..
āāā .github/
ā āāā docker/
ā ā āāā dockerfile.ci # CI Docker image (node:22-alpine + aws-cli)
ā āāā events/
ā ā āāā push-develop.json # act event payload for develop branch
ā ā āāā push-main.json # act event payload for main branch
ā āāā workflows/
ā āāā ci-cd.yml # GitHub Actions pipeline
āāā terraform/
ā āāā provider.tf # AWS provider & Terraform version
ā āāā variables.tf # Input variables
ā āāā s3.tf # Private S3 bucket + OAC bucket policy
ā āāā cloudfront.tf # CloudFront distribution + OAC
ā āāā outputs.tf # Bucket name, distribution ID, public URL
āāā src/
āāā core/
ā āāā api/ # Axios HTTP client
ā āāā models/ # Domain models (Metric, DateRange)
ā āāā services/ # Metrics service (business logic)
ā āāā stores/ # Svelte reactive stores (Toast)
āāā lib/
āāā components/ # Reusable UI components (StatCard, LineChart, Toast)
āāā features/ # Page-level feature components (Dashboard)
| Metrics Page |
|
Clone the repository
git clone https://github.com/MaySalguedo/SHORTRACE-ANALYTICS-FRONTEND.git
cd SHORTRACE-ANALYTICS-FRONTEND
npm install
Start the dev server
npm run dev
Run the full quality gate before pushing
# svelte-check + tsc + eslint + vitest coverage ā all in sequence
npm run validate
Provision AWS resources for the first time
# Initializes Terraform state and applies the full infrastructure
npm run compile:init
Update infrastructure after changes
npm run compile
Preview changes without applying
npm run tf:plan
Tear down all resources
npm run tf:destroy
Export the required environment variables and run:
export S3_BUCKET_NAME=your-bucket-name
export CLOUDFRONT_DISTRIBUTION_ID=your-distribution-id
# Build, sync to S3 and invalidate CloudFront in one command
npm run deploy
You can retrieve both values after provisioning with
npm run tf:output.
npm-run-all (run-s) for sequential script chaining.node:22-alpine + aws-cli) ā same image locally and in GitHub Actions.The pipeline runs automatically on every push. All jobs build and run the same Docker image (dockerfile.ci) ā guaranteeing identical behaviour between your machine and GitHub's runners.
All branches: Lint
develop: Lint ā Check (ts) ā Test
main: Lint ā Test ā Deploy
| Branch | Lint | Check (ts) | Test | Deploy |
|---|---|---|---|---|
feature/*, fix/*, etc. |
ā | ā | ā | ā |
develop |
ā | ā | ā | ā |
main |
ā | ā | ā | ā |
.github/docker/dockerfile.ci.npm run deploy inside the container, which chains:build ā deploy:s3 ā deploy:invalidate-e flags ā never baked into the image.Navigate to Settings ā Secrets and variables ā Actions in your repository and add:
Secrets
| Secret | Description |
|---|---|
SHORTRACE_AWS_ACCESS_KEY_ID |
IAM user access key with S3 write + CloudFront invalidation permissions |
SHORTRACE_AWS_SECRET_ACCESS_KEY |
Secret key for the IAM user above |
SHORTRACE_AWS_REGION |
AWS region where resources are deployed (e.g. us-east-1) |
SHORTRACE_S3_BUCKET_NAME |
S3 bucket name ā from Terraform output s3_bucket_name |
SHORTRACE_CLOUDFRONT_DISTRIBUTION_ID |
Distribution ID ā from Terraform output cloudfront_distribution_id |
Variables (non-sensitive, visible in logs)
| Variable | Description |
|---|---|
VITE_API_URL |
Base URL of the ShortRace metrics API (e.g. https://api.shortrace.com) |
š” Run
npm run tf:outputafter provisioning to getSHORTRACE_S3_BUCKET_NAMEandSHORTRACE_CLOUDFRONT_DISTRIBUTION_ID.
The pipeline can be tested locally with Docker and act before pushing. Event payloads are pre-configured in .github/events/.
docker build -t shortrace-ci -f .github/docker/dockerfile.ci .
# Lint
docker run --rm shortrace-ci npm run lint
# Type check
docker run --rm shortrace-ci npm run check
# Tests with coverage
docker run --rm shortrace-ci npm run test:cov
Create a .secrets and .vars on the root directory to store the secrets and variables.
Install act following the official guide, then:
# Simulate a push to develop (runs Lint ā Check ā Test)
act push -e .github/events/push-develop.json
# Simulate a push to main (runs Lint ā Check ā Test ā Deploy)
act push -e .github/events/push-main.json --secret-file .secrets --var-file .vars
actuses the sameubuntu-latestrunner image by default. Since jobs builddockerfile.cithemselves, Docker must be running on your machine.
The .github/events/ folder contains minimal push payloads that tell act which branch to simulate:
// push-develop.json
{ "ref": "refs/heads/develop" }
// push-main.json
{ "ref": "refs/heads/main" }
| Script | Description |
|---|---|
npm run dev |
Start Vite dev server with HMR |
npm run build |
Production build ā dist/ |
npm run preview |
Preview the production build locally |
npm run check:app |
Run svelte-check against tsconfig.app.json |
npm run check:node |
Run tsc against tsconfig.node.json |
npm run check |
check:app ā check:node in sequence |
npm run lint |
Run ESLint across all source files |
npm run format |
Auto-format with Prettier |
npm run test |
Run Vitest once (no coverage) |
npm run test:cov |
Run Vitest with V8 coverage report |
npm run validate |
check ā lint ā test:cov in sequence |
npm run tf:init |
Initialize Terraform state |
npm run tf:plan |
Preview infrastructure changes |
npm run tf:apply |
Apply infrastructure changes |
npm run tf:destroy |
Destroy all provisioned resources |
npm run tf:output |
Print Terraform outputs |
npm run compile:init |
tf:init ā tf:apply ā tf:output (first deploy) |
npm run compile |
tf:apply ā tf:output (subsequent deploys) |
npm run deploy:s3 |
Sync dist/ to S3 (--delete + cache headers) |
npm run deploy:invalidate |
Create CloudFront cache invalidation for /* |
npm run deploy |
build ā deploy:s3 ā deploy:invalidate |
After running npm run compile:init or npm run tf:output, Terraform prints:
| Output | Description |
|---|---|
s3_bucket_name |
Bucket name ā use as SHORTRACE_S3_BUCKET_NAME secret |
s3_bucket_arn |
Full ARN of the bucket |
cloudfront_distribution_id |
Distribution ID ā use as SHORTRACE_CLOUDFRONT_DISTRIBUTION_ID secret |
cloudfront_domain_name |
Public HTTPS URL of the deployed dashboard |
This software is released under the MIT License.
You are free to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software.
Developed with love ā Cartagena de Indias D.T. y C.
š OPEN SOURCE SOFTWARE ā FREE TO DISTRIBUTE š