Web corporativa para una pequeña empresa de pintura, construida con Astro + TypeScript, React (solo para componentes interactivos), Tailwind CSS y salida estática (SSG).
- 🎨 Home con hero, servicios, galería con lightbox, "sobre nosotros" y testimonios.
- 📄 Páginas: Inicio, Servicios (catálogo detallado) y Contacto.
- 📝 Formulario de contacto (React) con validación, estados de envío, honeypot anti-spam y destino configurable (Formspree o endpoint propio con Resend).
- 💬 WhatsApp: botón flotante en todas las páginas + enlaces en hero y contacto,
usando el enlace oficial
wa.mecon mensaje precargado. - 🔍 SEO: meta tags, Open Graph, Twitter Card, sitemap,
robots.txty datos estructurados JSON-LD de tipoLocalBusiness. - ♿ Accesibilidad y rendimiento: HTML semántico, navegación por teclado, imágenes
optimizadas con
<Image>y carga diferida.
src/
assets/ Imágenes (placeholders — sustitúyelas por las tuyas)
components/ Componentes .astro (estáticos) y .tsx (React, interactivos)
data/ ⭐ Datos editables: site.ts, services.ts, reviews.ts, gallery.ts
layouts/ Layout base
pages/ Rutas: index, servicios, contacto, api/contact, 404
styles/ global.css (Tailwind + paleta configurable)
public/ robots.txt, favicons
Requisitos: Node ≥ 22.12 (probado con Node 26).
npm install
cp .env.example .env # rellena tus variables
npm run dev # http://localhost:4321Según
CLAUDE.md, puedes lanzar el servidor en segundo plano conastro dev --backgroundy gestionarlo conastro dev stop|status|logs.
Casi todo se edita desde src/data/ sin tocar componentes:
| Archivo | Qué contiene |
|---|---|
src/data/site.ts |
Nombre, eslogan, teléfono, email, WhatsApp, dirección, horario, redes |
src/data/services.ts |
Lista de servicios (alimenta home, página de servicios y el <select>) |
src/data/reviews.ts |
Testimonios (nombre, localidad, estrellas, texto) |
src/data/gallery.ts |
Imágenes de la galería (importadas desde src/assets) |
- Paleta de colores y tipografía: bloque
@themeensrc/styles/global.css. - Dominio: cambia
siteenastro.config.mjsy la URL delSitemap:enpublic/robots.txt. - Imágenes: reemplaza los
.jpgdesrc/assets/manteniendo los nombres/imports.
El destino se elige con la variable PUBLIC_CONTACT_PROVIDER:
No requiere adapter ni servidor. En .env:
PUBLIC_CONTACT_PROVIDER=formspree
PUBLIC_FORMSPREE_ID=xxxxxxxx # ID de tu formulario en https://formspree.ioSi solo usas Formspree, puedes simplificar el proyecto eliminando el adapter:
quita adapter: vercel() y su import en astro.config.mjs, y borra src/pages/api/contact.ts.
Envía un email desde /api/contact. Requiere el adapter de Vercel (ya configurado). En .env:
PUBLIC_CONTACT_PROVIDER=resend
RESEND_API_KEY=re_xxxxxxxx # https://resend.com/api-keys
CONTACT_TO_EMAIL=info@pinturasramon.esEn
src/pages/api/contact.ts, cambia el remitentefrom:por un dominio verificado en Resend (para pruebas sirveonboarding@resend.dev).
npm run build # genera /dist (+ sitemap)
npm run preview # previsualiza el build- Sube el repo a GitHub e impórtalo en Vercel. Vercel detecta Astro automáticamente.
- En Settings → Environment Variables añade las variables de tu
.env(PUBLIC_CONTACT_PROVIDER,PUBLIC_FORMSPREE_IDy, si usas Resend,RESEND_API_KEYyCONTACT_TO_EMAIL). - Deploy. El endpoint
/api/contactse publica como función serverless gracias al adapter@astrojs/vercel.
Solo Formspree / hosting estático (Netlify, Cloudflare Pages, GitHub Pages…): elimina el adapter como se indica arriba y sube la carpeta
dist/(o conecta el repo). No necesitas variables de servidor.