Skip to content

OverridingComponents

yCENzh edited this page Sep 19, 2026 · 1 revision

Overriding components

Any theme component or layout can be replaced by putting a file at the matching path in your own project. No registration, no config entry.

Mirroring

The theme's components live at src/components/ and src/layouts/ inside the package. Mirror that structure in your project:

node_modules/shirones/src/components/atoms/blog/PostCard.astro   ← the theme's
src/components/atoms/blog/PostCard.astro                        ← yours, wins

That is the whole mechanism. Delete your file and the theme's copy is used again.

The extension does not have to match. If the theme ships PostCard.astro and you write PostCard.svelte, yours is picked up — resolution strips the extension before comparing. The probe order for components is .astro, .svelte, .ts, .js.

Layouts work the same way:

src/layouts/Layout.astro     ← replaces the theme's Layout

What counts as an override

The override table is built by walking the package's component and layout trees and probing your project for a matching path. So:

  • A file of yours that matches a theme path becomes an override.
  • A file of yours that matches nothing is just your own component. The theme will not load it, and nothing warns about it — there is no way to tell it apart from a component you wrote for your own pages.

If you mirror a path and your override does not seem to apply, check the path character by character. A typo produces a perfectly valid component that nothing imports.

index.ts barrels are not overridable at any depth. The theme relies on their named exports staying stable.

Explicit map

When the mirrored path is inconvenient — you keep your components somewhere else, or you want two variants — name the mapping instead:

// astro.config.mjs
shirones({
  components: {
    "atoms/blog/PostCard": "./src/components/MyPostCard.astro",
    "layouts/Layout": "./src/layouts/SiteLayout.astro",
  },
})

Keys are package-relative paths without an extension. Layout keys are prefixed with layouts/. Values resolve against your project root.

The explicit map wins over mirroring when both apply to the same component. A path in the map that does not exist is a hard error at config time, not a silent miss:

[shirones] Component override "atoms/blog/PostCard" points at "./src/components/MyPostCard.astro",
which does not exist (resolved to /you/my-blog/src/components/MyPostCard.astro).

Relative imports inside an override

A mirrored component usually starts life as a copy of the theme's, which means it is full of the theme's relative imports:

---
import PostMeta from "./PostMeta.astro";
import { formatDate } from "../../utils/date";
---

Those keep working. Resolution tries your project first and falls back to the equivalent file inside the package, so a copied component can reference theme siblings you have not mirrored. Mirror PostMeta.astro later and your copy takes over without editing the import.

The same applies to styles. Theme components use <style lang="stylus"> with relative imports:

@import "../styles/variables"

Those are rewritten to point into the package when your project does not have the file, so a copied component's styles still compile.

Finding what you can override

The package ships manifest.json at its root:

cat node_modules/shirones/manifest.json

It lists every overridable component, layout and config module, plus the routes the theme injects.

Read it as an inventory, not a promise. Some components in it are feature-gated (they only render when the relevant config enables them), and some exist for library or integration purposes rather than appearing on a default page. An override on a component that is not currently rendered is applied correctly and simply has nothing to affect.

Overriding config and data

The same mechanism covers shirones/config/ and shirones/config/data/, but there you are shadowing by filename rather than mirroring a tree — the details are in Configuration.

Dev reloads

The override table is rebuilt when a file changes under src/components/, src/layouts/, shirones/config/ or shirones/config/data/, so adding or removing an override in dev takes effect without a restart. Editing the contents of an override is ordinary HMR.

When an override stops applying

If the theme renames or moves a component, your mirrored file stops matching anything and quietly reverts to the theme's version. There is no warning for this, for the reason given above — the theme cannot distinguish a stale override from your own component.

After a major theme upgrade, diff your src/components/ tree against the new manifest.json. Anything you have that is no longer listed is either a component you wrote yourself or an override that needs moving.

Next

Clone this wiki locally