@xenterprises/nuxt-x-marketing

A comprehensive Nuxt layer for building marketing websites with 38+ pre-built components. Features dark mode support, responsive design, accessibility, and seamless integration with Nuxt UI.
8,219
Install
npm install @xenterprises/nuxt-x-marketing
Latest Version:1.15.5
Vue:3
License:Custom
Last Updated:Oct 22, 2026
Links: npm
Maintainer: tim-mushen

@xenterprises/nuxt-x-marketing

A comprehensive Nuxt layer for building marketing websites with 38+ pre-built components. Features dark mode support, responsive design, accessibility, and seamless integration with Nuxt UI.

Features

  • 38+ Marketing Components - Hero, Features, Pricing, Testimonials, Blog, Affiliate/Review, and more
  • Consent-aware tracking - Drop GTM/GA4/Clarity IDs in app.config, the cookie banner auto-fires them on accept
  • Zero Required Props - Every component works out of the box with sensible defaults
  • Dark Mode Support - All components support light and dark themes
  • Responsive Design - Mobile-first approach with tablet and desktop breakpoints
  • Accessible - WCAG 2.0 AA compliant with proper ARIA attributes
  • Customizable - Props-based configuration with slot overrides
  • Nuxt UI v4 Integration - Built on top of Nuxt UI v4 components
  • Animations - Scroll-triggered fade-in animations and parallax effects
  • Two Footer Modes - Generic white-label (XMarkLayoutFooter) and X Enterprises branded (XFooter)

Installation

npm install @xenterprises/nuxt-x-marketing

Add the layer to your nuxt.config.js:

export default defineNuxtConfig({
  extends: "@xenterprises/nuxt-x-marketing",
});

Quick Start

What the consumer writes

The layer is batteries-included: it ships a default app shell (navbar + footer + cookie-consent banner) and default pages (/, /blog, /blog/[...slug]). You do not write an app.vue — configure the shell in app/app.config.ts under the xMarketing namespace (it must live in app/, not the project root):

// app/app.config.ts
export default defineAppConfig({
  xMarketing: {
    name: "Acme Inc",
    url: "https://acme.com",
    header: {
      logo: { src: "/logo.svg", srcDark: "/logo-dark.svg", alt: "Acme" },
      nav: {
        links: [
          { label: "Pricing", to: "/#pricing" },
          { label: "Blog", to: "/blog" },
        ],
        buttons: [{ label: "Get Started", to: "/signup", color: "primary" }],
      },
    },
    footer: {
      logo: { src: "/logo.svg", alt: "Acme" },
      body: "Building the future of modern software.",
      socials: [
        { name: "GitHub", url: "https://github.com/acme", icon: "i-lucide-github" },
      ],
      columns: [
        {
          headerLabel: "Product",
          links: [{ label: "Blog", to: "/blog" }],
        },
      ],
    },
    blog: { active: true, title: "Blog" },
    tracking: { gtmId: "GTM-XXXXXXX" }, // optional; fires only after consent
  },
});

