@xenterprises/nuxt-x-marketing 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.claude/settings.local.json +23 -0
  2. package/.playground/app.vue +12 -6
  3. package/.playground/package-lock.json +6 -0
  4. package/.playground/pages/index.vue +2 -2
  5. package/.playground/pages/layout/x-legal.vue +12 -12
  6. package/LICENSE +60 -0
  7. package/README.md +210 -64
  8. package/app/app.config.ts +2 -72
  9. package/app/components/X/Footer/index.vue +3 -4
  10. package/app/components/X/Mark/Affiliate/ComparisonTable.vue +382 -0
  11. package/app/components/X/Mark/Affiliate/Disclosure.vue +138 -0
  12. package/app/components/X/Mark/Affiliate/ProductCard.vue +431 -0
  13. package/app/components/X/Mark/Affiliate/ProductDetail.vue +410 -0
  14. package/app/components/X/Mark/Affiliate/ProductGrid.vue +101 -0
  15. package/app/components/X/Mark/Blog/Author.vue +26 -20
  16. package/app/components/X/Mark/Blog/Card.vue +28 -15
  17. package/app/components/X/Mark/Blog/Detail.vue +177 -169
  18. package/app/components/X/Mark/Blog/List.vue +17 -16
  19. package/app/components/X/Mark/CTA/index.vue +74 -70
  20. package/app/components/X/Mark/Card/Promo.vue +149 -139
  21. package/app/components/X/Mark/Directory/CategoryHero.vue +124 -0
  22. package/app/components/X/Mark/Directory/ListingCard.vue +336 -0
  23. package/app/components/X/Mark/Directory/ListingDetail.vue +306 -0
  24. package/app/components/X/Mark/Directory/ListingGrid.vue +190 -0
  25. package/app/components/X/Mark/Directory/SubmitCTA.vue +201 -0
  26. package/app/components/X/Mark/FAQ/index.vue +191 -0
  27. package/app/components/X/Mark/Features/index.vue +87 -35
  28. package/app/components/X/Mark/Hero/index.vue +41 -38
  29. package/app/components/X/Mark/Layout/AnnouncementBar.vue +20 -28
  30. package/app/components/X/Mark/Modal/Chat.vue +124 -124
  31. package/app/components/X/Mark/Modal/Video.vue +46 -36
  32. package/app/components/X/Mark/Pricing/Comparison.vue +76 -21
  33. package/app/components/X/Mark/Pricing/Plans.vue +75 -25
  34. package/app/components/X/Mark/SocialProof/Testimonials.vue +89 -21
  35. package/app/components/X/Mark/SocialProof/Toast.vue +146 -138
  36. package/app/components/X/X/Footer/index.vue +101 -0
  37. package/app/components/X/X/Header/Nav/index.vue +62 -0
  38. package/app/components/X/X/Header/index.vue +72 -0
  39. package/app/components/X/X/Legal/index.vue +94 -0
  40. package/app/composables/useParallax.ts +32 -19
  41. package/app/composables/useScrollReveal.ts +20 -13
  42. package/app/pages/index.vue +230 -28
  43. package/componentList.json +1856 -238
  44. package/package.json +2 -1
  45. package/screenshots/playground-home.png +0 -0
@@ -0,0 +1,23 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(curl:*)",
5
+ "Bash(npm run dev:*)",
6
+ "Bash(cat:*)",
7
+ "Bash(npm install:*)",
8
+ "Bash(find:*)",
9
+ "Bash(ls:*)",
10
+ "Skill(frontend-design)",
11
+ "Bash(git log:*)",
12
+ "Bash(test:*)",
13
+ "Bash(timeout 300 npx playwright test:*)",
14
+ "Bash(npx playwright test:*)",
15
+ "Bash(npx playwright install:*)",
16
+ "Bash({} ;)",
17
+ "mcp__plugin_context7_context7__resolve-library-id",
18
+ "mcp__plugin_context7_context7__query-docs",
19
+ "Bash(git reset:*)",
20
+ "Bash(python3:*)"
21
+ ]
22
+ }
23
+ }
@@ -1,4 +1,5 @@
1
1
  <template>
