<!-- Portada: la imagen es lo primero que se pinta. --> <section class="hero grid gap-6 py-24">- <img src="portada.jpg" class="w-full rounded-xl">+ <img src="portada.avif" class="w-full rounded-xl"+ width="1600" height="900" decoding="async"+ fetchpriority="high" alt="Cocina en Chamberí"> <h1 class="text-5xl font-semibold tracking-tight"> Reformas integrales en Madrid, sin sorpresas </h1> <p class="max-w-prose text-lg text-neutral-400"> Presupuesto cerrado en 48 horas laborables. </p> <a href="/contacto" class="btn">Pedir presupuesto</a> </section>
Your website is slow or out of date: I fix it or build you a new one
First I review it for free and tell you what’s wrong. If it can be fixed, I send you a fixed quote. If a new one makes more sense, I rebuild it with one of the plans, move your content over and keep your Google traffic at no extra cost.
Who it is for
- Sites that take a long time to load and lose visitors for it
- Sites where updating a plugin is frightening
- Anyone who has lost Google rankings since the last change
Who it is not for
- Brand-new sites whose problem is the content, not the code
- Shops with complex WooCommerce logic: that calls for custom development
How I do it
First, the free review
I look at it myself, by hand: how long it takes to load, whether it works with a keyboard and a screen reader, and what Google reads. Within 48 working hours I tell you the three problems that cost you most and where I’d start, with their price.
If it can be fixed, a fixed quote
I tell you what I’ll fix, what it costs and how long it takes, in writing and before I touch anything.
If not, a new site with your content
I rebuild it with the plan that fits and move your text, images and posts over at no extra cost.
Without losing your Google traffic
Every old address points to its new page, checked one by one. This is exactly where cheap migrations wipe out your rankings.
What I change when I review a site.
Seven examples of the kind of change a review produces. On the left what tends to be there; on the right what I leave. The code is illustrative: the problems are the usual ones.
.listado { display: grid; gap: 1rem; } -/* Tres saltos, y ninguno sabe cuánto sitio hay. */+/* La tarjeta mide su hueco, no la ventana. */-.tarjeta { padding: 16px; font-size: 18px; }+.listado { container-type: inline-size; }-+-@media (max-width: 900px) {+.tarjeta {- .tarjeta { padding: 12px; font-size: 16px; }+ padding: clamp(0.5rem, 2cqi, 1rem);-}+ font-size: clamp(0.875rem, 1.6cqi, 1.125rem);-+ border-radius: clamp(0.25rem, 1cqi, 0.75rem);-@media (max-width: 600px) {+}- .tarjeta { padding: 8px; font-size: 14px; }+-}+@container (min-width: 30rem) {+ .tarjeta { grid-template-columns: 8rem 1fr; }+}
export async function cargarListado() { const items = await db.producto.findMany({ where: { activo: true },+ // La categoría entra en la misma ida.+ include: { categoria: true }, }); - // Una consulta, y luego otra por item.- for (const item of items) {- item.categoria = await db.categoria- .findUnique({ id: item.categoriaId });- } return items; }
-<div class="menu__abrir"+<button class="menu__abrir"- onclick="abrirMenu()">+ type="button"+ aria-expanded="false"+ aria-controls="menu">+ <span class="sr-only">Abrir el menú</span> <span></span> <span></span>-</div>+</button> <nav id="menu" class="menu"> <a href="/servicios">Servicios</a> <a href="/proyectos">Proyectos</a> <a href="/precios">Precios</a> <a href="/contacto">Contacto</a> </nav>
<form method="post" action="/contacto"> <label for="email">Correo</label>- <input id="email" type="email"+ <input id="email" type="email"- name="email">+ name="email"+ aria-invalid="true"+ aria-describedby="email-error"> - <span class="error">+ <span class="error" id="email-error"+ role="alert"> Escribe un correo válido </span> <button type="submit">Enviar</button> </form>
<section class="listado"> <?php foreach ( $productos as $p ) : ?> <article class="tarjeta">- <img src="<?php echo $p['imagen']; ?>" alt="">+ <img src="<?php echo esc_url( $p['imagen'] ); ?>"- <h2><?php echo $p['nombre']; ?></h2>+ alt="<?php echo esc_attr( $p['nombre'] ); ?>">- <p><?php echo $p['descripcion']; ?></p>+ <h2><?php echo esc_html( $p['nombre'] ); ?></h2>- <a href="<?php echo $p['url']; ?>">+ <p><?php echo wp_kses_post( $p['descripcion'] ); ?></p>- Ver ficha de <?php echo $p['nombre']; ?>+ <a href="<?php echo esc_url( $p['url'] ); ?>">- </a>+ Ver ficha de <?php echo esc_html( $p['nombre'] ); ?>+ </a> </article> <?php endforeach; ?> </section>
// El esquema estaba escrito y no lo miraba nadie. const Lead = z.object({ nombre: z.string().min(2).max(80), email: z.email(), mensaje: z.string().min(10).max(2000), }); export async function POST({ request }) {- const datos = await request.json();+ const lead = Lead.safeParse(await request.json());- await guardarLead(datos);+ if (!lead.success) {+ return new Response(null, { status: 422 });+ }+ await guardarLead(lead.data); return new Response(null, { status: 204 }); }
Where to start
First
Website X-ray
free
I look at your site and within 48 working hours tell you what is wrong and what I would fix first.
Request X-rayThen
Rebuild your old site
€590from
If yours can’t be fixed, I rebuild it with one of the plans. I move your content over and keep your Google traffic at no extra cost.
Get a free quoteTo make it last
Ongoing maintenance
€49per month
Backups, updates, security and an alert if the site goes down, from the first month. Three tiers, depending on how much you want to change each month.
See pricing
Shall we talk about your project?
Tell me what you need and I will send a first assessment within 24 working hours.
Reply within 24 working hours