Blog posts are markdown in content/blog/*.md — re-declare the blog collection in your own content.config.ts so Nuxt Content binds it to your content dir (the layer's .playground/content.config.ts is the reference).

Opting out of the defaults

Every shipped default has a switch or a standard Nuxt override:

  • xMarketing.header.active: false — removes the default navbar from the shell
  • xMarketing.footer.active: false — removes the default footer
  • xMarketing.consent.active: false — removes the cookie-consent banner (tracking scripts then never fire)
  • xMarketing.blog.active: false — the shipped /blog pages 404
  • Replace the whole shell by shipping your own app/app.vue; replace any page by shipping the same path under app/pages/ (standard Nuxt layer overriding)

Example Landing Page

All components work with zero required props — just drop them in and customize as needed:

<template>
  <div>
    <!-- Hero — works with zero props, or fully customized -->
    <XMarkHero
      :img="{ src: 'https://images.unsplash.com/photo-1551434678-e076c223a692', alt: 'Hero' }"
      eyebrow="Welcome to the future"
      title="Build something amazing today"
      subtitle="The modern platform for teams who want to ship faster."
      align="left"
      overlay="gradient"
      :buttons="[
        { label: 'Get Started Free', color: 'primary' },
        { label: 'Watch Demo', variant: 'outline' }
      ]"
    />

    <!-- Features — works with zero props, or pass your own -->
    <XMarkSection id="features" bg="default" padding="xl">
      <header class="text-center max-w-3xl mx-auto mb-16">
        <h2 class="xText-headline">Everything you need to succeed</h2>
      </header>
      <XMarkFeatures :features="features" layout="grid" :columns="3" />
    </XMarkSection>

    <!-- Testimonials -->
    <XMarkSection bg="subtle" padding="xl">
      <XMarkTestimonials :testimonials="testimonials" layout="grid" />
    </XMarkSection>

    <!-- Pricing -->
    <XMarkSection bg="default" padding="xl">
      <XMarkPricingPlans :plans="pricingPlans" />
    </XMarkSection>
  </div>
</template>

<script setup>
const features = [
  { icon: 'i-lucide-zap', title: 'Lightning Fast', description: 'Built for speed.' },
  { icon: 'i-lucide-shield-check', title: 'Secure by Default', description: 'Enterprise-grade security.' },
  { icon: 'i-lucide-users', title: 'Team Collaboration', description: 'Real-time collaboration tools.' },
]

const testimonials = [
  { quote: 'This platform transformed how our team works.', name: 'Sarah Chen', title: 'CTO', company: 'TechStart', rating: 5 },
]

const pricingPlans = [
  { name: 'Starter', price: '$19', period: '/month', features: ['5 team members', 'Basic analytics'], button: { label: 'Start Free Trial' } },
  { name: 'Pro', price: '$49', period: '/month', features: ['25 team members', 'Advanced analytics'], button: { label: 'Start Free Trial' }, popular: true },
]
</script>

Components

Core Layout

XMarkLayoutNavbar

Fixed navigation header with transparent-to-solid scroll transition. Falls back to xMarketing.header (logo, nav links, nav buttons) when props are omitted.

<XMarkLayoutNavbar
  :links="[{ label: 'Features', to: '/#features' }]"
  :logo="{ src: '/logo.svg', srcDark: '/logo-dark.svg', alt: 'Company' }"
  :buttons="[
    { label: 'Sign In', to: '/login', variant: 'ghost' },
    { label: 'Get Started', to: '/signup', color: 'primary' },
  ]"
  :transparent="true"
  :scroll-threshold="100"
/>
Prop Type Default Description
links Array xMarketing.header.nav.links Navigation links { label, to }
logo Object xMarketing.header.logo Logo { src, srcDark?, alt? }
buttons Array xMarketing.header.nav.buttons Action buttons { label, to, color?, variant?, icon? }
transparent Boolean true Start transparent over hero
scrollThreshold Number 100 Pixels before transition
XMarkSection

Section wrapper with background variants and optional patterns.

<XMarkSection bg="subtle" padding="xl" pattern="dots">
  <h2>Section Content</h2>
</XMarkSection>
Prop Type Default Description
bg String 'default' default, subtle, elevated, bold, transparent
padding String 'lg' none, sm, md, lg, xl
container String 'lg' sm, md, lg, xl, full, none
pattern String '' dots, grid, diagonal, topography, circuit, waves
patternOpacity Number 0.05 Pattern opacity (0-1)
bgImage String '' Background image URL
parallax Boolean false Enable parallax on bg image
XMarkLayoutFooter

Full footer with brand, link columns, social icons, and newsletter.

<XMarkLayoutFooter
  :logo="{ src: '/logo.svg', alt: 'Company' }"
  description="Building the future of modern software."
  :social="[{ name: 'Twitter', href: 'https://twitter.com', icon: 'i-lucide-twitter' }]"
  :columns="[{ title: 'Product', links: [{ label: 'Features', to: '/features' }] }]"
  :legal-links="[{ label: 'Privacy', to: '/privacy' }]"
  :has-newsletter="true"
  @newsletter-submit="handleSubmit"
/>
Prop Type Default Description
logo Object null Logo { src, alt? }
description String '' Brand description
social Array [] Social links { name, href, icon }
columns Array [] Link columns { title, links: [{ label, to }] }
legalLinks Array [] Legal links { label, to }
copyright String auto Copyright text
hasNewsletter Boolean false Show newsletter section
XMarkLayoutFooterLegal

Minimal footer with copyright and legal links only.

<XMarkLayoutFooterLegal
  copyright="© 2026 Acme Inc. All rights reserved."
  :links="[{ label: 'Privacy', to: '/privacy' }]"
/>

Hero & Landing

XMarkHero

Full-screen hero with image/video background and overlay.

<XMarkHero
  image-src="https://example.com/hero.jpg"
  video-src="https://example.com/hero.mp4"
  eyebrow="Welcome"
  title="Build something amazing"
  subtitle="The modern platform for teams."
  align="left"
  vertical-align="center"
  overlay="gradient"
  :show-scroll-indicator="true"
>
  <template #actions>
    <UButton size="xl" color="white">Get Started</UButton>
  </template>
</XMarkHero>
Prop Type Default Description
imageSrc String '' Background image URL
videoSrc String '' Background video URL
eyebrow String '' Small text above title
title String required Main headline
subtitle String '' Supporting text
align String 'left' left, center, right
verticalAlign String 'center' center, bottom
overlay String 'gradient' light, heavy, gradient, none
showScrollIndicator Boolean true Show scroll arrow

Content Sections

XMarkFeatures

Feature grid with icons, images, and optional links.

<XMarkFeatures
  :features="[
    { icon: 'i-lucide-zap', title: 'Fast', description: 'Lightning fast performance.' },
    { icon: 'i-lucide-shield', title: 'Secure', description: 'Enterprise security.' },
  ]"
  layout="grid"
  :columns="3"
/>
Prop Type Default Description
features Array required Features { icon?, image?, title, description, link? }
layout String 'grid' grid, list, alternating
columns Number 3 Grid columns (2, 3, or 4)
XMarkTestimonials

Testimonial cards in grid or carousel layout.

<XMarkTestimonials
  :testimonials="[
    {
      quote: 'Amazing product!',
      name: 'John Doe',
      title: 'CEO',
      company: 'Acme Inc',
      avatar: 'https://example.com/avatar.jpg',
    },
  ]"
  layout="grid"
/>
XMarkPricing

Pricing cards with billing toggle and popular badge.

<XMarkPricing
  :plans="[
    {
      name: 'Starter',
      price: '$19',
      period: 'month',
      description: 'Perfect for small teams.',
      features: ['5 team members', 'Basic analytics'],
      cta: 'Start Free Trial',
    },
    {
      name: 'Pro',
      price: '$49',
      period: 'month',
      features: ['25 team members', 'Advanced analytics'],
      cta: 'Start Free Trial',
      popular: true,
    },
  ]"
  :show-billing-toggle="true"
  :yearly-discount="20"
  @select="handlePlanSelect"
/>
Prop Type Default Description
plans Array required Pricing plans
highlighted String '' Plan name to highlight
showBillingToggle Boolean false Show monthly/yearly toggle
yearlyDiscount Number 20 Yearly discount percentage
XMarkComparison

Feature comparison table across plans.

<XMarkComparison
  :plans="['Starter', 'Pro', 'Enterprise']"
  :highlighted="'Pro'"
  :feature-groups="[
    {
      name: 'Core Features',
      features: [
        { name: 'Users', values: ['5', '25', 'Unlimited'] },
        { name: 'Storage', values: ['1GB', '10GB', 'Unlimited'] },
      ],
    },
  ]"
/>
XMarkNewsletter

Email signup form with variants.

<XMarkNewsletter
  title="Subscribe to our newsletter"
  description="Get the latest updates."
  :button="{ label: 'Subscribe' }"
  placeholder="Enter your email"
  variant="default"
  @submit="handleSubmit"
/>
Prop Type Default Description
title String 'Subscribe...' Form title
description String '' Form description
button Object { label: 'Subscribe' } Button config { label, color? }
variant String 'default' default, minimal, inline

Blog Components

XMarkBlogCard

Blog post card with image, title, excerpt, and author.

<XMarkBlogCard
  :post="{
    title: 'Getting Started with Nuxt',
    slug: 'getting-started',
    excerpt: 'Learn how to build modern web apps.',
    image: '/blog/cover.jpg',
    date: '2024-01-15',
    author: { name: 'John Doe', avatar: '/avatars/john.jpg' },
    category: 'Tutorial',
  }"
  variant="default"
/>
XMarkBlogList

Blog listing grid with optional featured post.

<XMarkBlogList
  :posts="posts"
  :columns="3"
  :show-featured="true"
/>
XMarkBlogDetail

Full blog post view with author, share buttons, and navigation.

<XMarkBlogDetail
  :post="post"
  :author="author"
  :related-posts="relatedPosts"
/>
XMarkBlogSidebar

Blog sidebar with search, categories, tags, and recent posts.

<XMarkBlogSidebar
  :categories="['Tutorials', 'News', 'Updates']"
  :tags="['vue', 'nuxt', 'javascript']"
  :recent-posts="recentPosts"
  :show-search="true"
  @search="handleSearch"
  @category-click="handleCategoryClick"
/>
XMarkBlogAuthor

Author bio with social links.

<XMarkBlogAuthor
  :author="{
    name: 'John Doe',
    title: 'Senior Developer',
    avatar: '/avatars/john.jpg',
    bio: 'Passionate about building great software.',
    social: { twitter: 'https://twitter.com/johndoe' },
  }"
  variant="full"
/>
Prop Type Default Description
author Object required Author data
variant String 'inline' inline, sm, full, card
XMarkBlogNavigation

Previous/next post navigation.

<XMarkBlogNavigation
  :previous="{ title: 'Previous Post', slug: 'prev-post' }"
  :next="{ title: 'Next Post', slug: 'next-post' }"
  base-path="/blog"
/>
XMarkBlogCTA

In-article newsletter signup.

<XMarkBlogCTA
  title="Enjoyed this article?"
  description="Subscribe for more content."
  variant="featured"
  @submit="handleSubmit"
/>

UI Elements

XMarkBadge

Trust and feature badges with presets.

<XMarkBadge preset="no-credit-card" variant="subtle" />
<XMarkBadge preset="cancel-anytime" />
<XMarkBadge icon="i-lucide-star" label="5-star rated" />
Prop Type Default Description
preset String '' no-credit-card, cancel-anytime, money-back, free-trial, secure
icon String '' Custom icon (if no preset)
label String '' Custom label (if no preset)
variant String 'default' default, subtle, outline
XMarkGlassCard

Glassmorphism card with blur effect.

<XMarkGlassCard :blur="10" :opacity="0.1">
  <h3>Card Content</h3>
</XMarkGlassCard>
XMarkPromoCard

Promotional card with image and CTA.

<XMarkPromoCard
  title="Special Offer"
  description="Get 50% off your first month."
  image="/promo.jpg"
  cta-text="Claim Offer"
  cta-link="/pricing"
/>
XMarkGlowDivider

Glowing section divider.

<XMarkGlowDivider color="primary" :intensity="0.5" />
XMarkPatternBg

SVG background patterns.

<XMarkPatternBg pattern="dots" :opacity="0.05" />
Prop Type Default Description
pattern String 'dots' dots, grid, diagonal, topography, circuit, waves
opacity Number 0.05 Pattern opacity
XMarkSectionStitch

Section divider shapes.

<XMarkSectionStitch shape="wave" position="top" :flip="false" />
Prop Type Default Description
shape String 'wave' angle, wave, curve, triangle, zigzag
position String 'bottom' top, bottom
flip Boolean false Flip horizontally

Modals & Overlays

XMarkVideoModal

Video lightbox supporting YouTube, Vimeo, and direct URLs.

<XMarkVideoModal
  v-model="showVideo"
  url="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  title="Product Demo"
/>
XMarkImageLightbox

Image gallery lightbox with keyboard navigation.

<XMarkImageLightbox
  v-model="showLightbox"
  :images="[
    { src: '/gallery/1.jpg', alt: 'Image 1', caption: 'First image' },
    { src: '/gallery/2.jpg', alt: 'Image 2' },
  ]"
  :start-index="0"
/>
XMarkFeatureModal

Feature detail modal.

<XMarkFeatureModal
  v-model="showFeature"
  :feature="{
    icon: 'i-lucide-zap',
    title: 'Lightning Fast',
    description: 'Detailed description...',
    image: '/features/speed.jpg',
  }"
/>

Notifications & Banners

XMarkAnnouncementBar

Dismissible top announcement banner.

<XMarkAnnouncementBar
  message="New feature available!"
  link-text="Learn more"
  link-url="/features"
  variant="primary"
  :dismissible="true"
  @dismiss="handleDismiss"
/>
Prop Type Default Description
message String required Announcement text
linkText String '' Optional link text
linkUrl String '' Optional link URL
variant String 'primary' primary, neutral, success, warning, error
dismissible Boolean true Show dismiss button
XMarkCookieBanner

Cookie consent banner.

<XMarkCookieBanner
  message="We use cookies to improve your experience."
  accept-text="Accept All"
  decline-text="Decline"
  :show-preferences="true"
  @accept="handleAccept"
  @decline="handleDecline"
  @preferences="handlePreferences"
/>
XMarkCookieToast

Cookie toast notification.

<XMarkCookieToast
  message="We use cookies"
  @accept="handleAccept"
/>
XMarkPrivacyCookieConsent

Consent-aware cookie banner + preferences modal that auto-fires tracking scripts. Drop your GTM/GA4/Clarity IDs into app.config.ts, drop <XMarkPrivacyCookieConsent /> into your layout, and the component handles banner display, consent storage, and dynamic script injection.

<!-- app.vue -->
<template>
  <div>
    <NuxtPage />
    <XMarkPrivacyCookieConsent
      policy-url="/cookies"
      privacy-url="/privacy"
    />
  </div>
</template>
// app.config.ts
export default defineAppConfig({
  xMarketing: {
    tracking: {
      gtmId: 'GTM-XXXXXXX',
      ga4Id: 'G-XXXXXXXX',
      clarityId: 'abc123def4',
      // Optional escape hatch for anything else (Meta Pixel, Hotjar, etc.)
      scripts: [
        {
          id: 'meta-pixel',
          src: 'https://connect.facebook.net/en_US/fbevents.js',
          category: 'marketing',
          attrs: { async: '' },
        },
      ],
      autoInject: true, // default
    },
  },
})

Scripts only fire after the visitor grants consent for the matching category (analytics or marketing). On revisit, the client plugin auto-loads stored scripts immediately — no flash of banner.

Prop Type Default Description
title String 'We use cookies' Banner heading
message String (see source) Banner body text
acceptLabel String 'Accept all' Accept button text
rejectLabel String 'Reject all' Reject button text
saveLabel String 'Save preferences' Save button text (modal)
policyLabel String 'Read our policy' Policy link text
policyUrl String — Cookie policy URL
privacyUrl String — Privacy policy URL
prefsTitle String 'Cookie preferences' Modal title
prefsDescription String (see source) Modal description
showCustomize Boolean true Show the Customize button
categories Category[] (4 standard) Categories shown in the modal
storageKey String 'xMarketing.consent' localStorage key
forceShow Boolean false Force the banner open (e.g. from a "Manage cookies" link)
Emit Payload When
@accept Record<CategoryId, boolean> Visitor accepted all
@reject Record<CategoryId, boolean> Visitor rejected all
@save Record<CategoryId, boolean> Visitor saved preferences

Underlying composable — useConsentTracking() is auto-imported. Use it directly if you need to programmatically grant consent or read state:

const consent = useConsentTracking()
consent.acceptAll()       // grant every category
consent.rejectAll()       // grant only necessary
consent.hasConsent('analytics')
consent.state.value       // reactive { necessary, analytics, marketing, preferences }
XMarkGDPR

GDPR cookie preference modal.

<XMarkGDPR
  v-model="showGDPR"
  :categories="[
    { id: 'necessary', name: 'Necessary', description: 'Required for the site to work.', required: true },
    { id: 'analytics', name: 'Analytics', description: 'Help us improve.', default: false },
  ]"
  @save="handleSavePreferences"
/>
XMarkSocialProofToast

Social proof notification toasts.

<XMarkSocialProofToast
  :notifications="[
    { name: 'John', location: 'New York', action: 'signed up', time: '2 minutes ago' },
  ]"
  :interval="5000"
  position="bottom-left"
/>

Utilities

XMarkBackToTop

Scroll to top button.

<XMarkBackToTop :show-after="300" :smooth="true" />
XMarkPopupChat

Chat widget trigger.

<XMarkPopupChat
  provider="intercom"
  :config="{ app_id: 'your-app-id' }"
/>

Affiliate & Review Components

Removed in favour of @xenterprises/nuxt-x-affiliate.

XMarkAffiliateDisclosure, XMarkAffiliateProductCard, XMarkAffiliateProductGrid, XMarkAffiliateProductDetail, and XMarkAffiliateComparisonTable duplicated components the affiliate layer already ships — without its per-merchant tagging (xAffiliateContent.merchants), impression tracking, or Product/Offer structured data. Use <XAFDisclosure>, <XAFProductCard>, <XAFRelatedProducts>, <XAFBuyButton>, and <XAFComparisonTable> instead.

Configuration

Configure the layer in your app.config.js:

export default defineAppConfig({
  xMarketing: {
    name: "X Enterprises",
    config: {
      markerProjectId: "your-marker-project-id", // Optional: Marker.io integration
    },
  },
});

Testing

Unit Tests

Run unit tests with Vitest:

npm run test:unit

E2E Tests

Run end-to-end tests with Playwright:

npm run test:e2e

Composables

Composable Description
useScrollReveal(options?) Intersection Observer scroll animations. Auto-adds is-visible class to [data-reveal], .xFadeUp, .xFadeIn, .xFadeLeft, .xFadeRight, .xScale, .xFadeUp-stagger elements.
useStaggerReveal(selector, delay?) Adds incremental transition-delay to [data-reveal] children inside a container.
useParallax(options?) Parallax scroll effect for .xParallax[data-parallax-speed] elements. Uses requestAnimationFrame for performance.
useElementParallax(speed?) Individual element parallax via template ref. Returns { elementRef }.
useXBlog() Nuxt Content blog helpers (getPosts, getPostByPath, getSurround, normalizeBlogPost). Expects a blog collection and markdown under content/blog/.

All composables are SSR-safe — they guard lifecycle hooks with getCurrentInstance() and import.meta.client checks.


Environment Variables

Name Required Description
Marker.io Project ID No Set via appConfig.xMarketing.config.markerProjectId (not env var)
Newsletter Org ID No Set via appConfig.xMarketing.config.emailMarketingNewsletters.organizationId

The layer itself has no required environment variables. Blog content is file-based via Nuxt Content (not Builder.io). All site config is done via app.config.ts.


CSS Classes

Typography

Class Description
xText-display Display heading — clamp(3rem, 8vw, 6rem), weight 700, tight tracking
xText-headline Section headline — clamp(2rem, 5vw, 3.5rem), weight 600
xText-title Card/feature title — clamp(1.25rem, 3vw, 1.75rem), weight 600
xText-body Body text — 1.125rem, line-height 1.7
xText-small Captions/labels — 0.875rem
xText-eyebrow Uppercase label — 0.75rem, 0.1em tracking
xText-balance Applies text-wrap: balance
xText-gradient Gradient text using primary color

Scroll Animations

Class Description
xFadeUp Fade in + slide up (24px) on scroll
xFadeIn Simple fade in on scroll
xFadeLeft Fade in from left (-24px) on scroll
xFadeRight Fade in from right (24px) on scroll
xScale Scale in (0.95 → 1) on scroll
xFadeUp-stagger Stagger children with 100ms delay increments (up to 6 children)
[data-reveal] Legacy fade up (40px) on scroll

Hover Effects

Class Description
xHover-lift Lift up 4px + shadow on hover
xHover-grow Scale to 1.02 on hover
xHover-glow Primary color glow shadow on hover
xHover-glow-neutral Neutral glow shadow on hover
xHover-glow-subtle Subtle glow shadow on hover
xHover-zoom Zoom child <img> to 1.08 on hover

Glass & Glow

Class Description
xGlass Glassmorphism — 20px blur, white/70 bg, border, shadow
xGlass-subtle Light glassmorphism — 8px blur
xGlass-heavy Heavy glassmorphism — 40px blur
xGlow-divider Glowing horizontal divider line
xGlow-border Glowing gradient border
xGlow-text Text glow shadow

Overlays

Class Description
xOverlay-light 30% black overlay
xOverlay-heavy 60% black overlay
xOverlay-gradient Bottom-to-top gradient overlay
xOverlay-vignette Radial vignette overlay

Parallax

Class Description
xParallax JS-driven parallax (use with data-parallax-speed="0.3")
xParallax-bg CSS-only parallax (background-attachment: fixed)

All animations respect prefers-reduced-motion: reduce.


How It Works

The layer provides a complete marketing website toolkit built on Nuxt UI v4:

  1. Component Registration: All components in app/components/X/Mark/ are auto-imported by Nuxt with the XMark prefix (e.g., X/Mark/Hero/index.vue → <XMarkHero>). Branded X Enterprises components live under X/X/ with the XX prefix.

  2. Design System: app/assets/css/x-marketing.css defines CSS custom properties for typography scale, spacing, colors, shadows, and motion. It uses Tailwind CSS v4 with @theme static for custom color palettes ("brand" and "deep"). Dark mode overrides use .dark selector.

  3. Animations: A client-side plugin (marketing.client.ts) auto-initializes useScrollReveal() and useParallax() globally on mount. Components that need scroll animations can also call useScrollReveal() directly.

  4. Configuration: app.config.ts provides the xMarketing namespace with header/footer/blog configuration and Nuxt UI theme overrides. Consumer apps merge their own app.config.ts to customize.

  5. Type System: app/types/marketing.d.ts exports interfaces for all data structures (BlogPost, Feature, PricingPlan, Testimonial, etc.) used across components.


Layer Architecture

Path Purpose
nuxt.config.ts Registers @nuxt/ui + @nuxt/content, loads CSS, enables SSR
content.config.ts Default Nuxt Content blog collection schema
app/app.config.ts Default xMarketing config + Nuxt UI theme overrides + type augmentation
app/app.vue Default app shell with navbar, newsletter, footer (override in consumer app)
app/assets/css/x-marketing.css Full design system: colors, typography, animations, effects
app/components/X/Mark/ Generic marketing components (auto-imported as XMark*)
app/components/X/X/ X Enterprises branded components (auto-imported as XX*)
app/components/X/Footer/ Legacy footer components
app/components/X/Header/ Legacy header components
app/composables/ Composables: useScrollReveal, useParallax, useXBlog
app/plugins/marketing.client.ts Client plugin: auto-initializes scroll/parallax globally
app/types/marketing.d.ts TypeScript interfaces for all data structures
app/pages/blog/ Default blog index + slug detail (Nuxt Content, not Builder.io)

Blog (Nuxt Content)

Breaking (Builder.io removed): default /blog pages no longer call the Builder CDN. Posts come from markdown in the consumer app.

  1. Peer-install @nuxt/content and better-sqlite3 (already required by Content v3).
  2. Ensure the layer is extended so content.config.ts defines the blog collection (or copy/adapt it).
  3. Add posts under content/blog/*.md:
---
title: Getting Started
description: First post on the marketing site.
date: 2025-01-15
author: Tim
image: /blog/cover.jpg
category: Tutorial
tags: [nuxt, marketing]
published: true
readingTime: 5
---

## Hello

Markdown body rendered via `ContentRenderer`.
  1. useXBlog().getPosts() / getPostByPath() feed XMarkBlogList and XMarkBlogDetail.

Overriding in Consumer Apps

  • nuxt.config.ts: Consumer config merges with layer config. Add modules, runtime config, etc.
  • app.config.ts: Deep-merges with layer defaults. Set xMarketing.header, xMarketing.footer, etc.
  • app.vue: Override entirely by creating your own app.vue in the consumer app.
  • Pages: Consumer pages take precedence. Override /blog by creating pages/blog/index.vue.
  • Content: Own the markdown under content/blog/; do not put secrets in frontmatter.

License

UNLICENSED - Proprietary to X Enterprises.

Related Packages

@xenterprises/nuxt-x-app

A comprehensive Nuxt layer providing production-ready admin dashboard components...

2,705
@xenterprises/nuxt-x-cards

A premium card component library for Nuxt 4 with cinematic image filters, warm s...

2,272
@xenterprises/nuxt-x-auth-nile

Nile Auth (thenile.dev) authentication layer for Nuxt

539

Version History

Version Released License
1.15.5 Custom
1.15.4 Custom
1.15.3 Custom
1.15.2 Custom
1.15.1 Custom