starlight-blog icon indicating copy to clipboard operation
starlight-blog copied to clipboard

set the order when middleware runs to "post"

Open gdisk opened this issue 7 months ago • 5 comments

Describe the pull request

Configure the starlight-blog middleware to run after other middlewares, thereby achieving compatibility with the Multi-Sidebar feature in the starlight-utils plugin. The benefit of this approach is that it allows simultaneous use of both starlight-blog and Multi-Sidebar: using the blog-specific sidebar on blog pages while utilizing Multi-Sidebar on other pages.

Why

Support writers use starlight-blog and Multi-Sidebar at the same time.

How

Just by set the order for addRouteMiddlewareSection in the plugin, then put starlight-blog plugin after starlight-utils, at last, rewrite the starlight sidebar.This can be implemented with the following code:

// astro.config.mjs
import starlightUtils from "@lorenzo_lewis/starlight-utils";
import starlightBlog from 'starlight-blog'

export const BLOG_PREFIX = "blogs";

export default defineConfig({
  ...
  integrations: [
      plugins: [
        starlightUtils({
            multiSidebar: true
        }),
        // must added after starlightUtils
        starlightBlog({
	    title: "My Blog",
            prefix: BLOG_PREFIX,
	}),
      ],
      components: {
        Sidebar: "./src/components/Sidebar.astro",
      },
      ...
    }),
	...
  ],
});
// src/components/Sidebar.astro
---
import MultiSidebar from "@lorenzo_lewis/starlight-utils/components/Sidebar.astro";
import Default from "@astrojs/starlight/components/Sidebar.astro";
const isBlog = Astro.locals.starlightRoute.id.startsWith("blogs");
---

{
	isBlog && (
		<Default {...Astro.locals.starlightRoute}>
			<slot />
		</Default>
	)
}
{
	!isBlog && (
		<MultiSidebar {...Astro.locals.starlightRoute}>
			<slot />
		</MultiSidebar>
	)
}

By default, plugin middleware runs in the order the plugins are added.Set order: "post" to run after all other middleware.If two plugins add middleware with the same order value, the plugin added first will run first.

gdisk avatar Apr 18 '25 05:04 gdisk

⚠️ No Changeset found

Latest commit: 0e00b3c1e894988c44cecf2432ce3b9bab607b81

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

changeset-bot[bot] avatar Apr 18 '25 05:04 changeset-bot[bot]

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
starlight-blog-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 18, 2025 5:58am

vercel[bot] avatar Apr 18 '25 05:04 vercel[bot]

Thanks for the contribution.

Would you be able to provide a link to a small reproduction of the issue or your Starlight config (including both plugins and how they are configured)? I haven't used a lot the starlight-utils plugin and I'd like to get a better understanding of the issue you're facing.

HiDeoo avatar Apr 18 '25 15:04 HiDeoo

Thanks for the contribution.

Would you be able to provide a link to a small reproduction of the issue or your Starlight config (including both plugins and how they are configured)? I haven't used a lot the starlight-utils plugin and I'd like to get a better understanding of the issue you're facing.

Certainly! I'd be honored to contribute to this project. Here's the complete Starlight configuration file along with the screenshots.

// astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import starlightUtils from "@lorenzo_lewis/starlight-utils";
import starlightBlog from 'starlight-blog'

export default defineConfig({
  integrations: [
    starlight({
      title: 'Docs',
      social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }],
      plugins: [
        starlightUtils({ multiSidebar: true }),
        // must add starlightBlog after starlightUtils, and set the param named 'order' used by 'addRouteMiddleware' to 'post' in starlight-blog plugin(in node_modules)
        // so that, starlight-utils will not use the route data generated by starlight-blog, and these two plugins can work well.
        starlightBlog({ prefix: 'blogs' })
      ],
      components: {
        Sidebar: "./src/components/Sidebar.astro",
      },
      sidebar: [
        {
          label: 'Guides',
          items: [
            { label: 'Example Guide', slug: 'guides/example' },
          ],
        },
        {
          label: 'Reference',
          autogenerate: { directory: 'reference' },
        },
      ],
    }),
  ],
});

when i visit the blogs, i can see the sidebar like this: image

when i visit other docs, i can see the muti-sidebar like this: image

the demo project shared at starlight-demo

gdisk avatar Apr 19 '25 03:04 gdisk

Took a few days to think about the issue, and I think there are multiple points:

Blog plugin middleware order

This is basically what is proposed in the PR and I think this may not be the best solution. The blog plugin middleware is not only used for example to override the sidebar but also to make accessible some blog data for the users and also for other middlewares. Having it run with the post order would not be ideal for this last use case. The current middleware could be split in two middlewares running at different stage altho I think this would only solve a specific compatibility issue between these 2 plugins rather than trying to make it more generic to use starlight-utils and other plugins.

Starlight utils middleware

If we take the example of the starlight-utils plugin and the blog plugin, there are 2 main issues:

  • The starlight-utils plugin seems to run for all pages which removes a lot of flexibility for other plugins. I think having a mechanism to exclude some pages could be beneficial, and for excluded pages, the default sidebar would be automatically be used. This would prevent the issue of where the blog plugin updates the sidebar for blog pages, and also make it easier for users as this would remove the need of a custom sidebar override like the one you described in your previous message. A similar example could be the "Excluded Pages" in the starlight-sidebar-topics plugin which is made specifically for custom pages that use a custom site navigation sidebar.
  • The starlight-utils plugin expects a very strict sidebar configuration where each top-level sidebar item must be either a group or autogenerated. This prevent any plugin from adding a link to the current sidebar. I think this makes sense with the current configuration approach being used altho quite limited. I wonder if this could be improved, not sure yet how, maybe every links added to the sidebar by other previous middlewares (which are not aware of the starlight-utils plugin) should be added to all sidebars when using the Multi-Sidebar option of the starlight-utils plugin. The specific issue with the blog plugin could be addressed in the blog plugin with new options to control how blog links are handled/added, and maybe not added at all and the user would be left in charge of adding them to the sidebar. Altho, I still think there may be a potential improvement to be made in the starlight-utils plugin to allow other plugins to add their own sidebar links.

I'll try to think about this more in the next few days, collect my thoughts, and create some discussions/issues in the Starlight utils repo. Let me also know if you have some thoughts on this too. Definitely an interesting topic but tricky one to solve as it involves multiple plugins and the way they interact with each other.

HiDeoo avatar Apr 23 '25 09:04 HiDeoo