2
+ <UApp>
2
3
  <div class="min-h-screen bg-neutral-50 dark:bg-neutral-950">
3
4
  <!-- Sidebar Navigation -->
4
5
  <aside class="fixed top-0 left-0 w-64 h-screen bg-white dark:bg-neutral-900 border-r border-neutral-200 dark:border-neutral-800 overflow-y-auto z-50">
@@ -16,8 +17,16 @@
16
17
  @click="toggleDarkMode"
17
18
  class="flex items-center gap-2 px-3 py-2 w-full rounded-lg text-sm text-neutral-600 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors"
18
19
  >
19
- <UIcon :name="isDark ? 'i-lucide-sun' : 'i-lucide-moon'" class="w-4 h-4" />
20
- <span>{{ isDark ? 'Light Mode' : 'Dark Mode' }}</span>
20
+ <ClientOnly>
21
+ <UIcon :name="isDark ? 'i-lucide-sun' : 'i-lucide-moon'" class="w-4 h-4" />
22
+ <template #fallback>
23
+ <UIcon name="i-lucide-moon" class="w-4 h-4" />
24
+ </template>
25
+ </ClientOnly>
26
+ <ClientOnly>
27
+ <span>{{ isDark ? 'Light Mode' : 'Dark Mode' }}</span>
28
+ <template #fallback><span>Dark Mode</span></template>
29
+ </ClientOnly>
21
30
  </button>
22
31
  </div>
23
32
 
@@ -189,11 +198,8 @@
189
198
  <main class="ml-64">
190
199
  <NuxtPage />
191
200
  </main>
192
-
193
- <!-- Nuxt UI Providers for modals and toasts -->
194
- <UModals />
195
- <UToaster />
196
201
  </div>
202
+ </UApp>
197
203
  </template>
198
204
 
199
205
  <script setup>
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": ".playground",
3
+ "lockfileVersion": 3,
4
+ "requires": true,
5
+ "packages": {}
6
+ }
@@ -129,8 +129,8 @@
129
129
  </main>
130
130
 
131
131
  <!-- Footer -->
132
- <XFooter />
133
- <XFooterXLegal />
132
+ <XXFooter />
133
+ <XXLegal />
134
134
  </div>
135
135
  </template>
136
136
 
@@ -17,7 +17,7 @@
17
17
  Without any props, displays X Enterprises logo, copyright, and legal links.
18
18
  </p>
19
19
  <div class="border border-neutral-200 dark:border-neutral-700 rounded-lg overflow-hidden">
20
- <XFooterXLegal />
20
+ <XXLegal />
21
21
  </div>
22
22
  </section>
23
23
 
@@ -25,7 +25,7 @@
25
25
  <section>
26
26
  <h2 class="text-lg font-semibold mb-4">Custom Copyright</h2>
27
27
  <div class="border border-neutral-200 dark:border-neutral-700 rounded-lg overflow-hidden">
28
- <XFooterXLegal
28
+ <XXLegal
29
29
  copyright="© 2024 Acme Corporation. All rights reserved."
30
30
  />
31
31
  </div>
@@ -35,7 +35,7 @@
35
35
  <section>
36
36
  <h2 class="text-lg font-semibold mb-4">Custom Links</h2>
37
37
  <div class="border border-neutral-200 dark:border-neutral-700 rounded-lg overflow-hidden">
38
- <XFooterXLegal
38
+ <XXLegal
39
39
  :links="customLinks"
40
40
  />
41
41
  </div>
@@ -45,7 +45,7 @@
45
45
  <section>
46
46
  <h2 class="text-lg font-semibold mb-4">Custom Logo</h2>
47
47
  <div class="border border-neutral-200 dark:border-neutral-700 rounded-lg overflow-hidden">
48
- <XFooterXLegal
48
+ <XXLegal
49
49
  :logo="{ src: 'https://cdn.x.enterprises/logo-x.png', alt: 'Custom Logo', href: '/' }"
50
50
  copyright="© 2024 Custom Company"
51
51
  />
