Changelog
All notable, user-facing, technical, security, and infrastructure changes are recorded here. Update this file as part of every deployment.
[Unreleased]
Deploy — 2026-08-09
Staging (npm run deploy:staging) and production (npm run deploy:prod).
Added
- Default Open Graph image (
/assets/images/og-default.jpg, four-panel people/devices banner) for social/messaging link previews and search snippets; set as Sanity defaultOgImage with a build-time fallback so og:image is always emitted. - Refund Policy page at
/refund-policy/ (last updated June 10, 2026): standalone non-refundable payments policy (aligned with Terms section 2), linked from the main footer, landing footers, Terms of Service, and llms.txt.
Fixed
- FAQ mobile topic dropdown: open menu stacks above accordion cards (no more options mixed into question rows).
- Case studies carousel (desktop): “Read the full story” (and media link) navigate to the case study again — swipe gesture capture no longer starts on CTAs/links with a fine pointer; inactive peek slides no longer intercept those clicks.
- Case studies carousel (mobile): header spacing — gap between title and arrows tightened, space restored between arrows and the card, and prev/next button gap reduced.
- Case studies carousel: mobile prev/next arrows restored; swipe works from text, CTA, and media areas.
- Social-only platform labels: tapping a supported-platform icon on mobile now shows the name (sticky
:hover no longer overrides the active state). - Blog “Updated” dates:
formatDate now uses America/Toronto for full ISO timestamps so evening Eastern edits no longer display as the next UTC calendar day. - Examples of our work marquee: replaced bright white card loading flash with a dark placeholder + soft shimmer, then fade-in when each image/video paints.
- Refund Policy URL: removed stale 301 redirects (
firebase.json, firebase.staging.json, _redirects) that sent /refund-policy/ to Terms of Service, so the standalone page can load. - Marketing glossary singles: bottom section padding matches content hub / video episode pages.
Changed
- Testimonials cards: stars and quote stay at the top; name/avatar/title pin to the bottom so short quotes don’t leave uneven empty space.
- Testimonials: when a client has no photo, show a circular placeholder with their first initial (e.g. “J”) instead of leaving an empty gap.
- Examples of our work: replaced POV Sunday posting-stress meme creative (social media management Images tab + marquee) with the updated lime-green post artwork.
- FAQ copy: onboarding questionnaire described as detailed (not short); Scale and Elite called out as plans when explaining free platform slots.
- Pricing add-ons: LinkedIn Authority format icon uses the same beige/brown badge as other format icons; Email and Blog Posts use +/- quantity counters (2/4/6) instead of dropdowns; included Instagram/Facebook platform cards use eyebrow beige instead of dark brown fill.
- Social-only landing: removed arrow from Book a demo CTA.
- Social-only CA landing removed:
/social-only/ca/ no longer ships a separate page (stale build output pruned). Old URLs still 301 to /social-only/. - Home “How to get started”: step 2 focuses on brand discovery; step 3 covers review/approve, monthly reports, and hands-off marketing (social posting emphasis instead of website freshness).
- Case study plan card: bumped add-ons heading, item names, and “Explore add-ons” link from caption size to menu size for easier reading.
- Case study results: removed star icon from the results heading; metrics show label above value; metric notes render as plain text instead of pills.
- Social media management hero: collage now uses the Examples of our work Images pool (replacing the previous set); nine posts show per load, randomized on each page load.
- Examples of our work: added Addison “Evolve Your Care” and camera-portrait creatives to the social media management Images tab (pillar + city pages).
- Examples of our work: removed Addison “Restore Your Confidence” and “Supplements for Hair Growth” creatives from the marquee, social media management Images tab, and hero collage (pillar + city pages).
- Examples of our work marquee and social media management Images tab: event creatives (Summer Soul / Velvet Rae, private events Toronto, corporate Tech Summit) interleaved with existing posts; filenames omit client brand names.
- Examples of our work marquee: two rows scrolling in opposite directions (top L→R loop, bottom reverse), each shuffled on load.
- Examples of our work: Images / Carousels / Video / Stories mockups shuffle on each page load; marquee gallery continues to randomize (and works with a single track).
- Examples of our work: randomized order of Images-tab creatives (social media management pillar + city pages) and the homepage marquee gallery.
- Examples of our work (Carousels tab): capped desktop mockup width (~240px) so carousel posts no longer stretch full-bleed; mobile cards aligned with Images tab size.
- Examples of our work: removed Groove Festival / Miles Bexley creative from the marquee and social media management Images tab.
- Examples of our work: added XO Creative posts “Own your email list. Not the algorithm.” and POV Sunday posting stress meme to the marquee and social media management Images tab.
- Short-form video examples: added
log-off.mp4 on social media management (pillar + city), short-form video expertise pages, and the Examples of our work marquee. - Refund Policy (last updated August 7, 2026): cancellation via Client Portal or account manager; takes effect at end of current billing cycle with service/access through the paid remainder; no prorated refunds.
- Footer: CTA label is “Book a Demo”; legal links (Privacy, Terms, Refund, Accessibility) use a smaller type size.
Deploy — 2026-07-26
Staging (npm run deploy:staging) and production (npm run deploy:prod).
Changed
- Terms of Service (last updated July 26, 2026): inactivity after 30 days proceeds to next month’s posts without auto-approval; content calendar is not resent for client approval after 30 days of delayed communication; remakes not provided for uncommunicated business-direction changes; one legally registered business per plan (each additional business requires its own plan); communication guidelines drop “live” from in-person meetings.
- Terms of Service (last updated July 26, 2026): short-form video defined as up to 60 seconds (removed 15-second minimum and custom-quote language); monthly reporting ownership clarified (software, dashboards, templates, workflows, methodologies); report-data license no longer claims anonymized/non-identifying metrics.
- Pricing add-ons: platform and post-format cards stack icons above titles; Short-Form Video format card lists YouTube Shorts among supported platforms; shared platform/format/ads card includes for pricing and social embed.
- Pricing add-ons: post-format icon wash uses brown theme (LinkedIn Authority remains brand blue); add-ons section bottom padding removed to tighten spacing before FAQ.
- Pricing add-on copy: Platforms — “Select additional platforms for $20/month each.”; Post formats — “Add extra post formats to your monthly plan.”
- Mobile nav CTAs: Pricing is outline (no arrow); Book a demo is the dark solid primary button.
- Short-form video FAQ: included videos are up to 60 seconds long.
Security
- Terms reinforce that access to monthly reports does not grant rights to proprietary reporting tools, templates, workflows, or methods, and prohibit copying or sharing them with third parties.
Staging deploy — 2026-07-25
Staging channel only (npm run deploy:staging). Production hosting was not updated.
Fixed
- Staging/prod deploy isolation:
deploy:staging no longer redeploys the shared live protectedSite function. Staging now uses protectedSiteStaging + functions/site-staging and firebase.staging.json (hosting channel rewrite). Live site updates only via deploy:prod → protectedSite + functions/site. Bare deploy:functions is blocked; deploy:hosting aliases to deploy:prod.
Security
- Staging and production static trees are isolated (
functions/site-staging vs functions/site) with separate Cloud Functions so a staging deploy cannot overwrite live HTML/assets served on production domains. Deploy script asserts staging commands never target live hosting or protectedSite.
Changed
- Terms of Service (last updated July 24, 2026): clarified onboarding & first delivery (10-day clock), delayed-onboarding behavior, deliverable definitions (Stories, LinkedIn authority; short-form video 15–60s), and related service terms.
- Privacy Policy: contact section no longer hard-links Client Portal / booking URLs in that block.
- Social media management / city landings: shared “Platforms we support” and social-only landing data modules; refreshed example work imagery; clearer monthly reporting copy.
- Pricing: multi-platform posting tooltip on plan features; LinkedIn Authority Posts format add-on (2 / 4 / 6 posts).
- FAQ: multi-platform publishing and caption-consistency answers; LinkedIn authority listed under format add-ons; shortened social-only plan FAQ.
- Lighthouse / performance: enable gzip compression for static assets in
protectedSite, remove unused global Lottie script, defer non-critical icon/font stylesheets, and load GTM after idle to reduce render-blocking work. - Home “How to get started” review mockup: shows 4 posts; inactive status reads Revision requested, approved rows show a checkmark with Approved; removed redo icon buttons; onboarding progress fill uses brand blue (
--blue-600). - Footer (mobile): tightened vertical spacing in the copyright / legal links block.
Fixed
- Accessibility: decorative get-started plan mockup tabs no longer use focusable
<button> elements inside aria-hidden containers.
Added
- LinkedIn Authority Posts pricing add-on ($49 base for 2 posts/month; 4 and 6 scale in the UI).
- Shared
_data/lib/socialMediaPlatformsSupport.js and _data/lib/socialOnlyLandingData.js as the source of truth for pillar, city, and social-only pages. - City landing pages for affordable social media management (
/social-media-management/<city>/). 16 localized pages (Toronto, Vancouver, Montreal, Calgary, Edmonton, Ottawa, New York, Los Angeles, Chicago, Houston, Miami, Atlanta, Dallas, Seattle, Denver, San Diego) built by pagination over _data/socialMediaCities.js, reusing the existing expertise layout and design system (pink accent, hero, stats, platforms, how-it-works/comparison, FAQ). - Locations index at
/social-media-management/locations/ listing every city in a grouped (Canada / United States) card grid. - Footer link ("Social media by city") and
llms.txt entry for discovery/AEO.
SEO / AEO
- Per-page unique meta title + description and canonical URL.
- Structured data per city:
Service (with areaServed City → State/AdministrativeArea → Country and an Offer at $99 USD), BreadcrumbList, auto FAQPage (city-specific + shared questions), and WebPage (mainEntity → Service). Validated by the existing audit:structured-data script. - Concise, extractable "direct answer" section near the top of each city page for answer engines.
- Localized, non-duplicative copy per city (local market context, industries served, neighborhoods, an area-specific FAQ) to avoid thin/duplicate content, plus internal links to the pillar page, pricing, comparison, and sibling cities.
- New pages are automatically included in
sitemap.xml.
Technical
- New files:
_data/socialMediaCities.js, social-media-management-locations/{index.njk, city.njk, city.11tydata.js}. - Scoped CSS added to
css/styles.css (.sm-locations, .sm-city-answer, .sm-city-local, .sm-city-links) using existing design tokens only.
Security
- No new user input, forms, endpoints, secrets, or third-party scripts were introduced; pages are statically generated. City content and JSON-LD are built from trusted in-repo data (no untrusted/user-supplied data rendered).
Fixed
- Brand videos tab on
/brand-photo-video/: replaced broken Wistia embeds (media IDs e2vc9156k4 and sf37r7i64u returned "This video is unavailable" — they never existed in the account) with a self-hosted HTML5 <video> player served from the existing media CDN (5-phase-treatment.mp4). Removed the empty/corrupt 5-phase-trichology-treatment.mp4 reference (0-byte file) and the unusable second thumbnail; the tab now shows a single working, centered player. Removed the now-dead Wistia thumbnail-switcher JS in js/main.js.
Security (fixes)
- Reduced third-party surface by removing the external Wistia iframe embed in favor of first-party video hosting. Native
<video> uses controlslist="nodownload"; no user input, secrets, or new endpoints are involved (static markup only).