diff --git a/Caddyfile b/Caddyfile deleted file mode 100644 index 242a78c..0000000 --- a/Caddyfile +++ /dev/null @@ -1,41 +0,0 @@ -# Configuración básica de Caddy para solu23.cloud -solu23.cloud { - # Raíz del sitio - root * /var/www/sol23_placeholder - - # Habilitar compresión - encode gzip - - # Servir archivos estáticos - file_server - - # Página de error personalizada (opcional) - handle_errors { - respond "{http.error.status_code} {http.error.status_text}" - } - - # Headers de seguridad - header { - # Habilitar HSTS - Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" - # Prevenir clickjacking - X-Frame-Options "SAMEORIGIN" - # Prevenir MIME sniffing - X-Content-Type-Options "nosniff" - # XSS Protection - X-XSS-Protection "1; mode=block" - # Referrer Policy - Referrer-Policy "strict-origin-when-cross-origin" - } - - # Logs (opcional) - log { - output file /var/log/caddy/solu23.log - format json - } -} - -# Redirección de www a no-www (opcional) -www.solu23.cloud { - redir https://solu23.cloud{uri} permanent -} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2982752 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:20-alpine + +# Install only production dependencies +WORKDIR /app +COPY package.json ./ + +# npm install will run inside Coolify/Traefik containers where network access exists +RUN npm install --omit=dev + +# Copy the rest of the repository +COPY . . + +EXPOSE 3000 + +CMD ["npm", "start"] diff --git a/README.md b/README.md index cd8f06d..d6bd1fd 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,37 @@ # Soul:23 coming soon page -A responsive landing page built with Bootstrap 4 that keeps a countdown and lets visitors request updates via the email form. A live preview is available at https://solu23.cloud. +Una landing page responsive Built con Bootstrap 4 que muestra una cuenta regresiva y un formulario de notificaciones. Se accede a una versión viva en https://solu23.cloud. **Author:** Marco Gallegos -## Subscription form +## Instalación local -The notification form is purely client-side; fill it out, but no emails are sent or stored until you connect it to your own backend. +```bash +npm install +npm start +``` -## Changing the countdown target +El servidor Express sirve todos los assets desde la raíz y expone `/healthchecker` con el script de salud como `text/plain`, listo para que operadores lo descarguen con `curl`. -The timer reads its target date from the `data-date` attribute on the `#countdown-timer` element in `index.html`. Update that attribute to any valid timestamp, for example: +## Deploy con Coolify / Traefik + +1. Importa el repositorio como app Docker en Coolify. +2. Elige el `Dockerfile` del proyecto, expone el puerto `3000` (ya definido en el contenedor). +3. Coolify/Traefik se encargan del TLS; usa el dominio que asignas en la app. +4. Si necesitas alertas, define la variable de entorno `WEBHOOK_URLS` antes de levantar la app. + +Una vez desplegado podrás invocar el verificador con: + +```bash +curl https://tudominio.cloud/healthchecker +``` + +## Contador y formulario + +El componente de tiempo lee el atributo `data-date` en `#countdown-timer`. Cámbialo por cualquier fecha válida: ```html
``` -If you prefer keeping the attribute dynamic, reassign the `countDownDate` variable inside `js/countdown.js` before the interval starts. +Si prefieres programarlo con JavaScript, reasigna la variable `countDownDate` dentro de `js/countdown.js` antes de que empiece el intervalo. diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index e324677..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,33 +0,0 @@ -version: '3.8' - -services: - caddy: - image: caddy:2-alpine - container_name: caddy_solu23 - restart: unless-stopped - ports: - - "80:80" - - "443:443" - - "443:443/udp" # HTTP/3 - volumes: - # Monta el Caddyfile - - ./Caddyfile:/etc/caddy/Caddyfile - # Monta los archivos del sitio - - ./:/var/www/sol23_placeholder - # Datos persistentes de Caddy (certificados SSL) - - caddy_data:/data - - caddy_config:/config - # Logs - - ./logs:/var/log/caddy - networks: - - caddy_network - -volumes: - caddy_data: - driver: local - caddy_config: - driver: local - -networks: - caddy_network: - driver: bridge diff --git a/package.json b/package.json new file mode 100644 index 0000000..3b7c396 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "soul23-coming-soon", + "version": "1.0.0", + "description": "Landing page for Soul:23 with a health checker endpoint for the ops team.", + "scripts": { + "start": "node server.js" + }, + "engines": { + "node": ">=18" + }, + "dependencies": { + "express": "^4.18.2" + } +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..3191bd9 --- /dev/null +++ b/server.js @@ -0,0 +1,24 @@ +const express = require("express"); +const path = require("path"); + +const app = express(); +const port = process.env.PORT || 3000; +const rootDir = path.join(__dirname); + +// Serve static assets from the project root +app.use(express.static(rootDir, { index: "index.html" })); + +// Health checker should always return the raw script with text/plain +app.get("/healthchecker", (req, res) => { + res.type("text/plain"); + res.sendFile(path.join(rootDir, "health_checker")); +}); + +// Fallback to index.html for other routes (optional) +app.get("*", (req, res) => { + res.sendFile(path.join(rootDir, "index.html")); +}); + +app.listen(port, () => { + console.log(`Soul:23 server listening on port ${port}`); +});