@@ -56,7 +56,7 @@
56
56
  <section>
57
57
  <h2 class="text-lg font-semibold mb-4">No Logo</h2>
58
58
  <div class="border border-neutral-200 dark:border-neutral-700 rounded-lg overflow-hidden">
59
- <XFooterXLegal
59
+ <XXLegal
60
60
  :logo="false"
61
61
  copyright="© 2024 Simple Company. All rights reserved."
62
62
  />
@@ -67,7 +67,7 @@
67
67
  <section>
68
68
  <h2 class="text-lg font-semibold mb-4">Fully Customized</h2>
69
69
  <div class="border border-neutral-200 dark:border-neutral-700 rounded-lg overflow-hidden">
70
- <XFooterXLegal
70
+ <XXLegal
71
71
  :logo="{ src: 'https://cdn.x.enterprises/logo-x.png', alt: 'Acme Inc', href: 'https://example.com' }"
72
72
  copyright="© 2020-2024 Acme Inc. Built with love."
73
73
  :links="fullCustomLinks"
@@ -163,15 +163,15 @@ const fullCustomLinks = [
163
163
  ]
164
164
 
165
165
  const codeExample = `<!-- Default (X Enterprises branding) -->
166
- <XFooterXLegal />
166
+ <XXLegal />
167
167
 
168
168
  <!-- Custom copyright only -->
169
- <XFooterXLegal
169
+ <XXLegal
170
170
  copyright="© 2024 Your Company. All rights reserved."
171
171
  />
172
172
 
173
173
  <!-- Custom links -->
174
- <XFooterXLegal
174
+ <XXLegal
175
175
  :links="[
176
176
  { label: 'Privacy Policy', href: '/privacy' },
177
177
  { label: 'Terms of Service', href: '/terms' },
@@ -180,15 +180,15 @@ const codeExample = `<!-- Default (X Enterprises branding) -->
180
180
  />
181
181
 
182
182
  <!-- Custom logo -->
183
- <XFooterXLegal
183
+ <XXLegal
184
184
  :logo="{ src: '/logo.png', alt: 'Company', href: '/' }"
185
185
  />
186
186
 
187
187
  <!-- Hide logo -->
188
- <XFooterXLegal :logo="false" />
188
+ <XXLegal :logo="false" />
189
189
 
190
190
  <!-- Fully customized -->
191
- <XFooterXLegal
191
+ <XXLegal
192
192
  :logo="{ src: '/logo.png', alt: 'Company', href: '/' }"
193
193
  copyright="© 2024 Company Inc. All rights reserved."
194
194
  :links="[
package/LICENSE ADDED
@@ -0,0 +1,60 @@
1
+ PROPRIETARY SOFTWARE LICENSE
2
+
3
+ Copyright (c) 2024-2026 X Enterprises LLC. All Rights Reserved.
4
+
5
+ This software and associated documentation files (the "Software") are the
6
+ exclusive property of X Enterprises LLC, a Washington limited liability
7
+ company.
8
+
9
+ TERMS AND CONDITIONS
10
+
11
+ 1. OWNERSHIP
12
+ All rights, title, and interest in and to the Software, including all
13
+ intellectual property rights, are and shall remain the exclusive property
14
+ of X Enterprises LLC.
15
+
16
+ 2. RESTRICTIONS
17
+ Without the prior written consent of X Enterprises LLC, you may not:
18
+ - Copy, modify, or distribute the Software
19
+ - Reverse engineer, decompile, or disassemble the Software
20
+ - Sublicense, sell, lease, or otherwise transfer the Software
21
+ - Remove or alter any proprietary notices or labels
22
+
23
+ 3. AUTHORIZED USE
24
+ Use of this Software is limited to authorized employees, contractors, and
25
+ agents of X Enterprises LLC, solely for purposes approved by X Enterprises
26
+ LLC.
27
+
28
+ 4. NO WARRANTY
29
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
32
+ X ENTERPRISES LLC BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY,
33
+ WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF,
34
+ OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
+ SOFTWARE.
36
+
37
+ 5. LIMITATION OF LIABILITY
38
+ IN NO EVENT SHALL X ENTERPRISES LLC BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
39
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
41
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
43
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
44
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
+
46
+ 6. GOVERNING LAW
47
+ This license shall be governed by and construed in accordance with the laws
48
+ of the State of Washington, United States, without regard to its conflict
49
+ of law provisions.
50
+
51
+ 7. TERMINATION
52
+ This license is effective until terminated. X Enterprises LLC may terminate
53
+ this license at any time without notice. Upon termination, you must destroy
54
+ all copies of the Software in your possession.
55
+
56
+ For licensing inquiries, contact: legal@x.enterprises
57
+
58
+ ---
59
+ X Enterprises LLC
60
+ Bothell, Washington, United States
package/README.md CHANGED
@@ -1,16 +1,18 @@
1
1
  # @xenterprises/nuxt-x-marketing
