Add Dockerfiles, .dockerignore and brand logo

- apps/api/Dockerfile: multi-stage pnpm build, runtime node:22-alpine, port 3001
- apps/web/Dockerfile: multi-stage pnpm + Vite, runtime nginx:alpine with SPA config
- .dockerignore: excludes node_modules, dist, .env, .git, IDE folders, design docs
- Brand logo (naturcalabacera.webp) integrated as favicon, sidebar icon, header logo
- index.html title updated to 'Naturcalabacera · Reservas'
This commit is contained in:
2026-04-30 10:22:37 +01:00
parent a0ccb8ca64
commit 22e8cc893f
7 changed files with 170 additions and 9 deletions

52
apps/web/Dockerfile Normal file
View File

@@ -0,0 +1,52 @@
# syntax=docker/dockerfile:1
# ───── Stage 1: build ─────
FROM node:22-alpine AS builder
WORKDIR /repo
RUN corepack enable
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
COPY packages/shared/package.json ./packages/shared/
COPY apps/web/package.json ./apps/web/
RUN pnpm install --frozen-lockfile
COPY packages/shared ./packages/shared
COPY apps/web ./apps/web
# Variables públicas inyectadas en el bundle por Vite (build-time)
ARG VITE_SUPABASE_URL
ARG VITE_SUPABASE_ANON_KEY
ARG VITE_SUPABASE_SCHEMA
ARG VITE_API_URL
ENV VITE_SUPABASE_URL=$VITE_SUPABASE_URL
ENV VITE_SUPABASE_ANON_KEY=$VITE_SUPABASE_ANON_KEY
ENV VITE_SUPABASE_SCHEMA=$VITE_SUPABASE_SCHEMA
ENV VITE_API_URL=$VITE_API_URL
RUN pnpm --filter @naturcalabacera/web build
# ───── Stage 2: runtime (Nginx sirviendo SPA) ─────
FROM nginx:alpine
COPY --from=builder /repo/apps/web/dist /usr/share/nginx/html
# Config SPA: cualquier ruta cae en index.html (React Router friendly)
RUN printf 'server {\n\
listen 80;\n\
server_name _;\n\
root /usr/share/nginx/html;\n\
index index.html;\n\
\n\
location / {\n\
try_files $uri $uri/ /index.html;\n\
}\n\
\n\
# Cache largo para assets con hash\n\
location /assets/ {\n\
expires 1y;\n\
add_header Cache-Control "public, immutable";\n\
}\n\
}\n' > /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -2,9 +2,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/webp" href="/naturcalabacera.webp" />
<link rel="apple-touch-icon" href="/naturcalabacera.webp" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>reservas-app</title>
<title>Naturcalabacera · Reservas</title>
</head>
<body>
<div id="root"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -126,12 +126,19 @@ function AppContent() {
<header className={`${theme.headerBg} backdrop-blur-xl border-b ${theme.headerBorder} px-4 md:px-10 py-4 md:py-6 shadow-2xl transition-all duration-700`}>
{/* Relative container: center title absolutely, left/right content on sides */}
<div className="relative flex items-center justify-center min-h-[3rem] md:min-h-[3.5rem]">
{/* Left: status dot + tagline (desktop only) */}
<div className="absolute left-0 hidden md:flex items-center gap-2">
<span className={`inline-block w-2 h-2 rounded-full shadow-lg ${theme.dotColor} ${theme.dotShadow} animate-pulse flex-shrink-0`} />
<span className={`text-xs font-medium ${theme.subtitleText}`}>
Gestiona tus reservas y disponibilidad
</span>
{/* Left: brand logo + status dot + tagline */}
<div className="absolute left-0 flex items-center gap-2 md:gap-3">
<img
src="/naturcalabacera.webp"
alt="Naturcalabacera"
className="w-9 h-9 md:w-11 md:h-11 object-contain drop-shadow-lg flex-shrink-0"
/>
<div className="hidden md:flex items-center gap-2">
<span className={`inline-block w-2 h-2 rounded-full shadow-lg ${theme.dotColor} ${theme.dotShadow} animate-pulse flex-shrink-0`} />
<span className={`text-xs font-medium ${theme.subtitleText}`}>
Gestiona tus reservas y disponibilidad
</span>
</div>
</div>
{/* Center: property name — always truly centered */}

View File

@@ -31,7 +31,7 @@ export function Sidebar({ currentView, onNavigate, isViewer = false, isAdmin = f
<div className={`p-8 border-b ${theme.dividerBorder}`}>
<h1 className="text-3xl font-black text-white flex items-center gap-3">
<div className={`p-2 bg-gradient-to-br ${theme.logoIconBg} rounded-xl shadow-lg ${theme.logoIconShadow} transition-all duration-700`}>
<Calendar className="w-6 h-6 text-white" />
<img src="/naturcalabacera.webp" alt="Naturcalabacera" className="w-6 h-6 object-contain" />
</div>
<span className={`bg-gradient-to-r ${theme.logoTextGradient} bg-clip-text text-transparent transition-all duration-700`}>
Reservas