Hashnode & Astro
Ta treść nie jest jeszcze dostępna w Twoim języku.
Hashnode is a hosted CMS that allows you to create a blog or publication.
Integrating with Astro
Section titled Integrating with AstroThe Hashnode Public API is a GraphQL API that allows you to interact with Hashnode. This guide uses graphql-request
, a minimal GraphQL client that works well with Astro, to bring your Hashnode data into your Astro project.
Prerequisites
Section titled PrerequisitesTo get started you will need to have the following:
-
An Astro project - If you don’t have an Astro project yet, our Installation guide will get you up and running in no time.
-
A Hashnode site - You can create free personal site by visiting Hashnode.
Installing dependencies
Section titled Installing dependenciesInstall the graphql-request
package using the package manager of your choice:
npm install graphql-request
pnpm add graphql-request
yarn add graphql-request
Making a blog with Astro and Hashnode
Section titled Making a blog with Astro and HashnodeThis guide uses graphql-request
, a minimal GraphQL client that works well with Astro, to bring your Hashnode data into your Astro project.
Prerequisites
Section titled Prerequisites- A Hashnode Blog
- An Astro project integrated with the graphql-request package installed.
This example will create an index page that lists posts with links to dynamically-generated individual post pages.
Fetching Data
Section titled Fetching Data-
To fetch your site’s data with the
graphql-request
package, make asrc/lib
directory and create two new filesclient.ts
&schema.ts
:Foldersrc/
Folderlib/
- client.ts
- schema.ts
Folderpages/
- index.astro
- astro.config.mjs
- package.json
-
Initialize an API instance with the GraphQLClient using the URL from your Hashnode Website.
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;}; -
Configure
schema.ts
to define the shape of the data returned from the Hashnode API.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>
Displaying a list of posts
Section titled Displaying a list of postsFetching via getAllPosts()
returns an array of objects containing the properties for each post such as:
title
- the title of the postbrief
- the HTML rendering of the content of the postcoverImage.url
- the source URL of the featured image of the postslug
- the slug of the post
Use the posts
array returned from the fetch to display a list of blog posts on the 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}`}>Read more</a> </div> )) } </body></html>