← Back to all blogs

Co-located TanStack Router, TanStack Query, and Shadcn Sidebar in Astro

| November 3, 2024

Table of Contents

Introduction

As of writing this article on November 3, 2024, I’m using the latest versions of the following packages:

{
"astro": "^4.16.7",
"@tanstack/react-query": "^5.59.16",
"@tanstack/react-router": "^1.78.0"
}

Before diving into the integration process, let’s briefly overview the tools we’ll be using:


Integrating TanStack Router

TanStack Router offers a co-located routing approach, allowing you to define routes alongside your components. This promotes better organization and scalability.

Installation

First, install TanStack Router and its dependencies:

Terminal window
pnpm install @tanstack/router

Configuration

TL;DR To create a URL like https://goastro.website/dashboard, organize your project folders as illustrated in the screenshot below:

Folder structure

Key Points:

  1. Must to have requirement from Tanstack Router: The red part in screenshot must be same in this case the “/dashboard” route.

  2. Better to have requirement from Astro: The yellow part can be anything, but if you want the url show at the address bar to be consistent, you should create the folder named “dashboard”.

  3. Modify astro.config.mjs as following:

    Click to expand the code
    astro.config.mjs
    // @ts-check
    import { defineConfig } from "astro/config";
    import tailwind from "@astrojs/tailwind";
    import remarkMath from "remark-math";
    import rehypeKatex from "rehype-katex";
    import partytown from "@astrojs/partytown";
    import react from "@astrojs/react";
    import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
    import mdx from "@astrojs/mdx";
    import icon from "astro-icon";
    import sitemap from "@astrojs/sitemap";
    // https://astro.build/config
    export default defineConfig({
    integrations: [
    react(),
    mdx(),
    tailwind({
    applyBaseStyles: false,
    }),
    partytown({
    // Adds dataLayer.push as a forwarding-event.
    config: {
    forward: ["dataLayer.push"],
    },
    }),
    icon(),
    sitemap(),
    ],
    vite: {
    plugins: [
    TanStackRouterVite({
    routesDirectory: "./src/toolbox/routes",
    generatedRouteTree: "./src/toolbox/routeTree.gen.ts",
    routeFileIgnorePrefix: "-",
    quoteStyle: "double",
    }),
    ],
    },
    });

Setting Up TanStack Query

Click to expand the example code
src/toolbox/routes/main.tsx
```tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
ErrorComponent,
RouterProvider,
createRouter,
} from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";
import { Spinner } from "@/components/Spinner";
// Initialize QueryClient with default options
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 5, // Number of retry attempts
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff: 1s, 2s, 4s, etc.
refetchOnWindowFocus: false, // Optional: Disable refetch on window focus
},
},
});
// Create a new router instance
const router = createRouter({
routeTree,
defaultPendingComponent: () => (
<div className="p-2 text-2xl">
<Spinner />
</div>
),
defaultErrorComponent: ({ error }) => <ErrorComponent error={error} />,
context: {
queryClient,
},
defaultPreload: "intent",
defaultPreloadStaleTime: 0,
});
// Extend TanStack Router's context to include our router
declare module "@tanstack/react-router" {
interface Register {
router: typeof router;
}
}
export const Dashboard = () => (
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} defaultPreload="intent" />
</QueryClientProvider>
);
```

Adding Shadcn Sidebar for Navigation

Shadcn provides a customizable and accessible sidebar component that integrates seamlessly with your Astro application.

Installation

Install the Shadcn Sidebar component:

Terminal window
pnpm dlx shadcn@latest add sidebar

Configuration

Important: Modify components/ui/sidebar.tsx by adding the type keyword before VariantProps to prevent rendering issues in Astro.

src/components/ui/sidebar.tsx
import { type VariantProps, cva } from "class-variance-authority";
// Rest of your sidebar component code...

Common Error:

You will encounter the following error if the type keyword is missing at the time of writing:

[ERROR] [vite] The requested module 'class-variance-authority' does not provide an export named 'VariantProps'
Stack trace:
at /Users/guo/beneficial-bar/node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-BWSbWtLw.js:52053:15
[...] See full stack trace in the browser, or rerun with --verbose.

Adding type ensures proper type imports and prevents such errors.


Conclusion

By implementing the methods discussed in this article, I successfully built my website with an integrated toolbox within my blog. This toolbox includes handy utilities like a Datetime Converter and a GitHub Raw Link Converter. If you’re interested in exploring these tools, simply click on the Toolbox link in the navigation bar. You’ll find detailed instructions and interactive demonstrations that showcase how each tool works.

Integrating TanStack Router, TanStack Query, and Shadcn’s Sidebar into your Astro project not only enhances the functionality of your website but also improves the overall user experience. Whether you’re developing a personal blog, a corporate site, or a complex web application, this approach provides a scalable and maintainable foundation for your projects.


References


Happy Coding!