Styled Notion block components for notro, installable via CLI.
This is NOT a component library.
notro-ui is a collection of copy-and-own Astro components. You run a CLI command, the source files are copied into your project, and they become your code. Edit them directly. No prop drilling. No theme configuration. No version lock-in.
This is the same philosophy as shadcn/ui and StarwindUI.
packages/notro-ui/src/templates/ ← canonical source (well-tested starting point)
↓ npx notro-ui init
apps/your-project/src/components/notro/ ← your code, fully owned by you
npx notro-ui initcopies all component files tosrc/components/notro/- Files are yours — edit classes, add variants, restructure markup freely
- Re-run
npx notro-ui add <name>to reset a single component to the template default
# Copy all components into your project
npx notro-ui init
# Or copy a single component
npx notro-ui add calloutFiles are written to src/components/notro/ by default. Use --out-dir to change the destination:
npx notro-ui init --out-dir src/components/blocksYour project needs:
npm install notro-loader tailwind-variantsAnd notro-theme.css imported in your global CSS (src/styles/global.css):
@import "./notro-theme.css";(npx notro-ui init copies notro-theme.css to src/styles/notro-theme.css automatically.)
After init, wire up the local NotroContent in your page:
---
// src/pages/blog/[slug].astro
import { buildLinkToPages, getPlainText } from "notro-loader";
import NotroContent from "../../components/notro/NotroContent.astro";
const { entry } = Astro.props;
---
<NotroContent
markdown={entry.data.markdown}
linkToPages={linkToPages}
/>The local NotroContent.astro (in src/components/notro/) imports all your installed components and maps them to Notion block types. This file is yours — add, remove, or swap components by editing it directly.
Every component exports its style definition using tailwind-variants:
<!-- src/components/notro/Callout.astro -->
export const callout = tv({
base: 'flex items-start gap-3 my-4 rounded-lg border ...',
variants: {
color: {
default: 'notro-bg-gray',
blue_background: 'notro-bg-blue',
// ...
},
},
});To customize, just edit the file:
<!-- Change border radius, padding, font -->
export const callout = tv({
base: 'flex items-start gap-2 my-6 rounded-none border-l-4 pl-6 ...',
...
});Color tokens (notro-bg-gray, notro-text-blue, etc.) are CSS variables defined in notro-theme.css. Edit that file to change colors globally.
| Component | Notion block |
|---|---|
Callout |
Callout block |
Toggle + ToggleTitle |
Toggle block |
H1 – H4 |
Heading 1–4 |
Quote |
Quote block |
TableBlock |
Table |
TableOfContents |
Table of contents |
Columns + Column |
Column layout |
ImageBlock |
Image |
Audio |
Audio embed |
Video |
Video embed |
FileBlock |
File attachment |
PdfBlock |
PDF embed |
PageRef |
Page link |
DatabaseRef |
Database link |
StyledSpan |
Colored / underlined inline text |
Mention |
@mention |
MentionDate |
Date mention |
SyncedBlock |
Synced block |
EmptyBlock |
Empty line spacer |
TableRow / TableCell / TableCol / TableColgroup |
Table internals |
NotroContent.astro |
Entry point — maps all components; edit makeHtmlElement(...) calls to style <p>, <ul>, <a>, etc. |
colors.ts |
Color variant map for tv() |
notro-theme.css |
CSS variables + complex selectors |
# See the full list
npx notro-ui list| Package | Role |
|---|---|
notro-loader |
Headless — Content Loader, MDX pipeline, unstyled components |
notro-ui |
Style layer — copy-and-own styled components that sit on top of notro-loader |
notro-loader provides compileMdxCached (the MDX compiler) and the headless component set. notro-ui's NotroContent.astro uses compileMdxCached directly and wires in your local styled components.
templates/blog/ is the reference implementation. It shows what a project looks like after running npx notro-ui init:
src/components/notro/— installed componentssrc/styles/notro-theme.css— installed themesrc/pages/blog/[slug].astro— usingNotroContent