Skip to content
HomePagesHomePages template kit
Menu

template-kit/no-bare-css-import

The template-kit/no-bare-css-import authoring rule — what it enforces, why, and how to fix it.

No @import in hand-written CSS. Not even a package’s — the browser drops it silently, and the styles simply never ship.

A hand-written stylesheet may not contain a top-level @import. That means the stylesheets the CSS build collects out of your section and template folders — a section’s styles.css, any other .css in a section folder, and a template’s own hand-written stylesheet.

There is no carve-out for a package specifier. @import "swiper/css"; is exactly as illegal here as @import "./tokens.css";. Both are reported, at the 1-based line of the first offender.

The scan is comment-aware, so an @import written about rather than as code is prose and passes:

/* css-reason: … */
/* Never @import here — see template-kit/no-bare-css-import. */ ← fine, it's a comment

Your Tailwind entry is not one of these files. The file that carries @import "tailwindcss"; and @import "@homepages/template-kit/styles.css"; is a Tailwind entry: it is compiled by Tailwind, its @imports are resolved at build time, and it is never wrapped in a cascade layer. It is not hand-written section or template CSS, and this rule does not reach it.

Every hand-CSS file the build collects is concatenated into a cascade layer:

@layer sections {
/* your styles.css, pasted in here */
}

That is how a section’s CSS lands in the layer order (theme, base, components, sections, template, utilities) instead of fighting Tailwind’s utilities for specificity.

@import is invalid inside a @layer block. And CSS’s error handling for an invalid at-rule is not an error — it is a shrug. The browser drops the statement and parses on. Nothing throws. Nothing warns. Your build succeeds, your preview looks plausible because the package’s own styling is missing in a way you have learned to read as “unstyled yet”, and the published page ships without the rules you imported. This is the quietest failure in the whole kit: the only signal is that the styles are not there.

Delete the @import.

A package’s stylesheet is reached from the code that needs it, not from CSS. Write import "swiper/css"; in the component or island that renders the thing — the CSS build bundles your Renderer.tsx and everything it imports, transitively, precisely to harvest those imports, and it compiles what they pull in into this section’s cascade layer. Package CSS goes in first and your own hand-CSS second, so at equal specificity your rules win.

Two things authors get wrong immediately after:

  • Bare specifiers only. A CSS import that resolves outside node_modules is an error, not a fallback. Your own stylesheets are discovered by filename — importing one from code would ship it twice. See no-css-import-from-render-path.
  • Importing is not installing. import "swiper/css" does not add swiper to your package.json. Add the dependency, or the install that builds your submission has nothing to resolve.
sections/gallery/styles.css
/* css-reason: styles the slide DOM the Swiper carousel builds at runtime. */
@import "swiper/css"; /* template-kit/no-bare-css-import — silently dropped */
.tr-gallery .swiper-pagination-bullet-active {
background: var(--tr-color-primary);
}

The pagination override ships. Swiper’s own layout CSS does not — and no error says so.

The @import is gone from the stylesheet:

sections/gallery/styles.css
/* css-reason: overrides the Swiper pagination DOM the carousel builds at runtime —
those nodes carry the library's own classes, which Tailwind's scanner never sees. */
.tr-gallery .swiper-pagination-bullet-active {
background: var(--tr-color-primary);
}

…and the package’s CSS is imported from the module that needs it, which is what routes it into this section’s layer:

sections/gallery/Carousel.tsx
"use client";
import Swiper from "swiper";
import "swiper/css"; // ← the sanctioned channel: the CSS build harvests this import
export default function Carousel({ slides }: { slides: { id: string; url: string }[] }) {
// …
}
  • no-css-import-from-render-path — the other half of this mental model. Hand-written CSS: no @imports at all, package or otherwise. Render path: no local CSS imports, but a package’s bare specifier is exactly right. An author who reads only one of the two pages will be confused by the other.
  • css-reason — the comment every hand-written stylesheet opens with.
  • Theme and CSS — the cascade-layer order, and the one file that legitimately does @import "tailwindcss".