ultimate-jekyll-manager 0.0.214 → 0.0.216

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
+ };
@@ -85,3 +85,33 @@ exclude:
85
85
  include:
86
86
  - .well-known
87
87
  - __
88
+
89
+ # Jekyll collections
90
+ collections:
91
+ team:
92
+ title: "Team Members"
93
+ output: true
94
+ updates:
95
+ title: "Updates"
96
+ output: true
97
+ alternatives:
98
+ title: "Alternatives"
99
+ output: true
100
+
101
+ # Jekyll defaults
102
+ defaults:
103
+ - scope:
104
+ path: ""
105
+ type: "team"
106
+ values:
107
+ permalink: "/team/:title"
108
+ - scope:
109
+ path: ""
110
+ type: "updates"
111
+ values:
112
+ permalink: "/updates/:title"
113
+ - scope:
114
+ path: ""
115
+ type: "alternatives"
116
+ values:
117
+ permalink: "/alternatives/:title"
@@ -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 }}