2
2
 
3
- A comprehensive Nuxt layer for building marketing websites with 33+ pre-built components. Features dark mode support, responsive design, accessibility, and seamless integration with Nuxt UI.
3
+ 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.
4
4
 
5
5
  ## Features
6
6
 
7
- - **33+ Marketing Components** - Hero, Features, Pricing, Testimonials, Blog, and more
7
+ - **38+ Marketing Components** - Hero, Features, Pricing, Testimonials, Blog, Affiliate/Review, and more
8
+ - **Zero Required Props** - Every component works out of the box with sensible defaults
8
9
  - **Dark Mode Support** - All components support light and dark themes
9
10
  - **Responsive Design** - Mobile-first approach with tablet and desktop breakpoints
10
11
  - **Accessible** - WCAG 2.0 AA compliant with proper ARIA attributes
11
12
  - **Customizable** - Props-based configuration with slot overrides
12
- - **Nuxt UI Integration** - Built on top of Nuxt UI v4 components
13
+ - **Nuxt UI v4 Integration** - Built on top of Nuxt UI v4 components
13
14
  - **Animations** - Scroll-triggered fade-in animations and parallax effects
15
+ - **Two Footer Modes** - Generic white-label (`XMarkLayoutFooter`) and X Enterprises branded (`XFooter`)
14
16
 
15
17
  ## Installation
16
18
 
