
Gymnopédies
A shadcn registry of dark, serif, glow-leaning React components for long-form reading experiences — blogs, essays, archives, photo journals.
Forms are intentionally out of scope — gymnopédies is a read-only design system.
Quick start
gymnopédies is distributed as a
and listed in the official
as @gymnopedies. The CLI copies component source straight into your
project — there is no runtime npm dependency on gymnopédies itself; you own
the code once it lands.
Requirements: a React 18+ project with Tailwind CSS v4 and the @/* tsconfig path alias.
A fresh Vite app set up with shadcn works out of the box:
The preset pulls in the theme tokens, every non-form shadcn primitive, the
bespoke blog components and the use-mobile hook — and installs their npm
dependencies (@base-ui/react, class-variance-authority, lucide-react,
date-fns, …) automatically.
Prefer to cherry-pick? Add items one at a time:
Then compose a page — see the (source under ) for a worked example.
Component catalogue
src/components/ui/ — 35 shadcn primitives (everything non-form):
src/components/blog/ — 5 bespoke gymnopédies primitives:
src/hooks/use-mobile ships alongside sidebar. Each component has a
*.stories.tsx file — browse them in .
Theme
The dark gymnopédies identity lives in src/styles/globals.css and installs as
the theme registry item:
Stack
- React 18 + TypeScript 5
- Vite 5 + Tailwind CSS v4
- shadcn/ui (style:
base-nova) — primitives from@base-ui/react - For non-Base-UI primitives shadcn still pulls in:
vaul(Drawer),cmdk(Command),recharts(Chart),sonner(Toast),embla-carousel-react(Carousel) - date-fns v4, lucide-react
- Storybook 9 + Chromatic
Distribution
The registry is generated from the file system by scripts/build-registry.ts,
which scans src/components/ui, src/components/blog and src/hooks, derives
each item's npm dependencies from its import statements, and wires internal
cross-references as full item URLs:
Hosting rides along with the Storybook deployment on Vercel: public/r/ is
copied into Storybook's storybook-static/ output via .storybook/main.ts's
staticDirs, so one domain serves the Storybook UI, the registry endpoints and
the sample blog:
- Storybook UI —
- Sample blog —
- Registry preset —
- Individual items — , etc.
Local development
Migration from the 0.1.x prototype (Emotion)
There is no compatibility shim. If you are still on gymnopedies@0.1.x (Emotion
- npm package), the path to v1.x is:
- Remove
gymnopediesfromdependencies. - Install Tailwind v4 in your project:
npx shadcn@latest init. - Adopt the v1 components via
npx shadcn@latest add @gymnopedies/<name>. - Rewrite call sites — APIs are not source-compatible:
- The legacy
Cardreturns asblog/Articlewith the same Props. Picturemoved to a compound API (Picture.Image/Picture.Caption).- The shadcn-style
ui/Cardis a separate compound primitive (Card / CardHeader / CardTitle / CardContent / CardFooter). GlobalStyleskeeps the same drop-in usability but is now a zero- dependency<style>injector instead of Emotion's<Global>.
- The legacy
Changelog
See for the full release history.
License
© shoota