Files
gureametsabilagun/README.md
Josep Piguillem 68783ca0b7 MCP remoto: servidor Streamable HTTP como servicio del compose
- mcp/http.js: MCP por HTTP (sin estado). Cada petición lleva la contraseña de aplicación
  del propio usuario (Basic o Bearer); se valida contra WordPress (caché 5 min), exige
  permiso de edición y no se guarda. Límite por IP, /healthz, IP real reenviada a WordPress.
- Herramientas comunes en mcp/src/tools.js (local y remoto); en remoto las fotos van por
  URL o base64 (sin acceso a archivos del servidor).
- Dockerfile del MCP y servicio «mcp» en docker-compose.yml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:25:42 +02:00

267 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Gure Ametsa Bi Lagun — Web WordPress
Web de la protectora **Gure Ametsa Bi Lagun** (Jaizubia 44, Hondarribia), en castellano y euskera, lista para desplegar con Docker Compose en **Dokploy**.
> Base de datos: MariaDB. WordPress no soporta PostgreSQL de forma oficial.
## Qué incluye
- **WordPress (última versión) + PHP 8.3 + MariaDB 11.4**, con WP-CLI dentro de la imagen.
- **Web bilingüe castellano / euskera** con [Polylang](https://wordpress.org/plugins/polylang/) (incluido en la imagen):
- Castellano en `/` y euskera en `/eu/`, con selector **ES | EU** en la cabecera y el pie.
- Todas las páginas, menús, especies y textos del tema existen en los dos idiomas desde el primer arranque.
- Las fichas de los animales comparten los datos (edad, sexo, estado, foto…) entre idiomas: solo hay que traducir el nombre y la descripción.
- **Instalación automática** en el primer arranque: idiomas, páginas, menús, portada y enlaces permanentes.
- **Tema propio `gure-ametsa`**: portada con textos editables en cada idioma (Apariencia → Personalizar → Portada · Castellano / Portada · Euskera), listado de adopciones con filtros, fichas de animales y diseño adaptado a móvil.
- **Plugin `gure-ametsa-core`** (mu-plugin, siempre activo):
- Tipo de contenido **Animales** con ficha: estado (en adopción / urgente / busca acogida / reservado / adoptado), sexo, edad, tamaño, raza, fecha de llegada, salud y compatibilidades.
- Listado público en `/adopta/`, filtrable por especie, sexo y tamaño. Los adoptados desaparecen del listado automáticamente.
- Formulario de contacto/adopción `[ga_contacto]`. Envía un email **y** guarda cada mensaje en *Mensajes* dentro del panel, así no se pierde aunque falle el correo.
- Shortcode `[ga_animales numero="6" especie="perro" estado="urgente"]` para usar en cualquier página.
## Gestión del día a día (sin tocar código)
| Qué | Dónde |
|---|---|
| Añadir o editar un animal | **Animales → Añadir animal**. Arriba va la historia y debajo la ficha: <br>• Datos comunes a castellano y euskera: estado, destacado, sexo, nacimiento o edad aproximada, tamaño, fecha de entrada, más fotos y vídeo. <br>• Textos de cada idioma: cómo es, qué necesita, convivencia y el hogar que buscamos. <br>La versión en euskera se crea con el **+** de la caja «Idiomas»; los datos comunes y las fotos se copian solos. |
| Estado | *Disponible*, *En proceso* o *Adoptado*. Los adoptados salen solos del listado. |
| Animales de la portada | Marcar **Destacado** en su ficha. Si no hay ninguno, salen los que llevan más tiempo. |
| Ayuda material | **Personalizar → Adopción y colabora → Ayuda material** (una línea por necesidad). |
| Textos del botón «Quiero conocerlo/la», formulario, confirmación, proceso, correo de destino | **Personalizar → Adopción y colabora → Listado y fichas**. |
| Aviso de cita previa, teléfono, horario | **Personalizar → Contacto y redes**. |
| Portada | **Personalizar → Portada**: cada bloque se puede mostrar u ocultar y reordenar. Por defecto se ve: portada principal, animales destacados, acogida, quiénes somos y contacto. Donaciones, cifras, finales felices, etc. están ocultos. |
| Menú | **Apariencia → Menús** (Principal / Nagusia). |
| Páginas (Acoge, Colabora, Quiénes somos, Contacto, Preguntas frecuentes) | **Páginas**, con el editor de bloques y los patrones «Gure Ametsa». |
| Mensajes recibidos | Menú **Mensajes** (además llegan por correo). |
Cada ficha tiene su propio enlace y botones para compartirla por WhatsApp o Facebook, o copiar el enlace.
## Migraciones
`docker/setup.sh` se ejecuta en cada arranque y aplica por etapas lo que falte (`ga_setup_version`):
| Etapa | Qué hace |
|---|---|
| 2 | Idiomas, tema, páginas y menús iniciales |
| 3 | Plugins recomendados |
| 4 | APIs (WPGraphQL, Swagger) |
| 5 | Indicaciones del cliente: páginas Acoge y Preguntas frecuentes, menú con submenús, retirada del hotel, estados nuevos y sin animaciones |
| 6 | Preguntas frecuentes con perdidos/encontrados; páginas del cuestionario y de finales felices (borrador) |
`docker/setup-content.php` es idempotente. **Las páginas que el cliente haya editado nunca se sobrescriben**; se detecta con una huella del contenido original.
## Herramientas para el equipo
- **Escritorio → «Fichas por revisar»**: animales sin foto, sin euskera, sin «Cómo es», sin especie o en proceso desde hace demasiado.
- **Animales (listado)**: estrella ☆/★ para destacar con un clic; acciones en bloque (estado, destacar, **imprimir carteles con QR**).
- **Ficha del animal → caja «Compartir»**: imagen para redes generada automáticamente (la que sale al compartir el enlace) y cartel A4 con QR.
- **Finales felices** (Animales → Finales felices): historias enviadas por las familias desde la página «Finales felices» (borrador hasta que queráis publicarla); se publican solo tras revisarlas.
- **Cuestionario de adopción** online: página fuera del menú y sin indexar; enviad el enlace tras el primer contacto (`?adoptar=ID` lo rellena con el animal). Preguntas en *Personalizar → Adopción y colabora → Cuestionario*.
- **Mensajes**: se borran solos a los 12 meses (configurable).
- **Asistente (MCP)**: remoto (servicio `mcp` del compose, añade su dominio en Dokploy → puerto 3000) o local. Ver [`mcp/README.md`](mcp/README.md).
### Pendiente fuera del código (requiere cuentas del cliente)
| Tarea | Cómo |
|---|---|
| Copias fuera del servidor | UpdraftPlus → Ajustes → Google Drive o Dropbox |
| Aviso si la web se cae | UptimeRobot o Better Stack (gratis) apuntando a la portada |
| Caché y cortafuegos | Cloudflare delante del dominio (proxy naranja) |
| Google Maps / búsqueda local | Ficha de Google Business con la misma dirección, horario y web |
| Aviso de «Nuevos animales» | Activar MailPoet, crear un formulario y un email de tipo «Aviso de nuevas publicaciones» para *Animales*; pegar el shortcode en *Personalizar → Pie* |
| Apadrinamiento con pago | Confirmar medios de pago, activar GiveWP y enlazarlo desde la sección «Apadrina» |
## Logo y colores
- El logo original se ha vectorizado en `wp-content/themes/gure-ametsa/assets/img/`:
- `logo.svg`: logo completo, sin fondo.
- `logo-mark.svg`: el arco con el perro y el gato, sin texto.
- `favicon.svg`: el mismo símbolo, para la pestaña del navegador.
- Las capas del SVG (arco, animales, texto) llevan clases propias. Así, en el pie oscuro el texto del logo se muestra en beige.
- La paleta por defecto, «Colores del logo», sale del propio logo:
| Color | Valor | Dónde se usa |
|---|---|---|
| Principal | `#401f0c` (marrón del logo) | Cabecera, botones, secciones oscuras |
| Acento | `#bd8537` (caramelo, el beige del logo más intenso) | Botones principales y palabras resaltadas |
| Secciones | `#f3ecdc` (beige aclarado) | Fondos alternos |
| Fondo | `#fcfaf5` | Fondo general |
| Texto | `#2b1508` | Texto |
- En *Diseño → Cabecera* se elige cómo sale el logo arriba: símbolo + nombre, logo completo o solo el nombre.
## APIs (in English)
The API is in English (routes, fields, values and messages), whatever the site language. The public website keeps its Spanish/Basque URLs (`/adopta/`, `/especie/perro/`).
| API | Endpoint | Notes |
|---|---|---|
| REST | `/wp-json/wp/v2/animals`, `/wp-json/wp/v2/species` | Every animal has a `profile` object (read **and write**). Filter by language with `?lang=es` / `?lang=eu`. |
| GraphQL (WPGraphQL) | `/graphql` | `animals(where: { language: "eu", adoptionStatus: AVAILABLE })`, `speciesList`, type `AnimalProfile`. GraphiQL IDE in the dashboard. |
| OpenAPI 3 / Swagger | `/rest-api/docs/` (UI), `/rest-api/schema` (JSON) | Logged-in users only unless `API_DOCS_PUBLIC=true`. «Try it out» uses your WordPress session. |
`profile` fields:
| Field | Type | Values / notes |
|---|---|---|
| `status` | string | `available`, `pending`, `adopted` (adopted animals are hidden from public listings) |
| `featured` | boolean | shown on the home page |
| `sex` | string | `male`, `female` |
| `birthDate`, `arrivalDate` | date `YYYY-MM-DD` | nullable |
| `age`, `ageUnit` | number, `years`/`months` | approximate age when the birth date is unknown |
| `size` | string | `small`, `medium`, `large` (dogs) |
| `galleryIds` | int[] | extra photos (attachment IDs); `photos` (read-only) = main photo + gallery URLs |
| `video` | URL | YouTube, Vimeo, Instagram or a media file |
| `personality`, `needs`, `compatibility`, `idealHome` | string | **per language** (each translation has its own) |
| `language`, `labels` | read-only | language of the translation and human-readable values in that language |
Shared fields (status, dates, size, photos…) are copied to every translation when written; texts are not.
```graphql
{
animals(first: 10, where: { language: "es", adoptionStatus: AVAILABLE }) {
nodes { title uri language speciesList { nodes { name } } profile { status sex featured size personality labels { age } } }
}
}
```
```bash
# Update an animal (application password: Users → Profile → Application passwords)
curl -u 'user:xxxx xxxx xxxx xxxx' -H 'Content-Type: application/json' \
-d '{"profile":{"status":"pending","featured":true}}' \
https://gureametsabilagun.pireon.dev/wp-json/wp/v2/animals/123
```
Contact-form messages are never exposed by any API.
> Note: the *WP API SwaggerUI* package on wordpress.org ships without its UI assets, so `/rest-api/docs/` is served by our own page (official Swagger UI, pinned version with SRI). The plugin is still used to generate the OpenAPI schema, which we post-process to document `profile`.
## Diseño
El diseño está inspirado en [Beargrass Animal Rescue](https://louisvillewebguy.com/examples/beargrass-animal-rescue/):
- **Tipografía:** títulos en Fraunces muy gruesa y texto en Karla. Las dos van incluidas en el tema, sin Google Fonts.
- **Paletas:** por defecto, los colores del logo. También están ciruela y mostaza (la de Beargrass), verde y rojo, azul mar y bosque.
- **Portada:** a pantalla completa, con foto real y botones a perros y gatos.
- **Listado de animales:** solo Perros y Gatos, con tarjetas de foto y nombre, sin filtros ni etiquetas, a petición del cliente.
- **Pasos de adopción:** en tarjetas.
- **Contacto:** sección oscura con el formulario en una tarjeta.
- **Pie:** columnas de enlaces.
## Personalizar la web sin programar
### Apariencia → Personalizar
- **Diseño (Gure Ametsa)**
- **Colores:** paletas listas (ciruela y mostaza, verde y rojo, azul mar y coral, bosque y teja) o colores a mano. El texto de los botones se ajusta solo para que se lea bien.
- **Tipografía:** tipos de letra de títulos y texto, grosor de los títulos, tamaño y redondeo de las esquinas.
- **Cabecera:** teléfono, selector ES|EU, botones y barra superior opcional.
- **Pie de página:** textos.
- **Contacto y redes:** dirección, teléfono, email, horario y redes. Se actualizan en toda la web.
- **Portada:** cada sección se puede **mostrar, ocultar y reordenar** (campo «Orden»). Sus textos se escriben en castellano y en euskera.
- Portada principal con foto o **vídeo en bucle** y las cuatro puertas
- Animales en adopción (**carrusel** o rejilla)
- Cómo adoptar
- Acogida
- Donaciones (admite un formulario de GiveWP)
- Cifras
- Historias con final feliz (muestra sola los animales adoptados)
- Perdidos y encontrados
- Preguntas frecuentes
- Contenido libre de la página Inicio
- Hotel y visita
- Contacto con formulario
- Opcionales, ocultas por defecto: tarjetas de ayuda y accesos a perros y gatos
- En los títulos se puede resaltar una parte con el color de acento escribiéndola **\*entre asteriscos\***.
### Editor de bloques: patrones «Gure Ametsa»
En cualquier página, abre **+ → Patrones → Gure Ametsa** para insertar secciones prediseñadas. Cada una está en castellano y en euskera:
- portada con imagen
- llamada a la acción
- tres tarjetas
- pasos numerados
- animales en adopción
- **carrusel de animales**
- adopciones urgentes
- imagen y texto
- testimonio
- preguntas frecuentes
- qué necesitamos
- contacto con formulario
También hay estilos de bloque propios en el panel **Estilos**: fondo arena u oscuro, tarjeta, aviso, antetítulo con rayita, imagen en arco, lista con ✓, pasos numerados y testimonio.
El shortcode `[ga_animales numero="10" vista="carrusel"]` muestra un carrusel de animales en cualquier página.
## Plugins incluidos
Se instalan solos en el primer arranque (etapa 3 de `docker/setup.sh`).
| Plugin | Estado | Para qué |
|---|---|---|
| WP Mail SMTP | activo | Envío fiable del correo. Se configura con las variables `SMTP_*` o desde el panel. |
| UpdraftPlus | activo | Copias de seguridad: base de datos a diario y archivos cada semana. Conectad Google Drive o Dropbox en sus ajustes. |
| Limit Login Attempts Reloaded | activo | Bloquea ataques al acceso del panel. |
| Two Factor | activo | Verificación en dos pasos (Usuarios → Perfil). |
| Converter for Media | activo | Convierte las fotos a WebP para que carguen más rápido. |
| Yoast SEO | activo | Google y vista previa al compartir en redes. |
| Smash Balloon Instagram Feed | activo | Muestra vuestro Instagram. Hay que conectar la cuenta. |
| Koko Analytics | activo | Estadísticas de visitas sin cookies. |
| Kadence Blocks | activo | Bloques visuales extra: carruseles de imágenes, pestañas, acordeones e iconos. |
| GiveWP | desactivado | Donaciones online con tarjeta o PayPal. |
| MailPoet | desactivado | Newsletter. |
| Complianz | desactivado | Aviso de cookies. Solo hace falta si añadís YouTube, Analytics, etc. |
| WP Super Cache | desactivado | Caché. Si lo activáis, excluid la página de Contacto. |
## Despliegue en Dokploy
1. Sube este directorio a un repositorio Git (GitHub/GitLab/Gitea).
2. En Dokploy: **Create Service → Compose**, elige el repositorio. Compose path: `./docker-compose.yml`.
3. En la pestaña **Environment**, pega el contenido de `.env.example` y cambia los valores (contraseñas largas, `WP_URL` con tu dominio real en `https://`).
4. En **Domains**, añade el dominio → servicio `wordpress`, puerto `80`, HTTPS activado (Let's Encrypt).
5. **Deploy**. En 1–2 minutos el sitio estará instalado. Entra en `https://tu-dominio/wp-admin` con `WP_ADMIN_USER` / `WP_ADMIN_PASSWORD`.
> `WP_URL` debe coincidir exactamente con el dominio configurado en Dokploy. Si cambias de dominio, basta con cambiar la variable y redesplegar.
### Datos persistentes y copias de seguridad
- Volúmenes: `wp_data` (WordPress, fotos subidas, plugins) y `db_data` (base de datos).
- En Dokploy puedes programar backups de volúmenes. También a mano:
```sh
docker compose exec wordpress wp --allow-root db export - > backup.sql
```
### Actualizaciones del tema
El tema y el plugin viven en la imagen y se copian al volumen en cada arranque: al hacer *Redeploy* se aplican los cambios. **No edites el tema desde el panel**; los cambios se perderían (por eso el editor de archivos está desactivado).
## Desarrollo local
```sh
cp .env.example .env # pon WP_URL=http://localhost:8080 y SEED_DEMO_ANIMALS=true
docker compose -f docker-compose.yml -f docker-compose.local.yml up -d --build
open http://localhost:8080
```
Para empezar de cero: `docker compose down -v`.
## Primeros pasos tras instalar
1. **Animales → Añadir animal**: nombre, foto principal, descripción y ficha, en castellano. Después, en la columna de idiomas del listado (o en la caja «Idiomas» del editor), pulsa **+** junto a la bandera vasca para crear la versión en euskera: la ficha y la foto se copian solas, solo hay que traducir nombre y descripción. Si usaste `SEED_DEMO_ANIMALS=true`, borra los de ejemplo.
2. **Apariencia → Personalizar**: sube el logo (Identidad del sitio), el icono y la foto de portada.
3. **Correo**: rellenad las variables `SMTP_*` en Dokploy (o configurad *WP Mail SMTP* desde el panel). Mientras tanto, los mensajes siguen llegando al menú *Mensajes*.
4. Revisa y completa **Aviso legal** y **Política de privacidad** (razón social, CIF).
5. **Traducciones**: los textos en euskera se han redactado para la web; conviene que una persona euskaldun los revise (páginas en *Páginas*, filtrando por idioma, y textos del tema en los archivos PHP).
## Estructura
```
Dockerfile Imagen: wordpress oficial + WP-CLI + código propio
docker-compose.yml Servicios wordpress + db (para Dokploy)
docker-compose.local.yml Expone el puerto 8080 en local
docker/entrypoint.sh Lanza la configuración inicial y arranca Apache
docker/setup.sh Instalación idempotente con WP-CLI
docker/setup-content.php Idiomas, páginas, menús y especies (es + eu)
docker/content/{es,eu}/ Contenido inicial de las páginas en cada idioma
wp-content/themes/gure-ametsa/ Tema (inc/: personalizador, CSS dinámico, patrones · template-parts/home/: secciones de portada)
wp-content/mu-plugins/gure-ametsa-core.php Animales + formulario
```