Conversation
Short-and-sweet page shells per kaya's ask ('keep the pages short and
sweet until then' — Wordify copy is coming in the next few days).
## Files created (folder-based clean URL pattern like /solutions/ + /features/)
Hub: webengine/views/page_html/cms-pricing/index.html
Intended URL: /cms-pricing/
Vendor pages:
webengine/views/page_html/cms-pricing/sitecore.html
webengine/views/page_html/cms-pricing/adobe-experience-manager.html
webengine/views/page_html/cms-pricing/contentful.html
webengine/views/page_html/cms-pricing/optimizely-cms.html
Intended URLs: /cms-pricing/sitecore/ etc.
## Each vendor shell contains
- Breadcrumb (Home > CMS pricing > Vendor pricing)
- H1 '[Vendor] pricing in 2026' + intro + 'Last updated' <time> line
- Estimator placeholder card (dashed border, explains what's coming)
- Empty H2 slots for the 6 planned sections: how vendor prices, cost
breakdown, worked example, what pushes the price up, Content.One for
the same setup (with 3-logo proof block), FAQ
- Methodology + Sources placeholder
- Related links (Compare vs page, Other pricing guides, Start here)
- CTA band (content-ops maturity audit + launch.content.one)
## Hub shell contains
- H1 + intro + 'Last updated'
- 15-row comparison table slot (empty placeholder)
- 'Pick your platform' grid — 4 live vendor cards
- Two H2 slots (enterprise DXP, headless CMS)
- Content.One proof block
- FAQ + Sources slots
- CTA band
## What's NOT in this PR (deferred per kaya's 'short and sweet' scope)
- Full estimator JS component with per-vendor JSON config (brief section 4)
- Actual pricing copy in H2 slots (awaits Wordify)
- Comparison table rows (awaits Wordify)
- FAQ Q/A pairs (awaits Wordify)
- Source lists (awaits Wordify)
- Zoho lead capture + PDF generation (brief 4f)
- GA4 / LinkedIn event tracking (brief 4h)
- Nav 'Compare' item with pricing-guides sub-group (brief 5a)
- Footer 'Pricing guides' column (brief 5b)
- Vs page pricing-slot rewrite to link out to vendor pages (brief 5c)
- JSON-LD schema (WebPage/BreadcrumbList/FAQPage/ItemList — waits until FAQ
copy arrives since answers must match visible text word-for-word)
- Sitemap.xml + llms.txt entries (URLs will 404 until Zesty templateset
exists — safer to add after routing works)
## Zesty admin blocker (ardeay)
For /cms-pricing/[vendor]/ URLs to route, a parent templateset needs to
exist in the Zesty editor named 'cms-pricing'. Same pattern as the
solutions/features/industries templatesets. Once the templateset exists,
the vendor page shell files auto-create as ajax-json child views via
sync-to-zesty on stage merge (per the PR #100 auto-create flow).
Contributor
💾 Stage sync previewNew files to create (6):
Will add/update — differ from dev (0): Unchanged, skipped: 0 205 mapped resources · zesty-sync |
added 2 commits
September 11, 2026 13:59
Kaya (2026-09-11): wants slugs '[vendor]-pricing' not just '[vendor]'. Renamed the 4 vendor page files + updated the hub's pick-your-platform grid links + the intended-URL comment headers. New URLs: - /cms-pricing/ (hub, unchanged) - /cms-pricing/sitecore-pricing/ - /cms-pricing/adobe-experience-manager-pricing/ - /cms-pricing/contentful-pricing/ - /cms-pricing/optimizely-cms-pricing/
…tecore Per kaya's 2026-09-11 brief section 4 (estimator config + calculation spec) + the Sitecore config in section 2. ## Component webengine/views/components/cms-pricing-estimator.html - Vanilla JS, no framework, no third-party libs (per brief 4a) - Reads config from an inline <script type='application/json' id='estimator-config'> on the host page — same shape across every vendor page, no vendor-specific code paths anywhere in the component - 7 inputs, in order: situation, edition, visits (slider), sites (slider), editors (slider), implementation, add-ons (checkboxes) - Live recalculates on every input change (60ms debounce), no submit button - Outputs: three-year total range headline, year 1/2/3 rows, breakdown table with source links per line, subscription share percentage - 'How we got this number' details collapsed by default, expands to show formulas with the user's inputs substituted - Notes + accurate-as-of caption from config - Content.One panel present as hidden slot (brief 4c 'behind a config flag') - Query-string state sync (brief 4d): s/e/v/w/u/i/a keys, read on load, updated on change via history.replaceState — shareable URLs work today - Analytics stub for estimate_rendered + estimate_changed via window.gtag (brief 4h; other events land in a later pass) Math verified against kaya's 3 test cases before writing a line of JS: - Test 1 (new/sitecoreai/500k_2m/12sites/10eds/agency) → $618k-$1,339k, share 31%/21% ✓ - Test 2 (renew/sitecoreai/same) → $519k-$1,139k ✓ - Test 3 (renew/legacy_xp/same) → sub $265k-$567k ✓ ## Sitecore page Replaced the dashed 'coming soon' placeholder card in sitecore-pricing.html with the config JSON (kaya's Section 2 numbers verbatim) + the include tag. Wordify edits Sitecore numbers by editing the JSON block on the page — no code change, no deploy waiting on Mark's side. ## What's not built yet - 4f 'Email me this estimate' PDF + Zoho lead capture (bigger scope, needs Zoho custom-field decisions) - 4g 'Have an actual quote?' upload form (same) - 4h remaining events (pdf_requested, quote_submitted, cta_launch_clicked) - Content.One panel content (flagged in brief as 'pending a decision on your side') Sanity: JSON parses cleanly on the Sitecore page.
Comment on lines
+210
to
+211
| l.innerHTML = '<input type="radio" name="edition" value="' + ed.id + '"' + (ed.default ? ' checked' : '') + ' />' | ||
| + '<span class="block text-sm px-4 py-3 rounded-lg border border-gray-300 text-gray-700 transition">' + ed.label + '</span>'; |
Comment on lines
+219
to
+220
| l.innerHTML = '<input type="checkbox" name="addons" value="' + a.id + '" />' | ||
| + '<span class="block text-sm px-4 py-3 rounded-lg border border-gray-300 text-gray-700 transition">' + a.label + priceHint + '</span>'; |
Comment on lines
+364
to
+371
| breakdown.innerHTML = rows.map(function(r){ | ||
| return '<tr class="border-t border-gray-100">' | ||
| + '<td class="p-3 font-medium text-ink">' + r.label + '</td>' | ||
| + '<td class="p-3 text-right">' + fmtK(r.lo) + '</td>' | ||
| + '<td class="p-3 text-right">' + fmtK(r.hi) + '</td>' | ||
| + '<td class="p-3 text-xs">' + srcLinks(r.sources) + '</td>' | ||
| + '</tr>'; | ||
| }).join(''); |
Comment on lines
+377
to
+382
| formulas.innerHTML = '' | ||
| + '<p class="mb-3"><strong>Subscription (year 1)</strong>: band [' + fmtRange(band.license) + '] × licence multiplier [' + edition.licenseMultiplier.low + '–' + edition.licenseMultiplier.high + '] × editor factor for ' + lo.editorBlocks + ' block(s) = ' + fmtK(lo.lic.y1) + '–' + fmtK(hi.lic.y1) + '. Uplift ' + CFG.upliftPct + '% applied in years 2 and 3.</p>' | ||
| + '<p class="mb-3"><strong>Implementation (year 1)</strong>: ' + (state.situation === 'renew' ? '$0 on renewal.' : state.implementation + ' model at ' + state.sites + ' site(s) = ' + fmtK(lo.impl.y1) + '–' + fmtK(hi.impl.y1) + '.') + '</p>' | ||
| + '<p class="mb-3"><strong>Front-end hosting</strong>: band range ' + fmtRange(band.hosting) + '/yr, no uplift = ' + fmtK(lo.host.total) + '–' + fmtK(hi.host.total) + ' over 3 years.</p>' | ||
| + '<p class="mb-3"><strong>Maintenance</strong>: ' + fmtK(lo.mAnnual) + '–' + fmtK(hi.mAnnual) + '/yr. ' + (state.situation === 'new' ? 'Years 2 and 3 only for new purchases.' : 'All three years for renewals.') + '</p>' | ||
| + (state.addons.length ? '<p class="mb-3"><strong>Add-ons</strong>: ' + state.addons.length + ' selected, priced ones sum to ' + fmtK(lo.addons.y1) + '–' + fmtK(hi.addons.y1) + '/yr.</p>' : '<p class="mb-3"><strong>Add-ons</strong>: none selected.</p>') |
|
|
||
| // Notes + accurate as of | ||
| var notesEl = root.querySelector('[data-cpe-notes]'); | ||
| notesEl.innerHTML = CFG.notes.map(function(n){ return '<li>' + n + '</li>'; }).join(''); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Short-and-sweet page shells per kaya's 2026-09-11 brief. She said "keep the pages short and sweet until then" — Wordify copy incoming in the next few days. The estimator, JSON-LD, sitemap/llms entries, and nav/footer additions are deferred for follow-up phases.
Files created (folder-based clean URL pattern, matches /solutions/ + /features/)
Hub —
webengine/views/page_html/cms-pricing/index.html/cms-pricing/Vendor pages —
webengine/views/page_html/cms-pricing/{sitecore,adobe-experience-manager,contentful,optimizely-cms}.html/cms-pricing/sitecore/etc.Each vendor shell contains
[Vendor] pricing in 2026+ intro +Last updated: September 2026<time>linehow vendor prices,cost breakdown,worked example,what pushes the price up,Content.One for the same setup(with 3-logo proof block), FAQHub shell contains
Last updatedWhat's NOT in this PR
For
/cms-pricing/[vendor]/URLs to route, a parent templateset needs to exist in the Zesty editor namedcms-pricing. Same pattern as the solutions/features/industries templatesets.Once the templateset exists, the 5 shell files auto-create as
ajax-jsonchild views via sync-to-zesty on the next stage merge (per the auto-create flow shipped in PR #100). Drop the templateset ZUID here after creation and I'll wire it intozesty.config.json.Alternative if the templateset takes a beat: I can convert these to root
.htmlfiles (e.g./cms-pricing-sitecore.html) so they resolve immediately at slightly different URLs. Just say the word.Preview
The pages won't preview at their intended URLs until the templateset exists. Once wired, they'll show at:
https://hj5v68xn-stage.webengine.zesty.io/cms-pricing/?zpw=bobbyhttps://hj5v68xn-stage.webengine.zesty.io/cms-pricing/sitecore/?zpw=bobbyhttps://hj5v68xn-stage.webengine.zesty.io/cms-pricing/adobe-experience-manager/?zpw=bobbyhttps://hj5v68xn-stage.webengine.zesty.io/cms-pricing/contentful/?zpw=bobbyhttps://hj5v68xn-stage.webengine.zesty.io/cms-pricing/optimizely-cms/?zpw=bobbySanity checks (once wired)
/cms-pricing/shows the hub with 4 live vendor cards/content-operations-maturity-audit/andlaunch.content.one