ultimate-jekyll-manager 0.0.215 → 0.0.217

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.
package/CLAUDE.md CHANGED
@@ -1015,6 +1015,95 @@ The `<html>` element has data attributes for JavaScript/CSS targeting:
1015
1015
 
1016
1016
  **Detection source:** `web-manager/src/modules/utilities.js`
1017
1017
 
1018
+ ## Alternatives Collection (SEO Competitor Comparison Pages)
1019
+
1020
+ UJ provides an `alternatives` collection for SEO landing pages that target users searching for competitors (e.g., "ExampleApp alternatives"). These pages are entirely frontmatter-driven and designed to convert visitors who are comparing products.
1021
+
1022
+ ### How It Works
1023
+
1024
+ 1. The `alternatives` collection is registered in `src/config/_config_default.yml` (UJM-controlled)
1025
+ 2. Each alternative is a markdown file in the consuming project's `_alternatives/` directory
1026
+ 3. The layout chain: `blueprint/alternatives/alternative` → `themes/classy/frontend/pages/alternatives/alternative`
1027
+ 4. An index page at `/alternatives` lists all alternatives automatically
1028
+ 5. **Shared content lives in the layout** — the theme layout provides default testimonials, stats, FAQs, CTA, and why_switch content so competitor pages only need competitor-specific data
1029
+ 6. The layout frontmatter uses `{{ page.resolved.alternative.competitor.name }}` to dynamically insert the competitor name into shared content (e.g., FAQ questions, CTA headlines)
1030
+
1031
+ ### Creating an Alternative Page
1032
+
1033
+ In the consuming project, create `src/_alternatives/competitor-name.md`. Only competitor-specific data is needed — shared sections are inherited from the layout:
1034
+
1035
+ ```yaml
1036
+ ---
1037
+ layout: blueprint/alternatives/alternative
1038
+ sitemap:
1039
+ include: true
1040
+
1041
+ alternative:
1042
+ competitor:
1043
+ name: "Competitor Name"
1044
+ description: "Brief description of the competitor (shown on /alternatives listing)"
1045
+ comparison:
1046
+ features:
1047
+ - name: "Feature Name"
1048
+ icon: "sparkles"
1049
+ ours:
1050
+ value: true # or string like "Unlimited"
1051
+ theirs:
1052
+ value: false # or string like "Limited"
1053
+ ---
1054
+ ```
1055
+
1056
+ That's it! The layout automatically generates:
1057
+ - Hero with "Brand vs Competitor Name" headline
1058
+ - Why Switch section with default differentiator items
1059
+ - Testimonials, Stats, FAQs, and CTA with shared content
1060
+ - All text dynamically references the competitor name via `{{ page.resolved.alternative.competitor.name }}`
1061
+
1062
+ **To override any inherited section**, define it in the competitor's frontmatter — `page.resolved` merge gives page-level values highest priority.
1063
+
1064
+ ### Available Sections
1065
+
1066
+ All sections are **optional** — omit or leave empty to hide. Sections with `(shared)` have default content in the layout:
1067
+
1068
+ | Section | Frontmatter Key | Description |
1069
+ |---------|----------------|-------------|
1070
+ | Hero | `alternative.hero` | Gradient animated hero with "Brand vs Competitor" headline (shared) |
1071
+ | Comparison | `alternative.comparison` | Side-by-side feature table — **must be defined per competitor** |
1072
+ | Why Switch | `alternative.why_switch` | Alternating image/text showcase blocks (shared) |
1073
+ | Video | `alternative.video` | YouTube embed (default: hidden, set `youtube_id` to show) |
1074
+ | Testimonials | `alternative.testimonials` | Reuses `testimonial-scroll.html` component (shared) |
1075
+ | Stats | `alternative.stats` | Social proof numbers with icons (shared) |
1076
+ | FAQs | `alternative.faqs` | Accordion with switching-related questions (shared) |
1077
+ | CTA | `alternative.cta` | Final conversion card with buttons (shared) |
1078
+
1079
+ ### Dynamic Competitor Name in Frontmatter
1080
+
1081
+ The layout uses `{{ page.resolved.alternative.competitor.name }}` in its frontmatter defaults to dynamically reference the competitor. This works because the template pipes these values through `| uj_liquify` to resolve Liquid expressions.
1082
+
1083
+ **Example:** The layout's default FAQ includes:
1084
+ ```yaml
1085
+ question: "Can I import my data from {{ page.resolved.alternative.competitor.name }}?"
1086
+ ```
1087
+ Which renders as "Can I import my data from ExampleApp?" for an ExampleApp competitor page.
1088
+
1089
+ ### Reference Implementation
1090
+
1091
+ - **Minimal competitor page:** `src/defaults/dist/_alternatives/example-competitor.md` — shows the minimum frontmatter needed (competitor name + comparison features)
1092
+ - **Layout with all defaults:** `src/defaults/dist/_layouts/themes/classy/frontend/pages/alternatives/alternative.html` — contains shared content for all sections
1093
+
1094
+ ### File Locations
1095
+
1096
+ | Purpose | Path |
1097
+ |---------|------|
1098
+ | Theme layout (alternative page) | `src/defaults/dist/_layouts/themes/classy/frontend/pages/alternatives/alternative.html` |
1099
+ | Theme layout (index/listing page) | `src/defaults/dist/_layouts/themes/classy/frontend/pages/alternatives/index.html` |
1100
+ | Blueprint (alternative) | `src/defaults/dist/_layouts/blueprint/alternatives/alternative.html` |
1101
+ | Blueprint (index) | `src/defaults/dist/_layouts/blueprint/alternatives/index.html` |
1102
+ | Default page (index) | `src/defaults/dist/pages/alternatives/index.md` |
1103
+ | Sample alternative | `src/defaults/dist/_alternatives/example-competitor.md` |
1104
+ | CSS | `src/assets/css/pages/alternatives/alternative/index.scss` |
1105
+ | JS | `src/assets/js/pages/alternatives/alternative/index.js` |
1106
+
1018
1107
  ## Audit Workflow
1019
1108
 
1020
1109
  When fixing issues identified by the audit task (`src/gulp/tasks/audit.js`):
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Alternatives Page JavaScript
3
+ */
4
+
5
+ // Libraries
6
+ let webManager = null;
7
+
8
+ // Module
9
+ export default (Manager) => {
10
+ return new Promise(async function (resolve) {
11
+ // Shortcuts
12
+ webManager = Manager.webManager;
13
+
14
+ // Initialize when DOM is ready
15
+ await webManager.dom().ready();
16
+
17
+ // Resolve after initialization
18
+ return resolve();
19
+ });
20
+ };
@@ -94,6 +94,9 @@ collections:
94
94
  updates:
95
95
  title: "Updates"
96
96
  output: true
97
+ alternatives:
98
+ title: "Alternatives"
99
+ output: true
97
100
 
98
101
  # Jekyll defaults
99
102
  defaults:
@@ -107,3 +110,8 @@ defaults:
107
110
  type: "updates"
108
111
  values:
109
112
  permalink: "/updates/:title"
113
+ - scope:
114
+ path: ""
115
+ type: "alternatives"
116
+ values:
117
+ permalink: "/alternatives/:title"
@@ -7,7 +7,7 @@ permalink: /.well-known/security.txt
7
7
  sitemap:
