WordPress Headless + Astro – Recursos de la clase 02

WordPress Headless + Astro – Recursos de la clase 02

SofiDev

Angela Sofía Osorio

Tiempo de lectura 2 minutes

¿Qué tal amigos? Estos son los apuntes y recursos de la clase número dos del curso de WordPress Headless + Astro. Recuerda que este es un curso exclusivo para miembros del canal con el nivel de Videos VIP.

Recurso 1 – Las Querys para WpGraphQL

https://gist.github.com/SofiDevO/211e021d784def365923216079fc8106

o también puedes copiarlo directamente de aquí:

#post cards  🦝
query getPostCards {
  posts {
    nodes {
      title
      slug
      featuredImage {
        node {
          altText
          mediaItemUrl
          srcSet(size: MEDIUM)
          sizes(size: LARGE)
          altText
          link
          sourceUrl(size: LARGE)
        }
      }
      author {
        node {
          avatar {
            url
          }
          firstName
          lastName
          name
          slug
        }
      }
      date
      excerpt
      categories {
        nodes {
          name
          slug
          parent {
            node {
              name
              slug
              id
            }
          }
          id
          uri
        }
      }
      isSticky
      seo {
        metaDesc
      }
    }
  }
  comments {
    edges {
      node {
        id
      }
    }
  }
}
#Post Content 🦝
query getPostContent {
  posts(first: 500) {
      nodes {
      slug
      date
      title
      databaseId
      id
       author {
          node {
          avatar {
              url
          }
          lastName
          name
          firstName
          description
          id
          }
      }
      content(format: RENDERED)
       featuredImage {
          node {
              altText
              mediaItemUrl
              srcSet(size: LARGE)
              sizes(size: LARGE)
              altText
              link
              sourceUrl(size: LARGE)
          }
      }
      tags {
          nodes {
          name
          }
      }
      categories {
          nodes {
          name
          }
      }
      commentCount
      dateGmt
      modified
      seo {
          cornerstone
          readingTime
          metaDesc
      }
      }
  }
}
            

#Main menu elements by name
query GET_MENU_BY_NAME {
  menu(id: "menu", idType: NAME) {
    menuItems {
      nodes {
        url
        label
        parentId
        id
      }
    }
  }
}


#Get categories post card  by slug
query getPostsByCategory {
  categories(where: {slug: "${slug}"}) {
      edges {
          node {
              id
               posts {
                  nodes {
                      title
                      slug
                      featuredImage {
                      node {
                          altText
                          mediaItemUrl
                      }
                      }
                      author {
                      node {
                          avatar {
                          url
                          }
                          firstName
                          lastName
                          name
                          slug
                      }
                      }
                      date
                      excerpt
                      categories {
                      nodes {
                          name
                          slug
                          parent {
                          node {
                              name
                              slug
                          }
                          }
                      }
                      }
                  }
                  }
              name
          }
      }
  }
}


query geUsers {
  users {
    nodes {
      avatar {
        default
        url
      }
      email
      description
      comments {
        nodes {
          status
          content(format: RENDERED)
          uri
        }
      }
      nickname
      name
      slug
      lastName
      firstName
      databaseId
      uri
    }
    pageInfo {
      endCursor
      startCursor
    }
    edges {
      node {
        email
        description
      }
    }
  }
}
GraphQL

Ahora es momento de configurar nuestro proyecto de Astro. Así que sigue los pasos del video y usa estas bases como referencia:

Ejemplo de tsconfig.json

Con esta configuración evitamos el uso innecesario de ../../../ en nuestras rutas hacia los archivos.

{
  "extends": "astro/tsconfigs/strict",
  "include": [".astro/types.d.ts", "**/*", "src/**/*"],
  "exclude": ["dist"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@src/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@atoms/*": ["src/components/atoms/*"],
      "@molecules/*": ["src/components/molecules/*"],
      "@organisms/*": ["src/components/organisms/*"],
      "@layouts/*": ["src/layouts/*"],
      "@pages/*": ["src/pages/*"],
      "@controllers/*": ["src/controllers/*"],
      "@utils/*": ["src/utils/*"],
      "@services/*": ["src/services/*"],
      "@data/*": ["src/data/*"],
      "@styles/*": ["src/styles/*"],
      "@img/*": ["public/img/*"]
      },
  }
}
JSON

BaseHead.astro

Este es el archivo donde vamos a configurar todas las metaetiquetas de nuestro head

---
// Import the global.css file here so that it is included on
// all pages through the use of the <BaseHead /> component.
import "@styles/global.css"
import { ClientRouter } from 'astro:transitions';
/* import { ViewTransitions } from "astro:transitions"; */

import { SITE_TITLE, SITE_DESCRIPTION } from "@src/const";
interface Props {
  title?: string;
  description?: string;
  image?: string;
}

const canonicalURL = new URL(Astro.url.pathname, Astro.site);

const {
  title = SITE_TITLE,
  description = SITE_DESCRIPTION,
  image = "/img/ubuntu.png",
} = Astro.props;

---

<!-- Global Metadata -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" type="image/png" href="/img/ubuntu.png" />
<meta name=”robots” content=”index, follow”>
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
<!-- Canonical URL -->
<link rel="canonical" href={canonicalURL} />

<!-- Primary Meta Tags -->

<meta name="title" content={title}   />
<meta name="description" content={description} />

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={new URL(image, Astro.url)} />

<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={Astro.url} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} />

<!-- Adsense -->
<meta name="google-adsense-account" content="ca-pub-3828278469742835">


<!-- css librerias/ cdn -->


<!-- Iconify CDN -->
<script src="https://code.iconify.design/iconify-icon/2.0.0/iconify-icon.min.js"
></script>
Astro

Acá está la referencia de uso en nuestro Layout:

---
//Layout.astro
import BaseHead from "@components/BaseHead.astro"
const {title, description, image} = Astro.props;

---


<!doctype html>
<html lang="en">
	<head>
		<BaseHead title={title} description={description} image={image}/>
	</head>
	<body>
		<slot />
	</body>
</html>

<style>
	html,
	body {
		margin: 0;
		width: 100%;
		height: 100%;
	}
</style>
Astro

Agregando nuestra configuración a wordpress.ts

//src/services/wordpress.ts

const baseURL = import.meta.env.WORDPRESS_URL;

interface WPGraphQLParams {
  query: string;
  variables?: object;
}

export async function wpquery({ query, variables = {} }: WPGraphQLParams) {
  const res = await fetch(baseURL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query,
      variables,
    }),
  });

  if (!res.ok) {
    throw new Error(`HTTP error! status: ${res.status}`);
  }

  const { data, errors } = await res.json();

  if (errors) {
    console.error('GraphQL Errors:', errors);
    throw new Error('Error en la consulta GraphQL');
  }

  return data;

}
TypeScript

Formatear Fecha

// src/utils/formatedDate.js

function formatedDate(date, locale = "es-ES"){
    const fecha = new Date(date);
    return new Intl.DateTimeFormat(locale, {
        year: "numeric",
        month: "long",
        day: "numeric",
    }).format(fecha);
}

export default formatedDate;
JavaScript