diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..500c0cf
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,24 @@
+FROM node:lts-alpine3.23 AS builder
+
+WORKDIR /app
+
+COPY package*.json ./
+COPY pnpm-lock.yaml* yarn.lock* ./
+
+RUN npm install
+COPY . .
+RUN npm run build
+
+FROM nginx:stable-alpine AS production
+
+RUN apk add --no-cache gettext
+
+RUN rm -rf /usr/share/nginx/html/*
+COPY --from=builder /app/dist /usr/share/nginx/html
+
+COPY public/env.template.js /usr/share/nginx/html/env.template.js
+COPY docker-entrypoint.sh /docker-entrypoint.sh
+RUN chmod +x /docker-entrypoint.sh
+
+EXPOSE 80
+ENTRYPOINT ["/docker-entrypoint.sh"]
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh
new file mode 100644
index 0000000..91709d5
--- /dev/null
+++ b/docker-entrypoint.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+set -e
+
+# Replace placeholders in env.template.js with environment variables and write env.js
+TEMPLATE_PATH="/usr/share/nginx/html/env.template.js"
+TARGET_PATH="/usr/share/nginx/html/env.js"
+
+if [ -f "$TEMPLATE_PATH" ]; then
+ echo "Rendering runtime config from $TEMPLATE_PATH"
+ # export all variables for envsubst to access
+ # only substitute variables present in the template
+ envsubst < "$TEMPLATE_PATH" > "$TARGET_PATH"
+else
+ echo "No runtime template found at $TEMPLATE_PATH, skipping"
+fi
+
+# Start nginx in foreground
+exec nginx -g 'daemon off;'
+
diff --git a/env.d.ts b/env.d.ts
index 11f02fe..70b745d 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -1 +1,7 @@
///