How I created this page with Astro and Sanity - Part 2 - Querying

Querying

I think this part is the most fun in every project, connecting different services together to create a solution.

Afraid to loose some helpful code (defining content and such) I created a new folder in my projects ({projectRoot}/src/pages/sanity-blog/). This folder contains two files:

  • index.astro
  • [slug].astro

Yes, the last one looks a bit wierd, but I think it's called "file based routing", where the folders and files inside of your /pages/-folder is basicly what you see in the URL of the page. Here is a very simplified routing table:

  • [your-domain].com -> /pages/index.astro
  • [your.domain].com/about -> /pages/about.astro (OR! /pages/about/index.astro)

That last one could be a bit confusing. But also shows why i created a folder named "sanity-blog". Beware of conflicts with routing name, since you cannot have a file /pages/about.astro and a folder with "about" as a name and "index.astro" as a file inside it.

If a user visits my page, and goes to jezpoz.dev/sanity-blog, they will be presented with the content that is in my /pages/sanity-blog/index.astro-file.

Now, you might be wondering about the brackets in the other file ([slug].astro). This is to allows dynamic routing, but all routes will render using the file i created. This handles one parameter, you can also add ... so it will catch all levels. More about this in the documation for routing.

"I thought you said you get bored of documentation?" - Yes, so lets get to some code.

/pages/sanity-blog/index.astro

This page will be a listing page of the most recent blog posts I have written. Maybe you found this post on there, who knows? The way this works is by fetching all posts I have written in Sanity (pagination will come later), and render them in a list. I've called the elements "blog post previews".

I've created a helper function to have all my queries and query-functions in.

Fetching preview blog posts from Sanity
type SanitySlug = {
  type: "_slug";
  current: string;
};

type SanityAuthorPreview = {
  name: string;
  image: SanityImageSource;
  slug: SanitySlug;
};

type PreviewPost = {
  title: string;
  slug: SanitySlug;
  mainImage: SanityImageSource;
  publishedAt: string;
  author: SanityAuthorPreview;
};
const previewQuery = groq`
  *[_type == "post" && defined(slug)][]{
    title,
    slug,
    mainImage,
    publishedAt,
    author->{
      name,
      image,
      slug,
    }
  } | order(publishedAt desc)
`;
export async function getPreviewPosts(): Promise<PreviewPost[]> {
  try {
    return await sanityClient.fetch<PreviewPost[]>(previewQuery);
  } catch (err) {
    console.error(err);
    throw new Error("Could not fetch posts preview");
  }
}
You can read more about this example code here