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:
38
apps/api/Dockerfile
Normal file
38
apps/api/Dockerfile
Normal file
@@ -0,0 +1,38 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# ───── Stage 1: build ─────
|
||||
FROM node:22-alpine AS builder
|
||||
WORKDIR /repo
|
||||
RUN corepack enable
|
||||
|
||||
# Manifiestos primero (para cachear pnpm install si no cambian deps)
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
COPY packages/shared/package.json ./packages/shared/
|
||||
COPY apps/api/package.json ./apps/api/
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Código fuente
|
||||
COPY packages/shared ./packages/shared
|
||||
COPY apps/api ./apps/api
|
||||
|
||||
# Compila TypeScript del api
|
||||
RUN pnpm --filter @naturcalabacera/api build
|
||||
|
||||
# Carpeta de despliegue self-contained con node_modules de producción
|
||||
RUN pnpm --filter @naturcalabacera/api deploy --prod /out
|
||||
|
||||
# Copia plantillas HTML al dist (tsc no las copia)
|
||||
RUN cp -r apps/api/src/templates /out/dist/templates
|
||||
|
||||
# ───── Stage 2: runtime ─────
|
||||
FROM node:22-alpine
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
|
||||
COPY --from=builder /out/dist ./dist
|
||||
COPY --from=builder /out/node_modules ./node_modules
|
||||
COPY --from=builder /out/package.json ./package.json
|
||||
|
||||
EXPOSE 3001
|
||||
CMD ["node", "dist/index.js"]
|
||||
52
apps/web/Dockerfile
Normal file
52
apps/web/Dockerfile
Normal 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;"]
|
||||
@@ -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>
|
||||
|
||||
BIN
apps/web/public/naturcalabacera.webp
Normal file
BIN
apps/web/public/naturcalabacera.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
@@ -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 */}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user