Compare commits

...

4 commits

Author SHA1 Message Date
saiminh
3108c0628a config for oublic vars and secrets 2026-02-16 12:00:12 +01:00
saiminh
b165d65acb legace peer deps 2026-02-16 11:05:33 +01:00
saiminh
63af976671 change brevo api env 2026-02-16 11:05:15 +01:00
saiminh
b8e2771875 updating dependencies 2026-02-16 10:58:22 +01:00
9 changed files with 881 additions and 521 deletions

27
.dockerignore Normal file
View file

@ -0,0 +1,27 @@
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
build
.svelte-kit
package
dist
.env
.env.*
!.env.example
.idea
.vscode
.DS_Store
.git
.gitignore
logs
*.log
coverage
.nyc_output
*.md
!README.md
netlify.toml
docker-compose.yml
docker-compose.*.yml
Dockerfile
.dockerignore

4
.env.example Normal file
View file

@ -0,0 +1,4 @@
# Copy to .env and adjust if needed. Not required — defaults work (port 3001).
# Used by: docker-compose
PORT=3001

7
.gitignore vendored
View file

@ -6,6 +6,7 @@ node_modules
.env .env
.env.* .env.*
!.env.example !.env.example
docker-compose.override.yml
vite.config.js.timestamp-* vite.config.js.timestamp-*
vite.config.ts.timestamp-* vite.config.ts.timestamp-*
@ -13,4 +14,8 @@ vite.config.ts.timestamp-*
.netlify .netlify
# IDE files # IDE files
.idea .idea
# Logs
err.log
out.log

View file

@ -2,7 +2,47 @@
This guide will help you deploy your SvelteKit application on your Hetzner VPS. This guide will help you deploy your SvelteKit application on your Hetzner VPS.
## Prerequisites ---
## Docker deployment (recommended)
Config is in git; defaults use port **3001**. Minimal steps on the server:
### Prerequisites on server
- Docker and Docker Compose installed
### Deploy / update
```bash
cd /path/to/floter-design # e.g. ~/floter-design
git pull
docker-compose up -d --build
```
### Optional: custom port
Create a `.env` file (do not commit) and set:
```bash
PORT=3001
```
Then run `docker-compose up -d --build` as above.
### Useful commands
- Logs: `docker-compose logs -f floter-design`
- Restart: `docker-compose restart floter-design`
- Stop: `docker-compose down`
Nginx in front of the app should proxy to `http://127.0.0.1:3001` (or the port in your `.env`).
---
## PM2 deployment (without Docker)
### Prerequisites
- Node.js installed on your VPS - Node.js installed on your VPS
- PM2 installed globally (`npm install -g pm2`) - PM2 installed globally (`npm install -g pm2`)

44
Dockerfile Normal file
View file

@ -0,0 +1,44 @@
# Multi-stage build for SvelteKit app (environment-agnostic)
# Stage 1: Build
FROM node:24.13.1-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --legacy-peer-deps
# Build-time args (for VITE_PUBLIC_* variables - these are public anyway)
ARG VITE_PUBLIC_CLOUDINARY_CLOUD_NAME=""
ENV VITE_PUBLIC_CLOUDINARY_CLOUD_NAME=${VITE_PUBLIC_CLOUDINARY_CLOUD_NAME}
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:24.13.1-alpine
WORKDIR /app
RUN npm install -g pm2
COPY package*.json ./
RUN npm ci --only=production --legacy-peer-deps && npm cache clean --force
COPY --from=builder /app/build ./build
COPY --from=builder /app/ecosystem.config.cjs ./ecosystem.config.cjs
RUN mkdir -p logs
# Default port; override with PORT env in compose or .env
ENV NODE_ENV=production
ENV HOST=0.0.0.0
ARG PORT=3001
ENV PORT=${PORT}
EXPOSE ${PORT}
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:' + (process.env.PORT || 3001), (r) => { process.exit(r.statusCode === 200 ? 0 : 1); })"
CMD ["pm2-runtime", "start", "ecosystem.config.cjs"]

29
docker-compose.yml Normal file
View file

@ -0,0 +1,29 @@
# Base compose file — commit to git.
# Override with .env (copy from .env.example) or docker-compose.override.yml (gitignored).
services:
floter-design:
build:
context: .
dockerfile: Dockerfile
args:
PORT: ${PORT:-3001}
VITE_PUBLIC_CLOUDINARY_CLOUD_NAME: ${VITE_PUBLIC_CLOUDINARY_CLOUD_NAME:-dkvjosg5p}
container_name: floter-design
restart: unless-stopped
ports:
- "${PORT:-3001}:${PORT:-3001}"
environment:
NODE_ENV: production
PORT: ${PORT:-3001}
HOST: 0.0.0.0
env_file:
- .env
volumes:
- ./logs:/app/logs
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:' + (process.env.PORT || 3001), (r) => { process.exit(r.statusCode === 200 ? 0 : 1); })"]
interval: 30s
timeout: 3s
retries: 3
start_period: 5s

1240
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,7 @@
"@types/node": "^20.5.1", "@types/node": "^20.5.1",
"@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0", "@typescript-eslint/parser": "^5.45.0",
"eslint": "^8.28.0", "eslint": "^8.57.1",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte": "^3.0.0", "eslint-plugin-svelte": "^3.0.0",
"prettier": "^3.0.0", "prettier": "^3.0.0",
@ -40,10 +40,10 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"gsap": "^3.13.0", "gsap": "^3.13.0",
"mdsvex": "^0.11.0", "mdsvex": "^0.12.0",
"pixi-filters": "^6.1.5", "pixi-filters": "^6.1.5",
"pixi.js": "^8.15.0", "pixi.js": "^8.15.0",
"superjson": "^1.13.1", "superjson": "^1.13.1",
"svelte-cloudinary": "^1.1.0" "svelte-cloudinary": "^2.3.1"
} }
} }

View file

@ -1,7 +1,8 @@
import type { Actions } from './$types'; import type { Actions } from './$types';
import { BREVO_API_KEY } from '$env/static/private'; import { env } from '$env/dynamic/private';
import { fail, redirect } from '@sveltejs/kit'; import { fail, redirect } from '@sveltejs/kit';
const BREVO_API_KEY = env.BREVO_API_KEY;
const BREVO_ENDPOINT = 'https://api.brevo.com/v3/smtp/email'; const BREVO_ENDPOINT = 'https://api.brevo.com/v3/smtp/email';
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;