nuxt-x-cards
nuxt-x-cards
Premium card component library for Nuxt 4. Ships 12 auto-imported components covering heroes, features, media, product showcases, team members, reviews, testimonials, pricing, and comparison tables — all sharing a unified Oura/Rivian-inspired design language: warm neutral surfaces, cinematic image filters, 4px-grid spacing, and WCAG AA contrast.
Installation
npm install @xenterprises/nuxt-x-cards
Peer dependencies (install if your app doesn't already have them): nuxt ^4, vue ^3, @nuxt/ui ^4.6.1, @iconify-json/lucide, and @iconify-json/simple-icons.
What the consumer writes
The minimal consumer setup is an extends entry plus an optional app/app.config.ts with your brand overrides — no components, pages, or server code to write. All 12 XCard* components and the useXCards() composable are auto-imported, and the layer registers no pages, middleware, or server routes (its single plugin only injects the default Google Fonts stylesheet into <head> — disable by setting x.cards.fonts.googleFontsUrl to an empty string).
// nuxt.config.ts
export default defineNuxtConfig({
extends: ["@xenterprises/nuxt-x-cards"],
});
// app/app.config.ts — must live in app/, not the project root
export default defineAppConfig({
x: {
cards: {
defaults: {
filter: "moody", // global image filter fallback for hero/media cards
},
brand: {
appName: "My Brand",
},
},
},
});
Then drop any XCard* component into a page:
<XCardHeroFullscreen
title="Built for speed"
image-url="/hero.jpg"
:primary-cta="{ label: 'Order Now', to: '/order' }"
/>
Every key under x.cards is optional — omit the whole app.config.ts and the layer falls back to its Oura/Rivian-inspired defaults (cream/olive palettes, cinematic filter, bottom-blur overlay). No environment variables are required — all configuration is via app.config.ts.
What the layer provides
12 components in five families, all auto-imported under the XCard prefix. Components fall back to useXCards() global defaults for filter, overlay, and aspect ratio unless overridden per instance.
HeroCards — above-the-fold hero sections
<XCardHeroFullscreen />— Full-viewport hero with gradient overlay, cinematic filter, and one or two CTAs<XCardHeroSplit />— Split two-column hero: image one side, editorial text the other, with hover zoom-in
FeatureCards — feature / benefit grids
<XCardFeature />— Multi-mode card supporting icon, full-bleed image, or large stat figure with four surface variants (default, elevated, bordered, glass)<XCardGrid />— Responsive 1/2/3/4-column CSS grid wrapper with 4px-grid gap tokens; slot-based, works with any XCard
MediaCards — full-bleed imagery
<XCardMedia />— Immersive full-bleed image card with gradient overlay, reveal animations, and configurable aspect ratio<XCardImageFilter />— Before/after filter showcase card with hover-to-reveal original; click/Enter/Space toggle for keyboard and touch users
ContentCards — social proof and people
<XCardProduct />— Product showcase card with color swatch switcher, image swap, andcolor-changeemit<XCardTeam />— Team member portrait card with role, bio, and ghost social-icon buttons<XCardReview />— Multi-source review card (Google, Yelp, Trustpilot, App Store, generic) with 5-star rating and avatar/initial fallback<XCardTestimonial />— Editorial testimonial card with split portrait + serif italic blockquote
PricingComparison — conversion blocks
<XCardPricing />— Pricing tier card with feature checklist, badge, and dark-inverted highlighted state<XCardComparison />— "Us vs Them" comparison table with boolean check/x or string values per row, dark-inverted "ours" column
Composables
useXCards()
Returns the merged layer configuration (consumer overrides deep-merged over defaults via defu). Use it to read design tokens in your own components.
const config = useXCards();
// config.colors.primary → "cream"
// config.defaults.filter → "cinematic"
// config.fonts.serif → "'Playfair Display', ..."
Returns XCardsConfig:
| Property | Type | Description |
|---|---|---|
colors.primary | string | Primary color name ("cream" default). |
colors.neutral | string | Neutral color name ("olive" default). |
colors.accents | object | { gold, goldHover, blue, green } hex values. |
fonts.sans | string | Sans-serif font stack. |
fonts.serif | string | Serif font stack (Playfair Display). |
fonts.display | string | Display font stack. |
fonts.googleFontsUrl | string | Google Fonts URL to inject. |
radius.card | string | Card border radius ('0.75rem'). |
radius.panel | string | Panel border radius ('1.5rem'). |
radius.pill | string | Pill/button border radius ('9999px'). |
spacing.baseUnit | number | Grid base unit in px (default 4). |
defaults.filter | string | Default image filter: "cinematic", "moody", "golden", "cool", "dramatic", "warm", "clean", "product", or "none". |
defaults.overlay | string | Default overlay style ('bottom-blur'). |
defaults.mediaAspectRatio | string | Default media aspect ratio ('landscape'). |
defaults.productAspectRatio | string | Default product aspect ratio ('product'). |
brand.appName | string | App name used in component titles ('nuxt-x-cards'). |
brand.logoIcon | string | Iconify icon class for the logo ('i-lucide-square-x'). |
Configuration
Override any token by adding an x.cards key to the consumer's app/app.config.ts:
// app/app.config.ts
export default defineAppConfig({
x: {
cards: {
colors: {
primary: "stone",
accents: {
gold: "#F5C518",
},
},
defaults: {
filter: "moody",
},
brand: {
appName: "My Brand",
logoIcon: "i-lucide-star",
},
},
},
});
Environment Variables
None required.
Minimal Usage Example
<template>
<!-- Hero section -->
<XCardHeroFullscreen
title="Built for speed"
subtitle="The fastest car we've ever made"
image-url="/hero.jpg"
filter="cinematic"
:primary-cta="{ label: 'Order Now', to: '/order' }"
:secondary-cta="{ label: 'Learn More', to: '/specs' }"
/>
<!-- Feature grid -->
<XCardGrid>
<XCardFeature
v-for="f in features"
:key="f.title"
:title="f.title"
:description="f.description"
:icon="f.icon"
/>
</XCardGrid>
<!-- Pricing -->
<XCardPricing
title="Pro"
price="$49"
period="/ month"
:features="['Unlimited projects', 'Priority support', 'API access']"
:highlighted="true"
:cta="{ label: 'Get started', to: '/signup' }"
/>
</template>
How It Works
Each component imports useXCards() to read the merged config for its design tokens. useXCards() calls useAppConfig() and reads appConfig.x.cards, then deep-merges it over the built-in defaults using defu — so consumers only need to override the keys they want to change. XCardImageFilter provides keyboard and touch accessibility: hover reveals the original, and click, Enter, and Space toggle the state for keyboard and touch users. All components use CSS custom properties driven by the design tokens so color swaps require no component changes. The layer registers no pages, middleware, or server routes; its one plugin loads x.cards.fonts.googleFontsUrl into <head> so the default fonts (Inter + Playfair Display) render with zero consumer code.
AI Context
package: "@xenterprises/nuxt-x-cards"
type: nuxt-layer
prefix: XCard
use-when: >
Adding premium card components to a Nuxt 4 project. Provides 12 auto-imported
XCard-prefixed components (heroes, feature grids, media, product showcases, team
members, reviews, testimonials, pricing, comparison) sharing a warm neutral /
cinematic design language. Configure design tokens via app.config.ts under x.cards.
No pages, middleware, or server routes are registered.
