Hashnode & Astro
Hashnode est un CMS hébergé qui vous permet de créer un blog ou une simple publication.
Intégration avec Astro
Section intitulée « Intégration avec Astro »L’API publique de Hashnode est une API GraphQL qui vous permet d’interagir avec Hashnode. Ce guide utilise graphql-request
, un client GraphQL minimal qui fonctionne bien avec Astro, pour apporter vos données Hashnode dans votre projet Astro.
Prérequis
Section intitulée « Prérequis »Pour commencer, vous devez disposer des éléments suivants :
-
Un projet Astro - Si vous n’avez pas encore de projet Astro, notre guide d’installation vous permettra d’être opérationnel en un rien de temps.
-
Un site Hashnode - Vous pouvez créer un site personnel gratuit en visitant Hashnode.
Installation des dépendances
Section intitulée « Installation des dépendances »Installez le paquet graphql-request
en utilisant le gestionnaire de paquets de votre choix :
npm install graphql-request
pnpm add graphql-request
yarn add graphql-request
Créer un blog avec Astro et Hashnode
Section intitulée « Créer un blog avec Astro et Hashnode »Ce guide utilise graphql-request
, un client GraphQL minimal qui fonctionne bien avec Astro, pour apporter vos données Hashnode dans votre projet Astro.
Prérequis
Section intitulée « Prérequis »- Un blog Hashnode
- Un projet Astro intégré avec le paquet graphql-request installé.
Cet exemple va créer une page d’index qui liste les articles avec des liens vers des pages individuelles générées dynamiquement.
Récupération des données
Section intitulée « Récupération des données »-
Pour récupérer les données de votre site avec le paquet
graphql-request
, créez un répertoiresrc/lib
et créez deux nouveaux fichiersclient.ts
&schema.ts
:Répertoiresrc/
Répertoirelib/
- client.ts
- schema.ts
Répertoirepages/
- index.astro
- astro.config.mjs
- package.json
-
Initialisez une instance API avec GraphQLClient en utilisant l’URL de votre site web 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;}; -
Configurez
schema.ts
pour définir la forme des données renvoyées par l’API 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>
Affichage d’une liste d’articles
Section intitulée « Affichage d’une liste d’articles »La récupération via getAllPosts()
renvoie un tableau d’objets contenant les propriétés de chaque article telles que :
title
- le titre de l’articlebrief
- l’affichage HTML du contenu de l’articlecoverImage.url
- l’URL source de l’image vedette de l’articleslug
- le nom de l’article.
Utilisez le tableau posts
renvoyé par la récupération pour afficher une liste d’articles de blog sur la page.
---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}`}>Lire la suite</a> </div> )) } </body></html>
Générer des pages
Section intitulée « Générer des pages »-
Créez la page
src/pages/post/[slug].astro
pour générer dynamiquement une page pour chaque article.Répertoiresrc/
Répertoirelib/
- client.ts
- schema.ts
Répertoirepages/
- index.astro
Répertoirepost/
- [slug].astro
- astro.config.mjs
- package.json
-
Importez et utilisez
getAllPosts()
etgetPost()
pour récupérer les données de Hashnode et générer des routes de pages individuelles pour chaque article.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);--- -
Créez le modèle pour chaque page en utilisant les propriétés de chaque objet
post
. L’exemple ci-dessous montre le titre de l’article et le temps de lecture, puis le contenu complet de l’article :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="fr"><head><title>{post.title}</title></head><body><img src={post.coverImage.url} alt={post.title} /><h1>{post.title}</h1><p>{post.readTimeInMinutes} mins de lecture</p><Fragment set:html={post.content.html} /></body></html><Fragment />
est un composant Astro intégré qui vous permet d’éviter un élément enveloppant inutile. Cela peut s’avérer particulièrement utile lorsque vous récupérez du HTML à partir d’un CMS (par exemple, Hashnode ou WordPress).
Publier votre site
Section intitulée « Publier votre site »Pour déployer votre site, consultez notre guide de déploiement et suivez les instructions de votre hébergeur préféré.
Ressources communautaires
Section intitulée « Ressources communautaires »astro-hashnode
sur GitHub