Replace hero text unit with autoplay promo video
Swap the homepage hero copy, CTAs, and stats for a looping muted video while keeping the rotating background treatment.
Lift icon contrast where the mark sits on a tinted bubble
The reported case is the brand green on a tint of itself: --color-primary against rgba(107,142,58,0.15) is 3.43:1. That clears the 3:1 WCAG 1.4.11 floor for gra...
Add the 25-year anniversary seal
Two placements, both chosen for where the claim is already being made: Footer — 60px, beside "© 2001–<year> ... established 2025". Site-wide, ...
Show the 2001 copyright range and the incorporation year
Renders "© 2001–<year> KamoCRM. KamoCRM Inc. established 2025. All rights reserved." The range start is hard-coded next to the dynamic end year rather than livi...
Add the meeting and payroll integrations
Zoom and Microsoft Teams for meetings, and the ten payroll vendors — ADP Workforce Now, BambooHR, Dayforce, Gusto, Paychex Flex, Paycor, Paylocity, Rippling, UK...
Count apps and integrations separately with real numbers
"Apps & Integrations" was one tile reading 31+. It is now two, each with a figure that can be re-derived rather than estimated: Apps 64 — Forgejo pro...
Reset the home headline on a display face and one light pass
The h1 stacked four effects: a fade wrapper, mouse parallax on each line, per-character 3D rotation on line one, and a blue/purple/green gradient cycling across...
Read the org's real background count and play order
The hero probed for bg/1.webp and then hardcoded three frames, so an org with more never showed them and the rotation modulo'd by LOCAL_BGS.length regardless of...
Locale-correct structured data, and a robots.txt rule that matched nothing
Every BreadcrumbJsonLd and ItemList URL was hardcoded to /en, so the structured data on /fr/terms told crawlers its breadcrumb parent was the English page — 19 ...
Index the collection detail pages in 19 more languages
The sync finished, so the ~2,400 detail pages that were noindexed for having English body copy now have real translations and can be indexed. Measured across al...
Stop advertising ta as a translated alternate
Key coverage is not translation. TranslateService returns the source text when no provider supports a direction — ProviderRouter logs "No provider supports en->...
Localize the hub cards and stop bundling the English datasets
The four hub pages rendered client components that imported the collection modules directly and took no props, so every card — industry names, integration tagli...
Translate the collection pages instead of hiding them
The 2,400 noindexed detail pages were noindexed because their body copy has no translation: competitors, industries, integrations and glossary keep their prose ...
Stop canonicalizing 21 translated locales into English
Every non-English page carried a hardcoded canonical to its /en twin — `export const metadata` is module-level, so it could not vary by locale and 28 pages ship...
Derive the add-on unit from the catalog, and correct stale prices
The storage add-on advertised as "+$4 /user/month" for a pool the same page called organization-wide. Cause: mapAddOns matched addonCode "additional_storage" wh...
Render Contact sales for add-ons with no list price
PageAddOn.price was typed number and built with Number(addon.pricePerUnit), so an add-on with no list price — the enterprise-negotiated origination systems — re...
Stop the runtime theme sheet whitening the canvas on light-mode machines
DynamicMetaLoader appends theme.<domain>/css/globals.css to <head> after our own stylesheet, and that file still carries create-next-app boilerplate: :root{--ba...
Submit the lead at step 1 instead of only on booking
handleFormSubmit checked the *** and advanced the step — it made no network call at all, so the contact details a visitor typed were only ever persisted if they...
Remove design-partner program page and links — no free-usage giveaways
Slug map in a plain module — client-reference proxy made server metadata render Article Not Found
500s on dynamic-segment pages + en fallback for missing locale keys
Removing the global force-dynamic made routes with generateStaticParams attempt static rendering for on-demand params, which throws DYNAMIC_SERVER_USAGE because...
Phase 3+4 — convert the traffic that already arrives
- changelog (#2 destination) gets a conversion block; careers shows the honest no-openings state - /subscribe page: post-registration plan intent lands somewher...
Related-content modules + signup CTA retargeting on programmatic templates
Solutions, integrations, alternatives, and glossary templates were organic dead ends: no internal related links and "Start free" CTAs pointing at /pricing inste...
Phase 0+1 — instrument the real funnel, unblock first paint
- forward data-* props through MagneticButton/RippleButton (events never reached the DOM) - instrument SharedNavigation, Hero, PreviewBanner, section CTAs; ?ref...
Commit outstanding work in progress
Staged and committed as-is so nothing is left uncommitted in the working tree. 4 files changed, 72 insertions(+)
Harden the kubectl download against flaky egress [skip ci]
dl.k8s.io over the runner's egress intermittently drops mid-transfer: curl: (56) OpenSSL SSL_read: decryption failed or bad record mac which fails the deploy ...
Starter capped at 5 users, Business at 25
Repositions the published seat caps on /pricing (and the calculator, JSON-LD offers, and llms.txt summaries) to match the subscription catalog: Starter 25 -> 5 ...
Replace forked chat with hosted <kamo-chat> embed; delete legacy proxy widget
Swaps the forked AI/live-support React chat (PublicChatWidget + AiChatPanel + LiveSupportPanel + the /api/chat/** server proxy routes) for the hosted, self-them...
Distinguish actively-translating vs queued messages
The translation queue was already sequential, but every queued bubble rendered "Translating…". Now the single in-flight message shows "Translating…" with a puls...
Show error icon when a message fails to translate
When the per-message translate call returns translated:false, errors out, or times out, the chat bubble now renders an AlertTriangle icon in red with tooltip "F...
Stream translations newest-first for visitor history
When the visitor lands on a non-English locale and the support chat has existing English messages, every bubble flagged needsTranslation by the backend now show...
Auto-translate visitor and agent messages
Live agent replies arriving in a language other than the visitor's URL locale now show a "Translating…" bubble while the TranslateService call resolves, then sw...
Move translations to kamo-translation-dictionary
All 22 locale files move to the centralized kamo-translation-dictionary repo. The CI now clones that repo and copies the kamo-marketing/ folder into messages/ b...
Scope concurrency to build jobs, not Kubernetes deploys
Workflow-level concurrency serialized the whole pipeline (including kubectl rollouts). Move the group to the build job only so deploy jobs from different runs c...
Periodic STOMP presence heartbeat for public support
Refresh Redis TTL for public session presence so agents see accurate online state.
Show active offer banner with live millisecond countdown
Fetches the active promotion server-side on the home page and renders a HeroOfferBanner between the subheadline and the free-forever callout. The banner shows t...
Drive minimized-tab entry through animation controls
Switching animate={...} to animate={tabControls} broke the entry animation: tabControls has no queued target on mount, so the button stayed at its initial { y: ...
Live unread badge + bounce on new agent message
- Keeps LiveSupportPanel mounted offscreen while the widget is minimized (only when a support session exists) so the STOMP subscription stays alive and onUn...
Remove SSR guard causing hydration mismatch; drop SockJS for native WebSocket
- Hero.tsx: remove typeof window check around ParticleField — ParticleField already has ssr:false so the guard produced a server/client tree mismatch (React #...
Use /public/{mainDomain}-{tld} path matching actual MinIO bucket layout
The getThemePath() was generating /domain/{tld}/{split}/kamosite paths that don't exist in MinIO — theme files live in the public bucket under kamocrm-com/, bad...
Add suppressHydrationWarning and fix broken placeholder images
suppressHydrationWarning on <html> prevents React error #418 caused by browser extensions (e.g. translate, dark mode) mutating html attributes between SSR and c...
Remove duplicate connectStomp call in sendMessage
When the first message creates a new session, onSessionCreated updates props which triggers useEffect to call connectStomp. The inline call in sendMessage was r...
Remove kamo-capcha-widget node_modules from repo
Drop tracked files under **************** so the tree matches a clean install (dependencies belong in package lock, not git).
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.