@@ -111,99 +113,60 @@ const handleNewsletterSubmit = (email) => {
111
113
 
112
114
  ### Example Landing Page
113
115
 
116
+ All components work with zero required props — just drop them in and customize as needed:
117
+
114
118
  ```vue
115
119
  <template>
116
120
  <div>
117
- <!-- Hero -->
121
+ <!-- Hero — works with zero props, or fully customized -->
118
122
  <XMarkHero
119
- image-src="https://images.unsplash.com/photo-1551434678-e076c223a692"
123
+ :img="{ src: 'https://images.unsplash.com/photo-1551434678-e076c223a692', alt: 'Hero' }"
120
124
  eyebrow="Welcome to the future"
121
125
  title="Build something amazing today"
122
126
  subtitle="The modern platform for teams who want to ship faster."
123
127
  align="left"
124
128
  overlay="gradient"
125
- >
126
- <template #actions>
127
- <UButton size="xl" color="white">Get Started Free</UButton>
128
- <UButton size="xl" variant="outline" color="white">Watch Demo</UButton>
129
- </template>
130
- </XMarkHero>
129
+ :buttons="[
130
+ { label: 'Get Started Free', color: 'primary' },
131
+ { label: 'Watch Demo', variant: 'outline' }
132
+ ]"
133
+ />
131
134
 
132
- <!-- Features -->
135
+ <!-- Features — works with zero props, or pass your own -->
133
136
  <XMarkSection id="features" bg="default" padding="xl">
134
137
  <header class="text-center max-w-3xl mx-auto mb-16">
135
138
  <h2 class="xText-headline">Everything you need to succeed</h2>
136
- <p class="mt-4 text-lg text-neutral-600">
137
- Powerful tools designed to help you build, launch, and grow.
138
- </p>
139
139
  </header>
140
140
  <XMarkFeatures :features="features" layout="grid" :columns="3" />
141
141
  </XMarkSection>
142
142
 
143
143
  <!-- Testimonials -->
144
144
  <XMarkSection bg="subtle" padding="xl">
145
- <header class="text-center max-w-3xl mx-auto mb-16">
146
- <h2 class="xText-headline">Loved by teams worldwide</h2>
147
- </header>
148
145
  <XMarkTestimonials :testimonials="testimonials" layout="grid" />
149
146
  </XMarkSection>
150
147
 
151
148
  <!-- Pricing -->
152
149
  <XMarkSection bg="default" padding="xl">
153
- <header class="text-center max-w-3xl mx-auto mb-16">
154
- <h2 class="xText-headline">Simple, transparent pricing</h2>
155
- </header>
156
- <XMarkPricing :plans="pricingPlans" />
150
+ <XMarkPricingPlans :plans="pricingPlans" />
157
151
  </XMarkSection>
158
152
  </div>
159
153
  </template>
160
154
 
161
155
  <script setup>
162
156
  const features = [
163
- {
164
- icon: "i-lucide-zap",
165
- title: "Lightning Fast",
166
- description: "Built for speed with optimized performance.",
167
- },
168
- {
169
- icon: "i-lucide-shield-check",
170
- title: "Secure by Default",
171
- description: "Enterprise-grade security with SOC 2 compliance.",
172
- },
173
- {
174
- icon: "i-lucide-users",
175
- title: "Team Collaboration",
176
- description: "Real-time collaboration tools for modern teams.",
177
- },
178
- ];
157
+ { icon: 'i-lucide-zap', title: 'Lightning Fast', description: 'Built for speed.' },
158
+ { icon: 'i-lucide-shield-check', title: 'Secure by Default', description: 'Enterprise-grade security.' },
159
+ { icon: 'i-lucide-users', title: 'Team Collaboration', description: 'Real-time collaboration tools.' },
160
+ ]
179
161
 
180
162
  const testimonials = [
181
- {
182
- quote: "This platform transformed how our team works.",
183
- name: "Sarah Chen",
184
- title: "CTO",
185
- company: "TechStart",
186
- avatar: "https://randomuser.me/api/portraits/women/44.jpg",
187
- },
188
- ];
163
+ { quote: 'This platform transformed how our team works.', name: 'Sarah Chen', title: 'CTO', company: 'TechStart', rating: 5 },
164
+ ]
189
165
 
190
166
  const pricingPlans = [
191
- {
192
- name: "Starter",
193
- price: "$19",
194
- period: "month",
195
- features: ["Up to 5 team members", "Basic analytics", "Email support"],
196
- cta: "Start Free Trial",
197
- },
198
- {
199
- name: "Pro",
200
- price: "$49",
201
- period: "month",
202
- features: ["Up to 25 team members", "Advanced analytics", "Priority support"],
203
- cta: "Start Free Trial",
204
- popular: true,
205
- },
206
- ];
167
+ { name: 'Starter', price: '$19', period: '/month', features: ['5 team members', 'Basic analytics'], button: { label: 'Start Free Trial' } },
168
+ { name: 'Pro', price: '$49', period: '/month', features: ['25 team members', 'Advanced analytics'], button: { label: 'Start Free Trial' }, popular: true },
169
+ ]
207
170
  </script>
208
171
  ```
209
172
 
@@ -236,8 +199,8 @@ Fixed navigation header with transparent-to-solid scroll transition.
236
199
  | Prop | Type | Default | Description |
237
200
  |------|------|---------|-------------|
238
201
  | `links` | `Array` | `[]` | Navigation links `{ label, to }` |
239
- | `logoLight` | `String` | required | Logo for transparent state |
240
- | `logoDark` | `String` | required | Logo for solid state |
202
+ | `logoLight` | `String` | `''` | Logo for transparent/dark state |
203
+ | `logoDark` | `String` | `''` | Logo for solid/light state |
241
204
  | `logoAlt` | `String` | `'Logo'` | Logo alt text |
242
205
  | `transparent` | `Boolean` | `true` | Start transparent over hero |
243
206
  | `scrollThreshold` | `Number` | `100` | Pixels before transition |
@@ -805,6 +768,189 @@ Chat widget trigger.
805
768
 
806
769
  ---
807
770
 
771
+ ### Affiliate & Review Components
772
+
773
+ For affiliate marketing, product review sites, and "best X" roundup posts.
774
+
775
+ #### XMarkAffiliateDisclosure
776
+
777
+ FTC/Amazon-required affiliate disclosure banner. Three variants for different placements.
778
+
779
+ ```vue
780
+ <!-- Subtle bar (default) -->
781
+ <XMarkAffiliateDisclosure />
782
+
783
+ <!-- Full-width banner at top of page -->
784
+ <XMarkAffiliateDisclosure variant="banner" :dismissible="true" />
785
+
786
+ <!-- Inline inside blog post prose -->
787
+ <XMarkAffiliateDisclosure variant="inline" />
788
+ ```
789
+
790
+ | Prop | Type | Default | Description |
791
+ |------|------|---------|-------------|
792
+ | `text` | `String` | Amazon associate disclosure | Disclosure text |
793
+ | `variant` | `String` | `'subtle'` | `subtle`, `banner`, `inline` |
794
+ | `icon` | `String` | `'i-lucide-info'` | Icon name |
795
+ | `dismissible` | `Boolean` | `false` | Show dismiss button |
796
+ | `storageKey` | `String` | `'affiliate-disclosure-dismissed'` | localStorage key |
797
+
798
+ #### XMarkAffiliateProductCard
799
+
800
+ Product card with affiliate buy button, star rating, price, pros/cons. Three layout variants.
801
+
802
+ ```vue
803
+ <XMarkAffiliateProductCard
804
+ :product="{
805
+ name: 'Sony WH-1000XM5',
806
+ image: '/products/sony-wh1000xm5.jpg',
807
+ price: '$279.99',
808
+ originalPrice: '$349.99',
809
+ rating: 4.8,
810
+ reviewCount: 12400,
811
+ pros: ['Best-in-class ANC', '30hr battery', 'Foldable design'],
812
+ cons: ['No IP rating', 'Expensive'],
813
+ affiliateUrl: 'https://amazon.com/dp/B09XS7JWHH',
814
+ affiliateTag: 'mysite-20',
815
+ badge: '#1 Pick',
816
+ }"
817
+ layout="card"
818
+ button-label="Check Price on Amazon"
819
+ />
820
+ ```
821
+
822
+ | Prop | Type | Default | Description |
823
+ |------|------|---------|-------------|
824
+ | `product` | `Object` | sample product | Product data `{ name, image?, price?, originalPrice?, rating?, reviewCount?, pros?, cons?, affiliateUrl?, affiliateTag?, badge? }` |
825
+ | `layout` | `String` | `'card'` | `card` (vertical), `row` (horizontal), `compact` (one-line) |
826
+ | `showPros` | `Boolean` | `true` | Show pros list |
827
+ | `showCons` | `Boolean` | `false` | Show cons list |
828
+ | `showRating` | `Boolean` | `true` | Show star rating |
829
+ | `showPrice` | `Boolean` | `true` | Show price |
830
+ | `buttonLabel` | `String` | `'Check Price on Amazon'` | CTA button text |
831
+ | `buttonIcon` | `String` | `'i-lucide-external-link'` | CTA button icon |
832
+ | `disclosure` | `String` | `''` | Small disclosure text below button |
833
+
834
+ #### XMarkAffiliateProductGrid
835
+
836
+ Grid of product cards for "best X" roundup posts. Automatically injects rank badges.
837
+
838
+ ```vue
839
+ <XMarkAffiliateProductGrid
840
+ :products="topHeadphones"
841
+ layout="grid"
842
+ :columns="3"
843
+ :show-ranking="true"
844
+ disclosure="This page contains affiliate links."
845
+ button-label="Check Price on Amazon"
846
+ />
847
+ ```
848
+
849
+ | Prop | Type | Default | Description |
850
+ |------|------|---------|-------------|
851
+ | `products` | `Array` | `[]` | Array of product objects |
852
+ | `layout` | `String` | `'grid'` | `grid` or `list` |
853
+ | `columns` | `Number` | `3` | Grid columns: `2` or `3` |
854
+ | `showRanking` | `Boolean` | `true` | Inject #1/#2/#3 badges on first 3 products |
855
+ | `disclosure` | `String` | `''` | Disclosure shown once at top |
856
+ | `buttonLabel` | `String` | `'Check Price on Amazon'` | CTA label for all cards |
857
+ | `cardLayout` | `String` | `'card'` | Card layout variant |
858
+
859
+ #### XMarkAffiliateProductDetail
860
+
861
+ Full product review page layout — image gallery, editorial score, pros/cons table, specs, sticky buy box.
862
+
863
+ ```vue
864
+ <XMarkAffiliateProductDetail
865
+ :product="{
866
+ name: 'Sony WH-1000XM5 Review',
867
+ images: ['/img/sony-1.jpg', '/img/sony-2.jpg'],
868
+ price: '$279.99',
869
+ originalPrice: '$349.99',
870
+ rating: 4.8,
871
+ reviewCount: 12400,
872
+ pros: ['Best-in-class ANC', '30hr battery'],
873
+ cons: ['No IP rating', 'Expensive'],
874
+ specs: { 'Driver Size': '30mm', 'Battery': '30 hours', 'Weight': '250g' },
875
+ description: 'The WH-1000XM5 sets the bar for noise-cancelling headphones.',
876
+ verdict: 'The best ANC headphones money can buy in 2024.',
877
+ affiliateUrl: 'https://amazon.com/dp/B09XS7JWHH',
878
+ affiliateTag: 'mysite-20',
879
+ }"
880
+ :score="9.2"
881
+ :has-buy-box="true"
882
+ :has-specs="true"
883
+ :has-pros-cons-table="true"
884
+ disclosure="This page contains affiliate links."
885
+ >
886
+ <template #after-verdict>
887
+ <!-- Additional content after verdict -->
888
+ </template>
889
+ <template #sidebar>
890
+ <!-- Additional sidebar widgets -->
891
+ </template>
892
+ </XMarkAffiliateProductDetail>
893
+ ```
894
+
895
+ | Prop | Type | Default | Description |
896
+ |------|------|---------|-------------|
897
+ | `product` | `Object` | sample product | Full product data including `images[]`, `specs{}`, `verdict` |
898
+ | `score` | `Number` | `null` | Editorial score 0–10 (shown as circular badge) |
899
+ | `hasBuyBox` | `Boolean` | `true` | Show sticky buy box sidebar |
900
+ | `hasSpecs` | `Boolean` | `true` | Show specs table |
901
+ | `hasProsConsTable` | `Boolean` | `true` | Show pros/cons two-column table |
902
+ | `disclosure` | `String` | `''` | Affiliate disclosure text |
903
+
904
+ **Slots:** `buy-box`, `after-verdict`, `sidebar`
905
+
906
+ #### XMarkAffiliateComparisonTable
907
+
908
+ Side-by-side product comparison table for "X vs Y" posts. Highlights best values per row.
909
+
910
+ ```vue
911
+ <XMarkAffiliateComparisonTable
912
+ :products="[
913
+ {
914
+ name: 'Sony WH-1000XM5',
915
+ image: '/img/sony.jpg',
916
+ price: '$279.99',
917
+ affiliateUrl: 'https://amazon.com/dp/B09XS7JWHH',
918
+ affiliateTag: 'mysite-20',
919
+ specs: { price: '$279.99', rating: '4.8/5', battery: '30 hours', weight: '250g' },
920
+ },
921
+ {
922
+ name: 'Bose QC45',
923
+ image: '/img/bose.jpg',
924
+ price: '$249.99',
925
+ affiliateUrl: 'https://amazon.com/dp/B098FKXT8L',
926
+ affiliateTag: 'mysite-20',
927
+ specs: { price: '$249.99', rating: '4.6/5', battery: '24 hours', weight: '238g' },
928
+ },
929
+ ]"
930
+ :specs="[
931
+ { label: 'Price', key: 'price' },
932
+ { label: 'Rating', key: 'rating' },
933
+ { label: 'Battery Life', key: 'battery' },
934
+ { label: 'Weight', key: 'weight' },
935
+ ]"
936
+ :show-buy-buttons="true"
937
+ :highlight-best="true"
938
+ button-label="Buy on Amazon"
939
+ disclosure="This page contains affiliate links."
940
+ />
941
+ ```
942
+
943
+ | Prop | Type | Default | Description |
944
+ |------|------|---------|-------------|
945
+ | `products` | `Array` | 2 sample products | 2–4 products with `specs` object |
946
+ | `specs` | `Array` | price/rating/battery | `[{ label, key }]` spec rows |
947
+ | `showBuyButtons` | `Boolean` | `true` | Show buy buttons in last row |
948
+ | `highlightBest` | `Boolean` | `true` | Highlight best value per row (lowest price, highest rating) |
949
+ | `buttonLabel` | `String` | `'Buy on Amazon'` | Buy button label |
950
+ | `disclosure` | `String` | `''` | Disclosure shown above table |
951
+
952
+ ---
953
+
808
954
  ## Configuration
809
955
 
810
956
  Configure the layer in your `app.config.js`:
package/app/app.config.ts CHANGED
@@ -1,9 +1,6 @@
1
1
  export default defineAppConfig({
2
2
  ui: {
3
3
  primary: "brand",
4
- header: {
5
- container: "max-w-screen-2xl container mx-auto",
6
- },
7
4
  colors: {
8
5
  primary: "brand",
9
6
  secondary: "deep",
@@ -82,6 +79,8 @@ declare module "@nuxt/schema" {
82
79
  xMarketing?: {
83
80
  /** Project name */
84
81
  name?: string;
82
+ /** Project URL */
83
+ url?: string;
85
84
  config?: {
86
85
  markerProjectId?: string;
87
86
  emailMarketingNewsletters?: {
@@ -145,72 +144,3 @@ interface NavLink {
145
144
  children?: NavLink[];
146
145
  }
147
146
 
148
- declare module "@nuxt/schema" {
149
- interface AppConfigInput {
150
- xMarketing?: {
151
- /** Project name */
152
- name?: string;
153
- config?: {
154
- markerProjectId?: string;
155
- emailMarketingNewsletters?: {
156
- organizationId?: string;
157
- };
158
- };
159
- header?: {
160
- logo?: {
161
- src?: string;
162
- srcDark?: string;
163
- alt?: string;
164
- };
165
- nav?: {
166
- buttons?: {
167
- label: string;
168
- to: string;
169
- icon?: string;
170
- target?: string;
171
- variant?: string;
172
- square?: boolean;
173
- color?: string;
174
- }[];
175
- links?: NavLink[];
176
- };
177
- };
178
- footer?: {
179
- body?: string;
180
- bg?: {
181
- color?: string;
182
- img?: {
183
- src?: string;
184
- alt?: string;
185
- };
186
- };
187
- logo?: {
188
- src?: string;
189
- alt?: string;
190
- };
191
- socials?: {
192
- name: string;
193
- url: string;
194
- icon: string;
195
- }[];
196
- columns?: {
197
- headerLabel: string;
198
- links: {
199
- label: string;
200
- to: string;
201
- target?: string;
202
- }[];
203
- }[];
204
- };
205
- blog?: {
206
- active?: boolean;
207
- title?: string;
208
- description?: string;
209
- meta?: {
210
- title?: string;
211
- description?: string;
212
- };
213
- };
214
- };
215
- }
216
- }
@@ -47,13 +47,12 @@
47
47
  <UButton
48
48
  :to="social.url"
49
49
  :icon="social?.icon"
50
- :alt="social?.name"
51
- color="gray"
50
+ :aria-label="social?.name"
51
+ color="neutral"
52
52
  square
53
53
  target="_blank"
54
54
  variant="ghost"
55
- >
56
- </UButton>
55
+ />
57
56
  </div>
58
57
  <UColorModeButton />
59
58
  </div>