Hashnode y Astro
Hashnode es un CMS alojado que te permite crear un blog o publicación.
Integración con Astro
Sección titulada "Integración con Astro"La API pública de Hashnode es una API de GraphQL que te permite interactuar con Hashnode. Esta guía utiliza graphql-request, un cliente minimalista de GraphQL que funciona muy bien con Astro, para importar tus datos de Hashnode a tu proyecto de Astro.
Requisitos previos
Sección titulada “Requisitos previos”Para empezar necesitarás tener lo siguiente:
-
Un proyecto de Astro - Si aún no tienes un proyecto de Astro, nuestra guía de instalación te pondrá en marcha en poco tiempo.
-
Un sitio de Hashnode - Puedes crear un sitio personal gratuito visitando Hashnode.
Instalación de dependencias
Sección titulada "Instalación de dependencias"Instala el paquete graphql-request utilizando el gestor de paquetes de tu elección:
npm install graphql-requestpnpm add graphql-requestyarn add graphql-requestCreación de un blog con Astro y Hashnode
Sección titulada “Creación de un blog con Astro y Hashnode”Esta guía utiliza graphql-request, un cliente minimalista de GraphQL que funciona muy bien con Astro, para importar tus datos de Hashnode a tu proyecto de Astro.
Requisitos previos
Sección titulada “Requisitos previos”- Un blog de Hashnode
- Un proyecto de Astro integrado con el paquete graphql-request instalado.
Este ejemplo creará una página de índice que lista las publicaciones con enlaces a páginas de publicaciones individuales generadas dinámicamente.
Obtención de datos
Sección titulada "Obtención de datos"-
Para obtener los datos de tu sitio con el paquete
graphql-request, haz un directoriosrc/liby crea dos nuevos archivosclient.tsyschema.ts:Directoriosrc/
Directoriolib/
- client.ts
- schema.ts
Directoriopages/
- index.astro
- astro.config.mjs
- package.json
-
Inicializa una instancia de API con GraphQLClient utilizando la URL de tu sitio web de Hashnode.
src/lib/client.ts import { gql, GraphQLClient } from "graphql-request";import type { AllPostsData, PostData } from "./schema";export const getClient = () => {return new GraphQLClient("https://gql.hashnode.com")}const myHashnodeURL = "astroplayground.hashnode.dev";export const getAllPosts = async () => {const client = getClient();const allPosts = await client.request<AllPostsData>(gql`query allPosts {publication(host: "${myHashnodeURL}") {idtitleposts(first: 20) {pageInfo{hasNextPageendCursor}edges {node {idauthor{nameprofilePicture}titlesubtitlebriefslugcoverImage {url}tags {nameslug}publishedAtreadTimeInMinutes}}}}}`);return allPosts;};export const getPost = async (slug: string) => {const client = getClient();const data = await client.request<PostData>(gql`query postDetails($slug: String!) {publication(host: "${myHashnodeURL}") {idpost(slug: $slug) {idauthor{nameprofilePicture}publishedAttitlesubtitlereadTimeInMinutescontent{html}tags {nameslug}coverImage {url}}}}`,{ slug: slug });return data.publication.post;}; -
Configura
schema.tspara definir la forma de los datos devueltos por la API de Hashnode.src/lib/schema.ts import { z } from "astro/zod";export const PostSchema = z.object({id: z.string(),author: z.object({name: z.string(),profilePicture: z.string(),}),publishedAt: z.string(),title: z.string(),subtitle: z.string(),brief: z.string(),slug: z.string(),readTimeInMinutes: z.number(),content: z.object({html: z.string(),}),tags: z.array(z.object({name: z.string(),slug: z.string(),})),coverImage: z.object({url: z.string(),}),})export const AllPostsDataSchema = z.object({id: z.string(),publication: z.object({title: z.string(),posts: z.object({pageInfo: z.object({hasNextPage: z.boolean(),endCursor: z.string(),}),edges: z.array(z.object({node: PostSchema,})),}),}),})export const PostDataSchema = z.object({id: z.string(),publication: z.object({title: z.string(),post: PostSchema,}),})export type Post = z.infer<typeof PostSchema>export type AllPostsData = z.infer<typeof AllPostsDataSchema>export type PostData = z.infer<typeof PostDataSchema>
Mostrar una lista de publicaciones
Sección titulada “Mostrar una lista de publicaciones”La obtención a través de getAllPosts() devuelve una matriz de objetos que contienen las propiedades de cada publicación como:
title- el título de la publicaciónbrief- la representación HTML del contenido de la publicacióncoverImage.url- la URL de origen de la imagen destacada de la publicaciónslug- el slug de la publicación
Usa la matriz posts devuelta por la consulta para mostrar una lista de publicaciones de blog en la página.
---import { getAllPosts } from '../lib/client';
const data = await getAllPosts();const allPosts = data.publication.posts.edges;
---
<html lang="en"> <head> <title>Astro + Hashnode</title> </head> <body>
{ allPosts.map((post) => ( <div> <h2>{post.node.title}</h2> <p>{post.node.brief}</p> <img src={post.node.coverImage.url} alt={post.node.title} /> <a href={`/post/${post.node.slug}`}>Read more</a> </div> )) } </body></html>Generación de páginas
Sección titulada "Generación de páginas"-
Crea la página
src/pages/post/[slug].astropara generar dinámicamente una página para cada publicación.Directoriosrc/
Directoriolib/
- client.ts
- schema.ts
Directoriopages/
- index.astro
Directoriopost/
- [slug].astro
- astro.config.mjs
- package.json
-
Importa y usa
getAllPosts()ygetPost()para obtener los datos de Hashnode y generar rutas de página individuales para cada publicación.src/pages/post/[slug].astro ---import { getAllPosts, getPost } from '../../lib/client';export async function getStaticPaths() {const data = await getAllPosts();const allPosts = data.publication.posts.edges;return allPosts.map((post) => {return {params: { slug: post.node.slug },}})}const { slug } = Astro.params;const post = await getPost(slug);--- -
Crea la plantilla para cada página usando las propiedades de cada objeto
post. El siguiente ejemplo muestra el título de la publicación y el tiempo de lectura, y luego el contenido completo de la publicación:src/pages/post/[slug].astro ---import { getAllPosts, getPost } from '../../lib/client';export async function getStaticPaths() {const data = await getAllPosts();const allPosts = data.publication.posts.edges;return allPosts.map((post) => {return {params: { slug: post.node.slug },}})}const { slug } = Astro.params;const post = await getPost(slug);---<!DOCTYPE html><html lang="en"><head><title>{post.title}</title></head><body><img src={post.coverImage.url} alt={post.title} /><h1>{post.title}</h1><p>{post.readTimeInMinutes} min read</p><Fragment set:html={post.content.html} /></body></html><Fragment />es un componente integrado de Astro que te permite evitar un elemento contenedor innecesario. Esto puede ser especialmente útil al obtener HTML desde un CMS (por ejemplo, Hashnode o WordPress).
Publicando tu sitio
Sección titulada "Publicando tu sitio"Para desplegar tu sitio, visita nuestra guía de despliegue y sigue las instrucciones para tu proveedor de alojamiento preferido.
Recursos de la comunidad
Sección titulada "Recursos de la comunidad"astro-hashnodeen GitHub
Más guías de CMS
Socios de CMS destacados
-
CloudCannon
CMS basado en Git creado para mayor velocidad, seguridad y cero dolores de cabeza.