8
8
  include: false
9
9
  ---
10
- Contact: mailto:{{ site.brand.email }}
10
+ Contact: mailto:{{ site.brand.contact.email }}
11
11
  Contact: {{ site.url }}/contact
12
12
  Preferred-Languages: en
13
13
  Canonical: {{ site.url }}/.well-known/security.txt
@@ -0,0 +1,81 @@
1
+ ---
2
+ ### ALL PAGES ###
3
+ layout: blueprint/alternatives/alternative
4
+ sitemap:
5
+ include: true
6
+
7
+ ### PAGE CONFIG ###
8
+ draft: true # Hide from listing and sitemap (only visible in development)
9
+
10
+ ### ALTERNATIVE CONFIG ###
11
+ # Only competitor-specific data is needed here.
12
+ # Shared content (testimonials, stats, FAQs, CTA, why_switch) is inherited from the layout.
13
+ # Override any inherited section by defining it here.
14
+ alternative:
15
+ competitor:
16
+ name: "ExampleApp"
17
+ description: "ExampleApp is a basic project management tool with limited features and outdated design."
18
+
19
+ comparison:
20
+ features:
21
+ - name: "Free Plan"
22
+ icon: "gift"
23
+ ours:
24
+ value: true
25
+ theirs:
26
+ value: true
27
+ - name: "AI-Powered Features"
28
+ icon: "sparkles"
29
+ ours:
30
+ value: "Advanced"
31
+ theirs:
32
+ value: "Basic"
33
+ - name: "Real-time Collaboration"
34
+ icon: "users"
35
+ ours:
36
+ value: true
37
+ theirs:
38
+ value: false
39
+ - name: "API Access"
40
+ icon: "code"
41
+ ours:
42
+ value: "Full REST API"
43
+ theirs:
44
+ value: "Limited"
45
+ - name: "Custom Branding"
46
+ icon: "palette"
47
+ ours:
48
+ value: true
49
+ theirs:
50
+ value: false
51
+ - name: "Priority Support"
52
+ icon: "headset"
53
+ ours:
54
+ value: "24/7"
55
+ theirs:
56
+ value: "Business hours"
57
+ - name: "Integrations"
58
+ icon: "plug"
59
+ ours:
60
+ value: "200+"
61
+ theirs:
62
+ value: "50+"
63
+ - name: "Mobile App"
64
+ icon: "mobile"
65
+ ours:
66
+ value: true
67
+ theirs:
68
+ value: true
69
+ - name: "Export Formats"
70
+ icon: "download"
71
+ ours:
72
+ value: "PDF, CSV, JSON"
73
+ theirs:
74
+ value: "CSV only"
75
+ - name: "Uptime SLA"
76
+ icon: "shield-check"
77
+ ours:
78
+ value: "99.99%"
79
+ theirs:
80
+ value: "99.5%"
81
+ ---
@@ -0,0 +1,9 @@
1
+ ---
2
+ ### ALL PAGES ###
3
+ layout: themes/[ site.theme.id ]/frontend/pages/alternatives/alternative
4
+ asset_path: alternatives/alternative
5
+
6
+ ### REGULAR PAGES ###
7
+ ---
8
+
9
+ {{ content | uj_content_format }}
@@ -0,0 +1,12 @@
1
+ ---
2
+ ### ALL PAGES ###
3
+ layout: themes/[ site.theme.id ]/frontend/pages/alternatives/index
4
+
5
+ ### REGULAR PAGES ###
6
+ meta:
7
+ title: "Alternatives - {{ site.brand.name }}"
8
+ description: "Compare {{ site.brand.name }} to popular alternatives. See why thousands of users choose {{ site.brand.name }} over the competition."
9
+ breadcrumb: "Alternatives"
10
+ ---
11
+
12
+ {{ content | uj_content_format }}
@@ -0,0 +1,583 @@
1
+ ---
2
+ ### ALL PAGES ###
3
+ layout: themes/[ site.theme.id ]/frontend/core/base
4
+
5
+ #### THEME CONFIG ####
6
+ theme:
7
+ main:
8
+ class: "pt-0"
9
+
10
+ ### PAGE CONFIG ###
11
+ # Alternative page defaults - shared content lives here so competitor pages only need competitor-specific data
12
+ alternative:
13
+ competitor:
14
+ name: "Competitor"
15
+ description: ""
16
+ hero:
17
+ tagline: "The #1 {{ page.resolved.alternative.competitor.name }} alternative"
18
+ headline: "{{ site.brand.name }} vs"
19
+ headline_accent: "{{ page.resolved.alternative.competitor.name }}"
20
+ description: "Looking for a {{ page.resolved.alternative.competitor.name }} alternative? See why thousands of users choose {{ site.brand.name }} for a faster, more powerful experience."
21
+ primary_button:
22
+ text: "Try Free for 14 Days"
23
+ icon: "rocket"
24
+ href: "/pricing"
25
+ class: "btn-light"
26
+ secondary_button:
27
+ text: "See All Features"
28
+ icon: "list-check"
29
+ href: "/pricing"
30
+ class: "btn-outline-light"
31
+ comparison:
32
+ superheadline:
33
+ icon: "scale-balanced"
34
+ text: "Head to Head"
35
+ headline: "See how we"
36
+ headline_accent: "compare"
37
+ subheadline: "A side-by-side look at {{ site.brand.name }} vs {{ page.resolved.alternative.competitor.name }}"
38
+ features: []
39
+ why_switch:
40
+ superheadline:
41
+ icon: "arrow-right-arrow-left"
42
+ text: "Why Switch"
43
+ headline: "Why teams are switching to"
44
+ headline_accent: "{{ site.brand.name }}"
45
+ subheadline: "Here's what makes us different"
46
+ items:
47
+ - title: "10x faster performance"
48
+ description: "Our platform is built on modern infrastructure that delivers blazing-fast load times and real-time updates. No more waiting around for pages to load or data to sync."
49
+ image: "https://cdn.itwcreativeworks.com/assets/sample/images/demos/1x1/sample-demo-1.svg"
50
+ - title: "Built for teams of all sizes"
51
+ description: "Whether you're a solo founder or a growing enterprise, our flexible workspace adapts to your needs. Collaborate seamlessly with unlimited team members on any plan."
52
+ image: "https://cdn.itwcreativeworks.com/assets/sample/images/demos/1x1/sample-demo-2.svg"
53
+ - title: "AI that actually works"
54
+ description: "Our AI features aren't just a gimmick. They're deeply integrated into every workflow to help you automate repetitive tasks and make smarter decisions faster."
55
+ image: "https://cdn.itwcreativeworks.com/assets/sample/images/demos/1x1/sample-demo-3.svg"
56
+ video:
57
+ superheadline:
58
+ icon: "circle-play"
59
+ text: "Watch Demo"
60
+ headline: "See {{ site.brand.name }} in"
61
+ headline_accent: "action"
62
+ subheadline: "A quick walkthrough of what makes {{ site.brand.name }} the best {{ page.resolved.alternative.competitor.name }} alternative"
63
+ youtube_id: null
64
+ testimonials:
65
+ superheadline:
66
+ icon: "megaphone"
67
+ text: "Testimonials"
68
+ headline: "People {% uj_icon \"heart\", \"text-danger\" %} "
69
+ headline_accent: "{{ site.brand.name }}"
70
+ subheadline: "Hear from real users who made the switch"
71
+ items:
72
+ - quote: "We made the switch and the difference is night and day. Everything just works faster."
73
+ author: "Sarah Johnson"
74
+ role: "Product Manager"
75
+ company: "TechStart Inc"
76
+ initial: "S"
77
+ - quote: "The AI features alone justified the switch. We're saving 10+ hours per week on repetitive tasks."
78
+ author: "Michael Chen"
79
+ role: "CTO"
80
+ company: "DataFlow"
81
+ initial: "M"
82
+ - quote: "The support team responds within minutes. It's refreshing to work with a company that actually cares."
83
+ author: "Emily Davis"
84
+ role: "Operations Director"
85
+ company: "Creative Studio"
86
+ initial: "E"
87
+ stats:
88
+ - number: "50,000+"
89
+ label: "Active Users"
90
+ sublabel: "From 120+ Countries"
91
+ icon: "users"
92
+ color: "primary"
93
+ - number: "4.9"
94
+ label: "Average Rating"
95
+ icon: "star"
96
+ color: "warning"
97
+ show_stars: true
98
+ - number: "99.99%"
99
+ label: "Uptime"
100
+ sublabel: "Enterprise-Grade"
101
+ icon: "shield-check"
102
+ color: "success"
103
+ - number: "24/7"
104
+ label: "Support"
105
+ sublabel: "Real Humans"
106
+ icon: "headset"
107
+ color: "info"
108
+ faqs:
109
+ superheadline:
110
+ icon: "messages-question"
111
+ text: "FAQs"
112
+ headline: "Switching"
113
+ headline_accent: "questions"
114
+ subheadline: "Everything you need to know about switching from {{ page.resolved.alternative.competitor.name }} to {{ site.brand.name }}"
115
+ items:
116
+ - question: "Can I import my data from {{ page.resolved.alternative.competitor.name }}?"
117
+ answer: "Yes! We offer a one-click migration tool that imports all your projects, files, and settings. The entire process takes just a few minutes."
118
+ - question: "Is there a free trial?"
119
+ answer: "Absolutely. You get a full 14-day free trial with access to all premium features. No credit card required to start."
120
+ - question: "How does pricing compare to {{ page.resolved.alternative.competitor.name }}?"
121
+ answer: "Our plans start at the same price point but include significantly more features. Most teams find they save money by switching because they no longer need additional tools."
122
+ - question: "What if I need help migrating?"
123
+ answer: "Our support team is available 24/7 to help with your migration. We also offer dedicated onboarding sessions for teams of 10+ members."
124
+ - question: "Can I cancel anytime?"
125
+ answer: "Yes, you can cancel your subscription at any time with no questions asked. We also offer a 30-day money-back guarantee."
126
+ section_cta:
127
+ text: "Get Started Free"
128
+ icon: "rocket"
129
+ href: "/pricing"
130
+ cta:
131
+ superheadline:
132
+ icon: "rocket"
133
+ text: "Make the Switch"
134
+ headline: "Ready to leave"
135
+ headline_accent: "{{ page.resolved.alternative.competitor.name }} behind?"
136
+ description: "Join thousands who chose {{ site.brand.name }}. Start your free trial today — no credit card required."
137
+ primary_button:
138
+ text: "Start Free Trial"
139
+ icon: "rocket"
140
+ href: "/pricing"
141
+ secondary_button:
142
+ text: "Talk to Sales"
143
+ icon: "comments"
144
+ href: "/contact"
145
+ ---
146
+
147
+ {% assign alt = page.resolved.alternative %}
148
+
149
+ <!-- Hero Section -->
150
+ <section class="bg-gradient-rainbow gradient-animated gradient-grain text-light overflow-hidden position-relative min-vh-80 d-flex align-items-center rounded-bottom-4 shadow-lg" data-competitor-name="{{ alt.competitor.name }}">
151
+ <div class="container py-5">
152
+ <div class="row justify-content-center">
153
+ <div class="col-lg-10 text-center py-5">
154
+ <div data-lazy="@class animation-slide-up">
155
+ {% iftruthy alt.hero.tagline %}
156
+ <p class="text-uppercase fw-semibold mb-3 opacity-80">{{ alt.hero.tagline | uj_liquify }}</p>
157
+ {% endiftruthy %}
158
+
159
+ <h1 class="display-3 fw-900 mb-4">
160
+ {{ alt.hero.headline | uj_liquify }} <span class="text-accent">{{ alt.hero.headline_accent | uj_liquify }}</span>
161
+ </h1>
162
+
163
+ {% iftruthy alt.hero.description %}
164
+ <p class="fs-4 mb-4 opacity-80">{{ alt.hero.description | uj_liquify }}</p>
165
+ {% endiftruthy %}
166
+
167
+ {% assign primary_btn_class = alt.hero.primary_button.class | default: "btn-light" %}
168
+ {% assign secondary_btn_class = alt.hero.secondary_button.class | default: "btn-outline-light" %}
169
+ <div class="d-flex flex-row flex-wrap gap-3 justify-content-center">
170
+ {% iftruthy alt.hero.primary_button.text %}
171
+ <a href="{{ alt.hero.primary_button.href }}" class="btn {{ primary_btn_class }} btn-lg py-3 px-5">
172
+ {% iftruthy alt.hero.primary_button.icon %}
173
+ {% uj_icon alt.hero.primary_button.icon, "me-2" %}
174
+ {% endiftruthy %}
175
+ {{ alt.hero.primary_button.text }}
176
+ </a>
177
+ {% endiftruthy %}
178
+ {% iftruthy alt.hero.secondary_button.text %}
179
+ <a href="{{ alt.hero.secondary_button.href }}" class="btn {{ secondary_btn_class }} btn-lg py-3 px-5">
180
+ {% iftruthy alt.hero.secondary_button.icon %}
181
+ {% uj_icon alt.hero.secondary_button.icon, "me-2" %}
182
+ {% endiftruthy %}
183
+ {{ alt.hero.secondary_button.text }}
184
+ </a>
185
+ {% endiftruthy %}
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ </div>
191
+ </section>
192
+
193
+ <!-- Comparison Table Section -->
194
+ {% assign comparison_features = alt.comparison.features %}
195
+ {% assign comparison_size = comparison_features | size %}
196
+ {% if comparison_size > 0 %}
197
+ <section>
198
+ <div class="container">
199
+ <div class="text-center mb-5" data-lazy="@class animation-slide-up">
200
+ {% iftruthy alt.comparison.superheadline.text %}
201
+ <span class="badge bg-body-tertiary border-gradient-rainbow border-1 text-body p-2 mb-1 fw-semibold small">
202
+ {% iftruthy alt.comparison.superheadline.icon %}
203
+ {% uj_icon alt.comparison.superheadline.icon, "me-1" %}
204
+ {% endiftruthy %}
205
+ {{ alt.comparison.superheadline.text }}
206
+ </span>
207
+ {% endiftruthy %}
208
+ <h2 class="h2 mb-2">
209
+ {{ alt.comparison.headline | uj_liquify }}
210
+ {% iftruthy alt.comparison.headline_accent %}
211
+ <span class="text-accent">{{ alt.comparison.headline_accent | uj_liquify }}</span>
212
+ {% endiftruthy %}
213
+ </h2>
214
+ {% iftruthy alt.comparison.subheadline %}
215
+ <p class="fs-5 text-muted">{{ alt.comparison.subheadline | uj_liquify }}</p>
216
+ {% endiftruthy %}
217
+ </div>
218
+
219
+ <div class="row justify-content-center">
220
+ <div class="col-lg-10">
221
+ <div class="table-responsive" data-lazy="@class animation-slide-up">
222
+ <table class="table table-hover align-middle">
223
+ <thead>
224
+ <tr>
225
+ <th scope="col" class="border-0 w-40">Feature</th>
226
+ <th scope="col" class="border-0 text-center fw-bold">{{ site.brand.name }}</th>
227
+ <th scope="col" class="border-0 text-center text-muted">{{ alt.competitor.name }}</th>
228
+ </tr>
229
+ </thead>
230
+ <tbody>
231
+ {% for feature in comparison_features %}
232
+ <tr>
233
+ <td class="fw-semibold">
234
+ {% iftruthy feature.icon %}
235
+ {% uj_icon feature.icon, "fa-md me-2 text-muted" %}
236
+ {% endiftruthy %}
237
+ {{ feature.name }}
238
+ </td>
239
+ <td class="text-center">
240
+ {% if feature.ours.value == true %}
241
+ {% uj_icon "circle-check", "text-success fs-4" %}
242
+ {% elsif feature.ours.value == false %}
243
+ {% uj_icon "circle-xmark", "text-muted fs-4 opacity-25" %}
244
+ {% else %}
245
+ <span class="fw-semibold">{{ feature.ours.value }}</span>
246
+ {% endif %}
247
+ </td>
248
+ <td class="text-center">
249
+ {% if feature.theirs.value == true %}
250
+ {% uj_icon "circle-check", "text-success fs-4" %}
251
+ {% elsif feature.theirs.value == false %}
252
+ {% uj_icon "circle-xmark", "text-muted fs-4 opacity-25" %}
253
+ {% else %}
254
+ <span class="text-muted">{{ feature.theirs.value }}</span>
255
+ {% endif %}
256
+ </td>
257
+ </tr>
258
+ {% endfor %}
259
+ </tbody>
260
+ </table>
261
+ </div>
262
+ </div>
263
+ </div>
264
+
265
+ {% iftruthy alt.section_cta.text %}
266
+ <div class="text-center mt-5" data-lazy="@class animation-slide-up">
267
+ <a href="{{ alt.section_cta.href }}" class="btn btn-primary btn-lg px-5">
268
+ {% iftruthy alt.section_cta.icon %}
269
+ {% uj_icon alt.section_cta.icon, "me-2" %}
270
+ {% endiftruthy %}
271
+ {{ alt.section_cta.text }}
272
+ </a>
273
+ </div>
274
+ {% endiftruthy %}
275
+ </div>
276
+ </section>
277
+ {% endif %}
278
+
279
+ <!-- Why Switch Section -->
280
+ {% assign why_switch_items = alt.why_switch.items %}
281
+ {% assign why_switch_size = why_switch_items | size %}
282
+ {% if why_switch_size > 0 %}
283
+ <section class="bg-body-secondary rounded-4">
284
+ <div class="container">
285
+ <div class="text-center mb-5" data-lazy="@class animation-slide-up">
286
+ {% iftruthy alt.why_switch.superheadline.text %}
287
+ <span class="badge bg-body-tertiary border-gradient-rainbow border-1 text-body p-2 mb-1 fw-semibold small">
288
+ {% iftruthy alt.why_switch.superheadline.icon %}
289
+ {% uj_icon alt.why_switch.superheadline.icon, "me-1" %}
290
+ {% endiftruthy %}
291
+ {{ alt.why_switch.superheadline.text }}
292
+ </span>
293
+ {% endiftruthy %}
294
+ <h2 class="h2 mb-2">
295
+ {{ alt.why_switch.headline | uj_liquify }}
296
+ {% iftruthy alt.why_switch.headline_accent %}
297
+ <span class="text-accent">{{ alt.why_switch.headline_accent | uj_liquify }}</span>
298
+ {% endiftruthy %}
299
+ </h2>
300
+ {% iftruthy alt.why_switch.subheadline %}
301
+ <p class="fs-5 text-muted">{{ alt.why_switch.subheadline | uj_liquify }}</p>
302
+ {% endiftruthy %}
303
+ </div>
304
+
305
+ {% for item in why_switch_items %}
306
+ {% assign is_even = forloop.index | modulo: 2 %}
307
+
308
+ {% if is_even == 0 %}
309
+ {% assign image_col_class = "col-lg-6 order-lg-2" %}
310
+ {% assign text_col_class = "col-lg-6 order-lg-1 pe-lg-5" %}
311
+ {% else %}
312
+ {% assign image_col_class = "col-lg-6" %}
313
+ {% assign text_col_class = "col-lg-6 ps-lg-5" %}
314
+ {% endif %}
315
+
316
+ <div class="row align-items-center g-3 g-lg-5 {% unless forloop.last %} mb-5 pb-5 {% endunless %}">
317
+ {% iftruthy item.image %}
318
+ <div class="{{ image_col_class }}" data-lazy="@class animation-slide-up">
319
+ <div class="card border-0 shadow-sm ratio ratio-4x3">
320
+ {% uj_image item.image, class="w-100 h-100 object-fit-cover rounded", alt=item.title %}
321
+ </div>
322
+ </div>
323
+ {% endiftruthy %}
324
+ <div class="{% iftruthy item.image %}{{ text_col_class }}{% endiftruthy %}{% iffalsy item.image %}col-lg-8 mx-auto text-center{% endiffalsy %}" data-lazy="@class animation-slide-up">
325
+ {% iftruthy item.icon %}
326
+ <div class="mb-3">
327
+ {% uj_icon item.icon, "display-5 text-primary" %}
328
+ </div>
329
+ {% endiftruthy %}
330
+ <h3 class="h2 mb-4">{{ item.title | uj_liquify }}</h3>
331
+ <p class="fs-5 text-muted mb-0">{{ item.description | uj_liquify }}</p>
332
+ </div>
333
+ </div>
334
+ {% endfor %}
335
+
336
+ {% iftruthy alt.section_cta.text %}
337
+ <div class="text-center mt-5" data-lazy="@class animation-slide-up">
338
+ <a href="{{ alt.section_cta.href }}" class="btn btn-primary btn-lg px-5">
339
+ {% iftruthy alt.section_cta.icon %}
340
+ {% uj_icon alt.section_cta.icon, "me-2" %}
341
+ {% endiftruthy %}
342
+ {{ alt.section_cta.text }}
343
+ </a>
344
+ </div>
345
+ {% endiftruthy %}
346
+ </div>
347
+ </section>
348
+ {% endif %}
349
+
350
+ <!-- Video Section -->
351
+ {% iftruthy alt.video.youtube_id %}
352
+ <section>
353
+ <div class="container">
354
+ <div class="text-center mb-5" data-lazy="@class animation-slide-up">
355
+ {% iftruthy alt.video.superheadline.text %}
356
+ <span class="badge bg-body-tertiary border-gradient-rainbow border-1 text-body p-2 mb-1 fw-semibold small">
357
+ {% iftruthy alt.video.superheadline.icon %}
358
+ {% uj_icon alt.video.superheadline.icon, "me-1" %}
359
+ {% endiftruthy %}
360
+ {{ alt.video.superheadline.text }}
361
+ </span>
362
+ {% endiftruthy %}
363
+ <h2 class="h2 mb-2">
364
+ {{ alt.video.headline | uj_liquify }}
365
+ {% iftruthy alt.video.headline_accent %}
366
+ <span class="text-accent">{{ alt.video.headline_accent | uj_liquify }}</span>
367
+ {% endiftruthy %}
368
+ </h2>
369
+ {% iftruthy alt.video.subheadline %}
370
+ <p class="fs-5 text-muted">{{ alt.video.subheadline | uj_liquify }}</p>
371
+ {% endiftruthy %}
372
+ </div>
373
+
374
+ <div class="row justify-content-center">
375
+ <div class="col-lg-10" data-lazy="@class animation-slide-up">
376
+ <div class="card border-gradient-rainbow shadow-lg rounded-4 overflow-hidden">
377
+ <div class="ratio ratio-16x9">
378
+ <iframe
379
+ data-lazy="@src https://www.youtube.com/embed/{{ alt.video.youtube_id }}?rel=0"
380
+ title="Video"
381
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
382
+ allowfullscreen
383
+ class="border-0"
384
+ ></iframe>
385
+ </div>
386
+ </div>
387
+ </div>
388
+ </div>
389
+
390
+ {% iftruthy alt.section_cta.text %}
391
+ <div class="text-center mt-5" data-lazy="@class animation-slide-up">
392
+ <a href="{{ alt.section_cta.href }}" class="btn btn-primary btn-lg px-5">
393
+ {% iftruthy alt.section_cta.icon %}
394
+ {% uj_icon alt.section_cta.icon, "me-2" %}
395
+ {% endiftruthy %}
396
+ {{ alt.section_cta.text }}
397
+ </a>
398
+ </div>
399
+ {% endiftruthy %}
400
+ </div>
401
+ </section>
402
+ {% endiftruthy %}
403
+
404
+ <!-- Testimonials Section -->
405
+ {% assign testimonials_size = alt.testimonials.items | size %}
406
+ {% if testimonials_size > 0 %}
407
+ {% include themes/classy/frontend/components/testimonial-scroll.html testimonials=alt.testimonials %}
408
+ {% iftruthy alt.section_cta.text %}
409
+ <div class="container">
410
+ <div class="text-center" data-lazy="@class animation-slide-up">
411
+ <a href="{{ alt.section_cta.href }}" class="btn btn-primary btn-lg px-5">
412
+ {% iftruthy alt.section_cta.icon %}
413
+ {% uj_icon alt.section_cta.icon, "me-2" %}
414
+ {% endiftruthy %}
415
+ {{ alt.section_cta.text }}
416
+ </a>
417
+ </div>
418
+ </div>
419
+ {% endiftruthy %}
420
+ {% endif %}
421
+
422
+ <!-- Stats Section -->
423
+ {% assign stats_size = alt.stats | size %}
424
+ {% if stats_size > 0 %}
425
+ <section>
426
+ <div class="container">
427
+ <div class="row text-center g-4">
428
+ {% for stat in alt.stats %}
429
+ <div class="col-lg-3 col-md-6" data-lazy="@class animation-slide-up">
430
+ <div class="mb-3">
431
+ {% uj_icon stat.icon, "text-{{ stat.color }} display-4" %}
432
+ </div>
433
+ <h3 class="display-5 fw-bold mb-2">{{ stat.number }}</h3>
434
+ {% iftruthy stat.show_stars %}
435
+ <div class="mb-0">
436
+ {% for i in (1..5) %}
437
+ {% uj_icon "star", "text-{{ stat.color }}" %}
438
+ {% endfor %}
439
+ </div>
440
+ {% endiftruthy %}
441
+ <p class="text-muted mb-0">{{ stat.label }}</p>
442
+ {% iftruthy stat.sublabel %}
443
+ <p class="small text-muted">{{ stat.sublabel }}</p>
444
+ {% endiftruthy %}
445
+ </div>
446
+ {% endfor %}
447
+ </div>
448
+
449
+ {% iftruthy alt.section_cta.text %}
450
+ <div class="text-center mt-5" data-lazy="@class animation-slide-up">
451
+ <a href="{{ alt.section_cta.href }}" class="btn btn-primary btn-lg px-5">
452
+ {% iftruthy alt.section_cta.icon %}
453
+ {% uj_icon alt.section_cta.icon, "me-2" %}
454
+ {% endiftruthy %}
455
+ {{ alt.section_cta.text }}
456
+ </a>
457
+ </div>
458
+ {% endiftruthy %}
459
+ </div>
460
+ </section>
461
+ {% endif %}
462
+
463
+ <!-- FAQ Section -->
464
+ {% assign faqs_size = alt.faqs.items | size %}
465
+ {% if faqs_size > 0 %}
466
+ <section>
467
+ <div class="container">
468
+ <div class="row justify-content-center">
469
+ <div class="col-lg-8">
470
+ <div class="text-center mb-5" data-lazy="@class animation-slide-up">
471
+ {% iftruthy alt.faqs.superheadline.text %}
472
+ <span class="badge bg-body-tertiary border-gradient-rainbow border-1 text-body p-2 mb-1 fw-semibold small">
473
+ {% iftruthy alt.faqs.superheadline.icon %}
474
+ {% uj_icon alt.faqs.superheadline.icon, "me-1" %}
475
+ {% endiftruthy %}
476
+ {{ alt.faqs.superheadline.text }}
477
+ </span>
478
+ {% endiftruthy %}
479
+ <h2 class="h2 mb-2">
480
+ {{ alt.faqs.headline | uj_liquify }}
481
+ {% iftruthy alt.faqs.headline_accent %}
482
+ <span class="text-accent">{{ alt.faqs.headline_accent | uj_liquify }}</span>
483
+ {% endiftruthy %}
484
+ </h2>
485
+ {% iftruthy alt.faqs.subheadline %}
486
+ <p class="fs-5 text-muted">{{ alt.faqs.subheadline | uj_liquify }}</p>
487
+ {% endiftruthy %}
488
+ </div>
489
+
490
+ <div class="accordion" id="faqAccordion" data-lazy="@class animation-slide-up">
491
+ {% for faq in alt.faqs.items %}
492
+ <div class="accordion-item border-0 mb-3">
493
+ <h2 class="accordion-header">
494
+ <button class="accordion-button collapsed py-4" type="button" data-bs-toggle="collapse" data-bs-target="#faq{{ forloop.index }}" aria-expanded="false" aria-controls="faq{{ forloop.index }}">
495
+ <span class="fw-semibold">{{ faq.question | uj_liquify }}</span>
496
+ </button>
497
+ </h2>
498
+ <div id="faq{{ forloop.index }}" class="accordion-collapse collapse" data-bs-parent="#faqAccordion">
499
+ <div class="accordion-body text-muted">
500
+ {{ faq.answer | uj_liquify }}
501
+ </div>
502
+ </div>
503
+ </div>
504
+ {% endfor %}
505
+ </div>
506
+
507
+ {% iftruthy alt.section_cta.text %}
508
+ <div class="text-center mt-5" data-lazy="@class animation-slide-up">
509
+ <a href="{{ alt.section_cta.href }}" class="btn btn-primary btn-lg px-5">
510
+ {% iftruthy alt.section_cta.icon %}
511
+ {% uj_icon alt.section_cta.icon, "me-2" %}
512
+ {% endiftruthy %}
513
+ {{ alt.section_cta.text }}
514
+ </a>
515
+ </div>
516
+ {% endiftruthy %}
517
+ </div>
518
+ </div>
519
+ </div>
520
+ </section>
521
+ {% endif %}
522
+
523
+ <!-- CTA Section -->
524
+ {% iftruthy alt.cta.headline %}
525
+ <section>
526
+ <div class="container">
527
+ <div class="card border-0 bg-gradient bg-primary text-white rounded-4 p-4 p-md-5 text-center position-relative overflow-hidden" data-lazy="@class animation-slide-up">
528
+ <!-- Decorative icon - top right -->
529
+ <div class="position-absolute top-0 end-0 opacity-25" style="font-size:10rem;transform:rotate(15deg)translate(30%,-30%)">
530
+ {% uj_icon "rocket", "text-white" %}
531
+ </div>
532
+
533
+ <!-- Decorative icon - bottom left -->
534
+ <div class="position-absolute bottom-0 start-0 opacity-25" style="font-size:8rem;transform:rotate(-20deg)translate(-30%,30%)">
535
+ {% uj_icon "sparkles", "text-white" %}
536
+ </div>
537
+
538
+ <div class="position-relative">
539
+ {% iftruthy alt.cta.superheadline.text %}
540
+ <span class="badge bg-white bg-opacity-25 text-light p-2 mb-3 fw-semibold small">
541
+ {% iftruthy alt.cta.superheadline.icon %}
542
+ {% uj_icon alt.cta.superheadline.icon, "me-1" %}
543
+ {% endiftruthy %}
544
+ {{ alt.cta.superheadline.text }}
545
+ </span>
546
+ {% endiftruthy %}
547
+
548
+ <h2 class="h3 fw-bold mb-3">
549
+ {{ alt.cta.headline | uj_liquify }}
550
+ {% iftruthy alt.cta.headline_accent %}
551
+ <span class="text-accent">{{ alt.cta.headline_accent | uj_liquify }}</span>
552
+ {% endiftruthy %}
553
+ </h2>
554
+
555
+ {% iftruthy alt.cta.description %}
556
+ <p class="lead mb-4">{{ alt.cta.description | uj_liquify }}</p>
557
+ {% endiftruthy %}
558
+
559
+ <div class="d-flex flex-column flex-sm-row gap-3 justify-content-center">
560
+ {% iftruthy alt.cta.primary_button.text %}
561
+ <a href="{{ alt.cta.primary_button.href }}" class="btn btn-light btn-lg px-4">
562
+ {% iftruthy alt.cta.primary_button.icon %}
563
+ {% uj_icon alt.cta.primary_button.icon, "me-2" %}
564
+ {% endiftruthy %}
565
+ {{ alt.cta.primary_button.text }}
566
+ </a>
567
+ {% endiftruthy %}
568
+ {% iftruthy alt.cta.secondary_button.text %}
569
+ <a href="{{ alt.cta.secondary_button.href }}" class="btn btn-outline-light btn-lg px-4">
570
+ {% iftruthy alt.cta.secondary_button.icon %}
571
+ {% uj_icon alt.cta.secondary_button.icon, "me-2" %}
572
+ {% endiftruthy %}
573
+ {{ alt.cta.secondary_button.text }}
574
+ </a>
575
+ {% endiftruthy %}
576
+ </div>
577
+ </div>
578
+ </div>
579
+ </div>
580
+ </section>
581
+ {% endiftruthy %}
582
+
583
+ {{ content | uj_content_format }}
@@ -0,0 +1,353 @@
1
+ ---
2
+ ### ALL PAGES ###
3
+ layout: themes/[ site.theme.id ]/frontend/core/base
4
+
5
+ #### THEME CONFIG ####
6
+ theme:
7
+ main:
8
+ class: "pt-0"
9
+
10
+ ### PAGE CONFIG ###
11
+ # Hero Section
12
+ hero:
13
+ tagline: "Compare & Choose"
14
+ headline: "{{ site.brand.name }} vs the"
15
+ headline_accent: "competition"
16
+ description: "Not sure if {{ site.brand.name }} is right for you? Compare us head-to-head with the most popular alternatives and see why thousands are making the switch."
17
+ primary_button:
18
+ text: "Get Started Free"
19
+ icon: "rocket"
20
+ href: "/pricing"
21
+ class: "btn-light"
22
+ secondary_button:
23
+ text: "See Pricing"
24
+ icon: "tags"
25
+ href: "/pricing"
26
+ class: "btn-outline-light"
27
+
28
+ # Alternatives Section
29
+ alternatives:
30
+ superheadline:
31
+ icon: "scale-balanced"
32
+ text: "Comparisons"
33
+ headline: "Explore"
34
+ headline_accent: "alternatives"
35
+ subheadline: "In-depth comparisons to help you make the right choice"
36
+ empty_message: "No alternatives available yet"
37
+ view_comparison: "View full comparison"
38
+
39
+ # Value Props Section
40
+ value_props:
41
+ superheadline:
42
+ icon: "trophy"
43
+ text: "Why Us"
44
+ headline: "Why people choose"
45
+ headline_accent: "{{ site.brand.name }}"
46
+ subheadline: "Here's what sets us apart from the rest"
47
+ items:
48
+ - title: "Lightning Fast"
49
+ description: "Built on modern infrastructure for blazing performance. No more waiting around."
50
+ icon: "bolt"
51
+ - title: "AI-Powered"
52
+ description: "Smart automation built into every workflow to save you hours every week."
53
+ icon: "sparkles"
54
+ - title: "24/7 Support"
55
+ description: "Real humans ready to help whenever you need it. Average response time under 5 minutes."
56
+ icon: "headset"
57
+
58
+ # Stats Section
59
+ stats:
60
+ - number: "50,000+"
61
+ label: "Active Users"
62
+ sublabel: "From 120+ Countries"
63
+ icon: "users"
64
+ color: "primary"
65
+ - number: "4.9"
66
+ label: "Average Rating"
67
+ icon: "star"
68
+ color: "warning"
69
+ show_stars: true
70
+ - number: "99.99%"
71
+ label: "Uptime"
72
+ sublabel: "Enterprise-Grade"
73
+ icon: "shield-check"
74
+ color: "success"
75
+ - number: "24/7"
76
+ label: "Support"
77
+ sublabel: "Real Humans"
78
+ icon: "headset"
79
+ color: "info"
80
+
81
+ # CTA Section
82
+ cta:
83
+ superheadline:
84
+ icon: "rocket"
85
+ text: "Get Started"
86
+ headline: "Ready to make the"
87
+ headline_accent: "switch?"
88
+ description: "Join thousands of happy users who chose {{ site.brand.name }}. Start your free trial today — no credit card required."
89
+ primary_button:
90
+ text: "Start Free Trial"
91
+ icon: "rocket"
92
+ href: "/pricing"
93
+ secondary_button:
94
+ text: "Talk to Sales"
95
+ icon: "comments"
96
+ href: "/contact"
97
+ ---
98
+
99
+ <!-- Hero Section -->
100
+ <section class="bg-gradient-rainbow gradient-animated gradient-grain text-light overflow-hidden position-relative min-vh-60 d-flex align-items-center rounded-bottom-4 shadow-lg">
101
+ <div class="container py-5">
102
+ <div class="row justify-content-center">
103
+ <div class="col-lg-10 text-center py-5">
104
+ <div data-lazy="@class animation-slide-up">
105
+ {% iftruthy page.resolved.hero.tagline %}
106
+ <p class="text-uppercase fw-semibold mb-3 opacity-80">{{ page.resolved.hero.tagline }}</p>
107
+ {% endiftruthy %}
108
+
109
+ <h1 class="display-3 fw-900 mb-4">
110
+ {{ page.resolved.hero.headline }} <span class="text-accent">{{ page.resolved.hero.headline_accent }}</span>
111
+ </h1>
112
+
113
+ {% iftruthy page.resolved.hero.description %}
114
+ <p class="fs-4 mb-4 opacity-80">{{ page.resolved.hero.description }}</p>
115
+ {% endiftruthy %}
116
+
117
+ {% assign primary_btn_class = page.resolved.hero.primary_button.class | default: "btn-light" %}
118
+ {% assign secondary_btn_class = page.resolved.hero.secondary_button.class | default: "btn-outline-light" %}
119
+ <div class="d-flex flex-row flex-wrap gap-3 justify-content-center">
120
+ {% iftruthy page.resolved.hero.primary_button.text %}
121
+ <a href="{{ page.resolved.hero.primary_button.href }}" class="btn {{ primary_btn_class }} btn-lg py-3 px-5">
122
+ {% iftruthy page.resolved.hero.primary_button.icon %}
123
+ {% uj_icon page.resolved.hero.primary_button.icon, "me-2" %}
124
+ {% endiftruthy %}
125
+ {{ page.resolved.hero.primary_button.text }}
126
+ </a>
127
+ {% endiftruthy %}
128
+ {% iftruthy page.resolved.hero.secondary_button.text %}
129
+ <a href="{{ page.resolved.hero.secondary_button.href }}" class="btn {{ secondary_btn_class }} btn-lg py-3 px-5">
130
+ {% iftruthy page.resolved.hero.secondary_button.icon %}
131
+ {% uj_icon page.resolved.hero.secondary_button.icon, "me-2" %}
132
+ {% endiftruthy %}
133
+ {{ page.resolved.hero.secondary_button.text }}
134
+ </a>
135
+ {% endiftruthy %}
136
+ </div>
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </section>
142
+
143
+ <!-- Alternatives List Section -->
144
+ <section>
145
+ <div class="container">
146
+ <div class="text-center mb-5" data-lazy="@class animation-slide-up">
147
+ {% iftruthy page.resolved.alternatives.superheadline.text %}
148
+ <span class="badge bg-body-tertiary border-gradient-rainbow border-1 text-body p-2 mb-1 fw-semibold small">
149
+ {% iftruthy page.resolved.alternatives.superheadline.icon %}
150
+ {% uj_icon page.resolved.alternatives.superheadline.icon, "me-1" %}
151
+ {% endiftruthy %}
152
+ {{ page.resolved.alternatives.superheadline.text }}
153
+ </span>
154
+ {% endiftruthy %}
155
+ <h2 class="h2 mb-2">
156
+ {{ page.resolved.alternatives.headline }}
157
+ {% iftruthy page.resolved.alternatives.headline_accent %}
158
+ <span class="text-accent">{{ page.resolved.alternatives.headline_accent }}</span>
159
+ {% endiftruthy %}
160
+ </h2>
161
+ {% iftruthy page.resolved.alternatives.subheadline %}
162
+ <p class="fs-5 text-muted">{{ page.resolved.alternatives.subheadline }}</p>
163
+ {% endiftruthy %}
164
+ </div>
165
+
166
+ {% if site.alternatives %}
167
+ {% assign alternatives = site.alternatives | sort: 'alternative.competitor.name' %}
168
+ {% else %}
169
+ {% assign alternatives = nil %}
170
+ {% endif %}
171
+
172
+ {% if alternatives and alternatives.size > 0 %}
173
+ <div class="row g-4 justify-content-center">
174
+ {% for item in alternatives %}
175
+ {% if item.draft and jekyll.environment == 'production' %}
176
+ {% continue %}
177
+ {% endif %}
178
+ <div class="col-md-6 col-lg-4" data-lazy="@class animation-slide-up">
179
+ <div class="card border-0 bg-body-tertiary h-100 hover-flex rounded-4 overflow-hidden">
180
+ <div class="card-body p-0 d-flex flex-column">
181
+ <!-- Gradient header strip -->
182
+ <div class="bg-gradient-rainbow gradient-animated p-4 text-light">
183
+ <div class="d-flex align-items-center gap-3">
184
+ <div class="bg-white bg-opacity-25 rounded-circle d-flex align-items-center justify-content-center flex-shrink-0" style="width:48px;height:48px">
185
+ {% uj_icon "scale-balanced", "text-white fs-5" %}
186
+ </div>
187
+ <h3 class="h5 fw-bold mb-0">
188
+ {{ site.brand.name }} vs {{ item.alternative.competitor.name }}
189
+ </h3>
190
+ </div>
191
+ </div>
192
+
193
+ <div class="p-4 d-flex flex-column flex-grow-1">
194
+ {% iftruthy item.alternative.competitor.description %}
195
+ <p class="text-muted mb-4 flex-grow-1">{{ item.alternative.competitor.description }}</p>
196
+ {% endiftruthy %}
197
+
198
+ <a href="{{ item.url }}" class="btn btn-primary w-100 stretched-link">
199
+ {{ page.resolved.alternatives.view_comparison }}
200
+ {% uj_icon "arrow-right", "ms-2" %}
201
+ </a>
202
+ </div>
203
+ </div>
204
+ </div>
205
+ </div>
206
+ {% endfor %}
207
+ </div>
208
+ {% else %}
209
+ <div class="card border-0 bg-body-tertiary rounded-4" data-lazy="@class animation-slide-up">
210
+ <div class="card-body p-5 text-center text-muted">
211
+ {% uj_icon "box-open", "display-4 mb-3 opacity-50" %}
212
+ <p class="fs-5 mb-0">{{ page.resolved.alternatives.empty_message }}</p>
213
+ </div>
214
+ </div>
215
+ {% endif %}
216
+ </div>
217
+ </section>
218
+
219
+ <!-- Value Props Section -->
220
+ {% assign value_props_size = page.resolved.value_props.items | size %}
221
+ {% if value_props_size > 0 %}
222
+ <section class="bg-body-secondary rounded-4">
223
+ <div class="container">
224
+ <div class="text-center mb-5" data-lazy="@class animation-slide-up">
225
+ {% iftruthy page.resolved.value_props.superheadline.text %}
226
+ <span class="badge bg-body-tertiary border-gradient-rainbow border-1 text-body p-2 mb-1 fw-semibold small">
227
+ {% iftruthy page.resolved.value_props.superheadline.icon %}
228
+ {% uj_icon page.resolved.value_props.superheadline.icon, "me-1" %}
229
+ {% endiftruthy %}
230
+ {{ page.resolved.value_props.superheadline.text }}
231
+ </span>
232
+ {% endiftruthy %}
233
+ <h2 class="h2 mb-2">
234
+ {{ page.resolved.value_props.headline }}
235
+ {% iftruthy page.resolved.value_props.headline_accent %}
236
+ <span class="text-accent">{{ page.resolved.value_props.headline_accent }}</span>
237
+ {% endiftruthy %}
238
+ </h2>
239
+ {% iftruthy page.resolved.value_props.subheadline %}
240
+ <p class="fs-5 text-muted">{{ page.resolved.value_props.subheadline }}</p>
241
+ {% endiftruthy %}
242
+ </div>
243
+
244
+ <div class="row g-4">
245
+ {% for prop in page.resolved.value_props.items %}
246
+ <div class="col-lg-4 col-md-6" data-lazy="@class animation-slide-up">
247
+ <div class="card bg-body border-0 h-100 rounded-4 shadow-sm">
248
+ <div class="card-body p-4 text-center">
249
+ <div class="mb-4">
250
+ {% uj_icon prop.icon, "display-4 text-primary" %}
251
+ </div>
252
+ <h3 class="h4 fw-bold mb-3">{{ prop.title }}</h3>
253
+ <p class="text-muted mb-0">{{ prop.description }}</p>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ {% endfor %}
258
+ </div>
259
+ </div>
260
+ </section>
261
+ {% endif %}
262
+
263
+ <!-- Stats Section -->
264
+ {% assign stats_size = page.resolved.stats | size %}
265
+ {% if stats_size > 0 %}
266
+ <section>
267
+ <div class="container">
268
+ <div class="row text-center g-4">
269
+ {% for stat in page.resolved.stats %}
270
+ <div class="col-lg-3 col-md-6" data-lazy="@class animation-slide-up">
271
+ <div class="mb-3">
272
+ {% uj_icon stat.icon, "text-{{ stat.color }} display-4" %}
273
+ </div>
274
+ <h3 class="display-5 fw-bold mb-2">{{ stat.number }}</h3>
275
+ {% iftruthy stat.show_stars %}
276
+ <div class="mb-0">
277
+ {% for i in (1..5) %}
278
+ {% uj_icon "star", "text-{{ stat.color }}" %}
279
+ {% endfor %}
280
+ </div>
281
+ {% endiftruthy %}
282
+ <p class="text-muted mb-0">{{ stat.label }}</p>
283
+ {% iftruthy stat.sublabel %}
284
+ <p class="small text-muted">{{ stat.sublabel }}</p>
285
+ {% endiftruthy %}
286
+ </div>
287
+ {% endfor %}
288
+ </div>
289
+ </div>
290
+ </section>
291
+ {% endif %}
292
+
293
+ <!-- CTA Section -->
294
+ {% iftruthy page.resolved.cta.headline %}
295
+ <section>
296
+ <div class="container">
297
+ <div class="card border-0 bg-gradient bg-primary text-white rounded-4 p-4 p-md-5 text-center position-relative overflow-hidden" data-lazy="@class animation-slide-up">
298
+ <!-- Decorative icon - top right -->
299
+ <div class="position-absolute top-0 end-0 opacity-25" style="font-size:10rem;transform:rotate(15deg)translate(30%,-30%)">
300
+ {% uj_icon "rocket", "text-white" %}
301
+ </div>
302
+
303
+ <!-- Decorative icon - bottom left -->
304
+ <div class="position-absolute bottom-0 start-0 opacity-25" style="font-size:8rem;transform:rotate(-20deg)translate(-30%,30%)">
305
+ {% uj_icon "sparkles", "text-white" %}
306
+ </div>
307
+
308
+ <div class="position-relative">
309
+ {% iftruthy page.resolved.cta.superheadline.text %}
310
+ <span class="badge bg-white bg-opacity-25 text-light p-2 mb-3 fw-semibold small">
311
+ {% iftruthy page.resolved.cta.superheadline.icon %}
312
+ {% uj_icon page.resolved.cta.superheadline.icon, "me-1" %}
313
+ {% endiftruthy %}
314
+ {{ page.resolved.cta.superheadline.text }}
315
+ </span>
316
+ {% endiftruthy %}
317
+
318
+ <h2 class="h3 fw-bold mb-3">
319
+ {{ page.resolved.cta.headline }}
320
+ {% iftruthy page.resolved.cta.headline_accent %}
321
+ <span class="text-accent">{{ page.resolved.cta.headline_accent }}</span>
322
+ {% endiftruthy %}
323
+ </h2>
324
+
325
+ {% iftruthy page.resolved.cta.description %}
326
+ <p class="lead mb-4">{{ page.resolved.cta.description }}</p>
327
+ {% endiftruthy %}
328
+
329
+ <div class="d-flex flex-column flex-sm-row gap-3 justify-content-center">
330
+ {% iftruthy page.resolved.cta.primary_button.text %}
331
+ <a href="{{ page.resolved.cta.primary_button.href }}" class="btn btn-light btn-lg px-4">
332
+ {% iftruthy page.resolved.cta.primary_button.icon %}
333
+ {% uj_icon page.resolved.cta.primary_button.icon, "me-2" %}
334
+ {% endiftruthy %}
335
+ {{ page.resolved.cta.primary_button.text }}
336
+ </a>
337
+ {% endiftruthy %}
338
+ {% iftruthy page.resolved.cta.secondary_button.text %}
339
+ <a href="{{ page.resolved.cta.secondary_button.href }}" class="btn btn-outline-light btn-lg px-4">
340
+ {% iftruthy page.resolved.cta.secondary_button.icon %}
341
+ {% uj_icon page.resolved.cta.secondary_button.icon, "me-2" %}
342
+ {% endiftruthy %}
343
+ {{ page.resolved.cta.secondary_button.text }}
344
+ </a>
345
+ {% endiftruthy %}
346
+ </div>
347
+ </div>
348
+ </div>
349
+ </div>
350
+ </section>
351
+ {% endiftruthy %}
352
+
353
+ {{ content | uj_content_format }}
@@ -0,0 +1,7 @@
1
+ ---
2
+ ### ALL PAGES ###
3
+ layout: blueprint/alternatives/index
4
+ permalink: /alternatives
5
+
6
+ ### REGULAR PAGES ###
7
+ ---
@@ -243,3 +243,9 @@ pagination:
243
243
  title: ":title - page :num"
244
244
  sort_field: "date"
245
245
  sort_reverse: true
246
+
247
+ # Jekyll collections
248
+ collections:
249
+
250
+ # Jekyll defaults
251
+ defaults:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultimate-jekyll-manager",
3
- "version": "0.0.215",
3
+ "version": "0.0.217",
4
4
  "description": "Ultimate Jekyll dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {