Commit Graph
279 Commits
Author SHA1 Message Date
Matthew Meszaros 0334d2c64a feat: prevent ResizeObserver feedback warnings from reaching PostHog and scope worker outage alerts per workspace on shared cloud workers 2026-09-16 17:42:38 +02:00
Matthew Meszaros ae012dd13f Clear the live error-tracking issues, and the workspace rename that renamed the wrong workspace (#533)
* feat: stop a managed Kafka cluster refusing topic creation from failing the publish, by treating a topic- or cluster-authorization failure from CreateTopics as a topic the cluster owns rather than one that is missing, which on Confluent Cloud dropped every warmup event and filed one issue per message because the topic never became known

* feat: drop a report whose error is a cancelled context in errs rather than at ninety call sites, so a browser navigating away or a container draining on deploy stops filing one issue per query that happened to be in flight, while a deadline this process set and blew through still reports

* feat: stop renaming one workspace from renaming another, by keying the workspace settings editor on the workspace id so a switch re-seeds the name field instead of leaving the previous workspace's name against the new workspace's autosave baseline, and pinning every save on the workspace, sending and tracking pages to the workspace its draft was hydrated from

* feat: drop Script error. and the ResizeObserver notice on the marketing site and the hosted form page the way the dashboard and admin panel already do, since those two carry no stack and no bug and between them were the largest issues in error tracking, all of it from warmbly.com

* feat: rename the forms Turnstile script module to turnstileScript.ts so it no longer differs only in case from the Turnstile.tsx component, which resolved both imports to one file on a case-insensitive filesystem and failed forms' typecheck with TS1149

* feat: upload source maps from the static build:pages build as well as the image build, so the dashboards served from a static host stop reporting every stack frame as a minified name beside 'Invalid source map: bad json', which is PostHog falling back to fetching the .map from a host that answers with its SPA fallback

* feat: build every admin list in pg_admin.go with make rather than declaring it nil, so an empty page serializes as [] instead of null, and guard the audit table's own empty check, which is what crashed admin.warmbly.com/audit with 'null is not an object (evaluating d.data.length)' whenever a filter matched nothing

* feat: match the whole broker description rather than a substring when deciding a topic create was refused for permissions, since that answer remembers the topic as present, and clear the cached promise and dead tag when the forms Turnstile script fails to load so a blocked first attempt no longer leaves every later mount with the same rejection and the captcha permanently missing
2026-09-15 09:05:53 -07:00
Matthew Meszaros b9a98cef8f feat: rebuild the unified inbox as three columns with no metric strip, a flattened scope rail with one row language and bare counts, three-line conversation rows carrying an unread dot in the gutter instead of an avatar and bar, a subject-first thread header with icon-only actions, a filter popover that applies on the spot and shows each added filter as a removable chip that never repeats what the current view already fixes, and real loading throughout: a delayed progress bar over dimmed stale rows, row-shaped skeletons for first load, next page and the thread reader, and optimistic row removal so archive, delete and snooze land instantly 2026-09-14 08:26:03 -07:00
Matthew Meszaros c28f915648 feat: erase everything a disconnected mailbox leaves behind, revoking its OAuth grant at Google and deleting its stored message bodies through a durable retried queue, cascade the nine mailbox foreign keys that had none so warmup receipts, tampering events and provider message maps stop outliving the mailbox, clear thread labels and snoozes on conversations the delete emptied, make workspace deletion possible at all by cascading the four organization foreign keys with no delete action, and put Disconnect in the mailbox row menu and a Settings danger zone since it was only reachable from the selection bar (#506) 2026-09-14 07:55:01 -07:00
Matthew Meszaros d74d5e6836 fix: retire the warmup spam score, a counter that grew with volume rather than misbehaviour and that no band could act on (#508)
* fix: retire the warmup spam score, a ratchet that grew with volume rather than misbehaviour and that no band ever read, dropping the column from the pool row and the reputation ledger and explaining a pool finding with the band's own reason instead (#491)

* test: pin the advisor snapshot's pool columns against the scan, since the band's reason now reaches the finding through that select alone (#491)

* fix: hold a warmup sentence's score and reason with the sentence itself, keep the retired spam_score key on the published analytics payload as a deprecated zero, seed the sandbox with severity-shaped scores, and record the raw spam report when the warmup service is absent (#491)
2026-09-14 07:44:34 -07:00
Matthew Meszaros 40506c4f05 fix: seed the two warmup pools on every instance under fixed ids and make one pool per type structural, since the baseline squash dropped the insert and a fresh self-hosted instance never warmed; move memberships onto the canonical pools, scope the standing mirror trigger to the columns it mirrors so a pool move keeps a retention window, commit the runtime and every seeder to the ids through MoveToPool, assert the pools at boot and in a warmup_pools_missing health check, and drop the guide's claim of cross-tier borrowing the health gate rejects (#493) 2026-09-13 21:37:17 -07:00
Matthew Meszaros 7300b3b021 feat: full PostHog coverage: identify the signed-in user and workspace in the dashboard and admin panel with autocapture, heatmaps, dead and rage clicks, web vitals, network timing, console capture and session replay masking only password fields, send server-side signup, trial and subscription events under the user id with the organization as a group, keep the marketing site and form pages cookieless while capturing everything stateless plus a form funnel, upload the form app's source maps, and add WARMBLY_POSTHOG_SESSION_REPLAY 2026-09-13 20:58:22 -07:00
Matthew Meszaros 6b6efca865 fix: campaign follow-ups opened a new conversation instead of replying in the contact's thread, so carry In-Reply-To/References and the Gmail threadId from the previous send, give every step a reply-in-thread switch, and let a threading step inherit the conversation's subject (issue #472) (#489) 2026-09-13 20:51:41 -07:00
Matthew Meszaros 1dc4aedc3c fix: retire the warmup invalid-token band with its table, metric query, service and repository methods and admin tab, since nothing has fed it since #481 and no attributable forged-token signal exists; key the live pool fixtures on the canonical pool ids so the warmup, repository routing and tasks routing suites run on a fresh database, and correct every doc, site and advisor line that still described the retired signal or a spam-score threshold nothing implements (#490) 2026-09-13 08:09:01 -07:00
Matthew Meszaros 8799680166 fix: never charge a mailbox for a warmup token that arrived in its inbox, hold a quarantine or block for its full term against fresh metrics, and keep a penalised address's standing across removal, pool exit and export through a trigger-maintained mirror, since the recipient never controlled the token, the bands read seven days against 30-day terms, and the pool row died on paths a snapshot at deletion never saw (#481) 2026-09-13 04:34:44 -07:00
Matthew Meszaros 55d712579b feat: collapse the left navigation to an icon rail, drag the unibox conversation list against the thread, and remember the contact rail toggle instead of reopening it on every conversation (#479) 2026-09-13 01:09:29 -07:00
Matthew Meszaros 9ce576bb3f feat: rebuild the marketing contact page as a minimal list of real channels (team@warmbly.com, the Discord, GitHub issues and discussions, docs, status) and the Mindroot Ltd registration, dropping the invented Delaware entity, postal address, team locations, business hours and SLA 2026-09-12 03:02:57 -07:00
Matthew Meszaros 170c33780a feat: pass ui_host to PostHog in the dashboard, admin panel and marketing site from its own environment variable so a proxied api_host stops breaking toolbar and session-replay links, which the SDK builds against whatever it sends events to and which a reverse proxy does not serve, defaulting to us.posthog.com so an install that does not proxy is unaffected 2026-09-11 11:34:02 +02:00
Matthew Meszaros ced741e352 feat: make PostHog the default error tracker across every runtime while keeping Sentry fully supported alongside or instead of it, by turning internal/observability/errs into a two-sink fan-out with a local-log fallback, adding $exception capture to the Go services, the Rust tracking service, the Elixir realtime service and the dashboard, admin and form apps, reporting gin panics with their route, request id, workspace and user, attaching that identity plus a route and failed-request trail to browser exceptions, and wiring POSTHOG_ERROR_TRACKING, the node join env, compose, source-map upload and the docs to match 2026-09-10 19:11:32 +02:00
Matthew Meszaros 68b5d8f358 feat: bind a campaign lead to the mailbox that sends its first email so every follow-up leaves from the same address, holding a lead back while its mailbox is merely out of budget or outside its hours and moving it to another mailbox only when that one can no longer send for the campaign at all 2026-09-09 08:51:00 -07:00
Matthew Meszaros 435dbb522f feat: replace the worker tier/type/risk-pool/egress categories with a scored placement model and make the fleet pull-based, so a machine joins with one command, workers and consumers share one node registry with usage and liveness, nodes self-update to the version the control plane resolves, and the Hetzner provisioning, worker profiles and SSH orchestrator are removed 2026-09-09 04:54:01 -07:00
Matthew Meszaros 156a90c39a feat: default every PostHog capture host (site build, dashboard runtime, backend analytics client) to PostHog Cloud US instead of EU, and update the configuration docs table, since the customers are primarily US-based 2026-09-07 20:28:31 -07:00
Matthew Meszaros 26c88d2426 feat: address the CodeRabbit review on the PostHog PR by dropping a referrer that is not a hostname instead of storing its query string or fragment, redacting email-shaped values out of every acquisition field before they reach the database or an analytics property, counting an invited signup which returned before the count was taken, hanging subscription_started off the persisted trial-to-paid transition so a redelivered webhook cannot report a second start, capturing the validated provider in both OAuth mailbox paths including Warmbly Cloud, making the two acquisition toggles mutually exclusive and naming them after what they actually select, and replacing the unsupported CNIL consent-exemption claim with what the guidance says and an explicit note that qualifying is a deployment-specific assessment this document does not make 2026-09-07 05:45:11 -07:00
Matthew Meszaros b27e261a08 feat: defer the marketing site's CTA attribution script until the document is parsed, because it runs from head where the register links it rewrites do not exist yet, and verify against the real built pricing page that all six links carry the UTM parameters, the landing path and the referrer host while the login links are left alone 2026-09-07 04:24:04 -07:00
Matthew Meszaros 8e9f67f46b feat: add cookieless PostHog analytics for the hosted marketing site and dashboard with server-side signup and subscription events, a first-party acquisition record written once at signup on a new organization_acquisition table registered in the org-transfer spec, an acquisition column and channel filter in the admin org list, and never a single request from a self-host because every key is unset by default 2026-09-07 04:18:33 -07:00
Matthew Meszaros 04a2ed59c9 feat: address the CodeRabbit review on the lead-intake PR by giving the webhook sink its own copy of every map payload so the automation goroutine never writes into the map still being marshalled for endpoint delivery, propagating contact lookup errors in the upsert action's skip mode and in the native actions adapter so a failed lookup is never mistaken for a missing contact, adding the contacts source CHECK as NOT VALID in migration 000129 to skip the table scan under the migration lock, defaulting a new create-or-update-contact node's email template to the address key the chosen trigger actually carries, correcting the n8n guide on which lead-form sources have a trigger node, naming API batches over 100 contacts among the silent bulk arrivals in the contacts guide, and updating the marketing automations page from nine to twelve triggers 2026-09-06 00:47:33 -07:00
Matthew Meszaros a3989f9d9c feat: turn automations into a lead-intake path so a Facebook, Instagram, LinkedIn or TikTok lead form pushed by Zapier, Make, n8n or any webhook becomes a tagged, campaign-enrolled contact without leaving Warmbly: add the warmbly.upsert_contact and warmbly.add_to_campaign built-in actions with templated field mapping, custom fields, tags, campaign and an if-exists policy, fire a rich contact.created event from the one contact write path (silent for file imports, sheet syncs and API batches over 100) and expose contact.created and form.submitted as automation triggers with condition fields, variables and sample data, carry an automation depth through events raised by an action so a flow that creates a contact cannot re-trigger itself past five hops, stamp automation-created contacts with the new automation source (migration 000129), share the campaign picker between the sheet sync wizard and the automation builder, document lead intake in the automations, Zapier, Make, contacts, forms, integrations, expressions and webhook pages plus a new n8n guide, mirror the new triggers and actions on the marketing automations page, and drop the 34 MB cli binary that was committed by mistake 2026-09-06 00:36:05 -07:00
Matthew Meszaros 3596a9770f feat: make mailboxes truly unlimited under a fair-use allowance of one mailbox per daily send the plan includes (15,000 on Business), drop the 200 hard cap and the 5-per-day connect throttle, open a request-more dialog with inline limit requests and plan upgrade when the allowance is reached, add bulk CSV mailbox import with live progress and a downloadable failed-rows file, reserve attachment storage atomically under a per-org lock so concurrent uploads cannot pass the quota (#326), report storage and the allowance on the billing usage meters, and honor approved daily-send overrides in the sender 2026-09-04 21:00:26 -07:00
Matthew Meszaros aba176f8aa fix: never highlight a plan at or below the workspace's current one, so an Enterprise customer is no longer shown Business as the best value, and stop the agencies page promising each client its own machine and IP now that the FAQ states we do not sell or manage IPs as a product 2026-09-04 09:20:33 -07:00
Matthew Meszaros d78e4423e4 fix: address the review of the notifications work — bound detached alert delivery to a fixed pool that drops and logs rather than spawning a goroutine per event, never echo a transport error that embeds the webhook URL, treat an emptied channel target as cleared so switching transport cannot post Slack payloads to a Discord URL, emit user.registered for invited signups and the worker alert after a successful reassignment, format Stripe amounts by currency exponent, refuse an upgrade while the plan list is still loading instead of silently opening the portal, apply a fixed discount to the annual invoice rather than to each month, convert proration from minor units, contain focus in the nested enterprise dialog, hide the odometer wheels from assistive tech, and drop the last dedicated-IP row from the pricing matrix 2026-09-04 06:33:20 -07:00
Matthew Meszaros 87ada2c99f feat: drop the purple gradient and indigo plan accents for the app's own slate and sky palette (Business wears sky, Enterprise solid ink, no gradients anywhere), highlight the best-value plan instead of whatever sits one rung up, remove the duplicated capability matrix from Overview and the comparison table from Plans, and stop calling dedicated workers 'dedicated IPs' across the dashboard, docs, pricing page, FAQ and agencies page 2026-09-04 05:11:47 -07:00
Matthew Meszaros 5eb92c601c feat: give every campaign email a working opt-out: a reply-to-opt-out line by default or an unsubscribe link (workspace setting under Settings > Sending with a per-campaign override and a {{.UnsubscribeLink}} variable), signed per-recipient unsubscribe links served on the API origin so the List-Unsubscribe header no longer points at a dead warmbly.com page, a confirm page on GET with RFC 8058 one-click on POST and a resubscribe button, reply opt-out detection through the whole-word compliance lexicon with quoted history stripped, a first-class suppression list (Contacts tab, GET/POST/DELETE /suppressions with address and domain entries, audited removal, contact drawer action), the contact Subscribed flag enforced in campaign routing, migration 000122 with a shared recipient_suppressed() predicate, and docs for all of it 2026-09-03 01:52:40 -07:00
Matthew Meszaros 8da0235155 feat: let the footer's bottom row wrap on phones instead of forcing GitHub, Discord, RSS and Open source onto one line that pushed the page wider than the screen and made iOS Safari scale the whole layout, and clip horizontal overflow at the html and body level so no single overflowing element can widen the page again 2026-09-02 09:13:28 -07:00
Matthew Meszaros 15d9f22659 feat: make phones show the same product visuals as desktop: every feature window is the 1280px browser with chrome and app shell at every width, scaled and cropped from the same anchor at the same zoom, with the frame keeping a desktop frame's proportions below lg instead of growing to each mock's content height; the app shell drops its chrome prop and becomes a container query root, and the mocks' responsive classes become @sm/@md/@lg/@xl container variants with viewport units pinned to the 1280x900 app viewport, so a mock renders its desktop state inside the window regardless of the visitor's screen instead of collapsing to phone layouts inside a desktop screenshot 2026-09-02 09:08:56 -07:00
Matthew Meszaros 3ecb25786a feat: register the app shell's visibility observer under reduced motion too so an off-screen shell still pauses its animations while only the counter ticker stays off, and read the ?noshell, ?noanim and ?nogl phone diagnostics as query parameter names through URLSearchParams instead of matching the raw query string 2026-09-02 09:00:29 -07:00
Matthew Meszaros b675b82657 feat: remove the remaining iOS Safari GPU hogs from the index page without changing its look: the app shell's three SkyChrome cloud blurs are baked into one SVG background (public/backdrops/shell-ambient.svg, same shapes, blur radii and opacities) so fifteen shells stop running forty-five live 60-70px blur layers, .round-clip clips with clip-path instead of the translateZ + mask-image trick that forced a 3D layer and a mask buffer on all fourteen frames, a shell that scrolls off screen pauses its pings and pulses, and ?noshell, ?noanim and ?nogl query switches let a phone isolate whichever subsystem is left 2026-09-02 08:54:16 -07:00
Matthew Meszaros f3a4d09f0b feat: release the grain frame's shader mount through dispose(), the method ShaderMount actually exposes, so the WebGL context and canvas are really freed when a frame scrolls out of range instead of throwing on a missing disconnect() and leaking every context 2026-09-02 08:46:01 -07:00
Matthew Meszaros e6d615beb2 feat: stop iOS Safari crashing while scrolling the index page by keeping its GPU footprint bounded: every grain frame's WebGL canvas is now released when it scrolls 300px past the viewport and recreated on approach so the page holds two or three GL contexts instead of nine, phones render the grain at a 1280x720 pixel budget instead of the full 3x device ratio, feature sections a viewport or more away drop their app screens from rendering with content-visibility (display none where unsupported) and refit them on the way back so at most a few of the fourteen scaled windows are composited at once, and backdrop filters inside the scaled app shells are turned off on touch devices where the blur is invisible at that size, with the desktop look unchanged 2026-09-02 08:40:22 -07:00
Matthew Meszaros 454c1391c6 feat: pause the feature carousel's reduced-motion timer while the frame is hovered or off screen and resume it with the remaining hold time, so a slide never advances right after release the way the paused fill animation never does 2026-09-02 06:11:45 -07:00
Matthew Meszaros 37d48baf0b feat: address the CodeRabbit review on the index visuals: the app shells and feature screens are aria-hidden pictures whose buttons, inputs and links leave the tab order and the shell's fake Search control is a span, the CRM board counts and sums open deals per stage and hides the open row at zero like the app's pg_crm summary so the Won column no longer reads 42,000 open, the dashboard stat strip totals agree with the at-risk, failing and paused rows beneath it, the story carousel advances on a timer under reduced motion where no fill animation ends, the forms sparkline gradients are keyed by row index instead of name length so two 17-character names no longer share an id, the unibox reply controls reveal on hover at md and up, the hosted form mock uses paragraphs instead of h1/h2 so it stays out of the page outline, and four stylelint findings in global.css are cleared 2026-09-02 06:04:11 -07:00
Matthew Meszaros 1d626496af feat: rebuild the index page product visuals 1/1 with the dashboard for issue #268: every feature section renders the real app shell (AppShellMock with the live sidebar counts) inside a browser window hung from a corner, a shared demo cursor engine (lib/cursor.ts + DemoCursor) walks element anchors instead of guessed coordinates, the campaign builder opens its step editor as the 320px spring side sheet and portals the ⌘J caret assistant over the whole window, analytics, integrations, developers and CRM use a new wide FeatureSection mode that fits the full 1280px window by width so centred dialogs read as centred, forms, form builder and hosted form mocks replace the AI assistant mock, the hero gets a grain backdrop (@paper-design/shaders) and a three-point free to self-host / 10 mailboxes / no card line instead of the long pricing paragraph, the How we differ section is removed, and a Discord glyph linking to dc.warmbly.com is added to the header, mobile menu and footer 2026-09-02 05:53:04 -07:00
Matthew Meszaros 152f626469 feat: remove the free trial: a new hosted workspace starts on the free plan with no time limit, may hold up to 10 mailboxes (connected directly or through a linked self-hosted instance) and warm them in the free pool, and everything else (campaigns, inbox, contacts, CRM, integrations, API keys, audit) sits behind a Starter lock in the sidebar and a SubscriptionGate overlay until a plan is active; the pool-link allowance now counts every mailbox in the workspace, and the marketing site and guide say free workspace instead of 14-day trial 2026-08-29 08:34:22 -07:00
Matthew Meszaros 37b60b59d3 feat: let a self-hosted instance warm its mailboxes in the hosted pool: device-code link approved at /connect, instance-token API that enrolls SMTP/IMAP mailboxes as warmup-only accounts (no history import, non-warmup mail dropped), free for 10 mailboxes and unlimited on the seeded $15 pool plan, tier fallback to proven healthy mailboxes when a pool runs thin, local warmup stands down for enrolled mailboxes, Settings > Warmbly Cloud step flow and linked-instances page, docs guide, marketing copy, and fix SetWarmupLifecycle re-reading the row with an org-scoped lookup so every warmup start/pause returned 404 2026-08-29 07:09:04 -07:00
Matt 46beea4884 feat: keep cd warmbly in the self-host terminal so make up runs inside the cloned repository instead of the parent directory where no Makefile exists 2026-08-27 16:12:09 +02:00
Matt 932a29cda4 feat: replace the how-we-differ comparison table with six drawn guardrail cards joined into one connected panel like pricing, showing the cap bar, send spacing dots, the 10-vs-80 percent quarantine axis, the warmup staircase, auth check pills and the real CampaignLimitDefault constant, and rebuild the changelog into a plinth release feed on a rail that dissolves off the bottom edge with its columns mirrored against the open-source split below 2026-08-27 16:05:46 +02:00
Matt 4426278f9b feat: redesign the personalization section as a rendered-per-recipient artifact, one template panel beside three recipient results showing the if branch, the else branch and the default fallback with color-coded merge, spintax and fallback spans plus a feature grid covering custom CSV fields with spaces, coercing helper functions, nested spintax, per-step A/B variants, real-engine preview and launch-blocking validation 2026-08-27 15:44:18 +02:00
Matt 13ddfc6607 feat: rebuild the index bento as layered product-UI artifact cards with viewport-gated continuous motion, join the pricing tiers into one connected panel with yearly savings and log-scaled volume meters in place of the dedicated-IPs bullet, redesign the open-source band from the dark cloud gradient into a light repo-browser-plus-terminal plinth, drop the templating section separator borders, and update pool copy so self-hosted instances connect to the shared warmup pool with a free tier 2026-08-27 15:31:00 +02:00
Matthew Meszaros a7518a8558 docs: refresh the documentation site, fix inaccurate claims and contact addresses, add SEO primitives (#90)
* feat: rewrite the self-hosting docs against repo ground truth: turn the deployment guide into a full self-host guide (quick start with first-admin bootstrap via make grant-admin, .env secrets with exact key formats, PUBLIC_HOST derivation and HTTPS reverse-proxy vars, provider switches with build-tag caveats, mailbox OAuth, remote worker enrollment via SSH or wmenroll tokens, real CI image tags, upgrades and backups), rewrite the events page around the real NATS/Kafka bus topics and {type,body} envelopes, fix Kafka-era and make-target claims in architecture/local-development/deploy README, add API_PUBLIC_URL and drop the dead LOG_DISCORD_WEBHOOK_URL in env.example, and remove the docker-compose.kafka.yml comment pointing at a file that does not exist

* feat: make the self-hosting docs visual and skimmable by adding a Mermaid MDX component (client-rendered, theme-aware) to the docs site, condensing the self-host guide around a control-plane topology diagram, a worker enrollment sequence diagram, a dashboard screenshot, and symptom/check troubleshooting + optional-subsystem tables, and adding an execution-plane flowchart to the architecture page

* feat: stop the docs root flashing a 'Continue to the Warmbly docs' link before redirecting by navigating with an inline location.replace that runs during HTML parse, and demoting the visible link and meta refresh to no-JS fallbacks inside noscript

* feat: cut docs bulk and duplication by deleting three orphaned API pages that were stale forks of the reference section and were unreachable from the sidebar (porting their unique social sign-in, promo-code, and referral endpoints into api/reference/account-org.mdx as compact tables), condensing the deliverability and warmup guides to roughly half their length around tables instead of prose, replacing prose em dashes across the guides and MCP pages, and adding the required trailing slashes to internal links in 24 files

* feat: condense the sequences guide by about 40 percent, folding the switch-step deciders and branch conditions into tables and cutting restated prose while keeping every rule about threading, instant branches, reply matching, and stop on reply

* feat: condense the automations, unibox, advisor, and expressions guides by roughly 40 percent each, folding trigger lists, action catalogs, sending controls, and advisor checks into tables, adding a trigger-condition-action flow diagram to automations, and cutting restated prose while preserving every threshold, permission boundary, and rule

* feat: condense the mailboxes, campaigns, analytics, and team-roles guides by roughly 45 percent each, replacing prose walks through providers, rotation modes, lead statuses, counting rules, A/B confidence, and the permission matrix with compact tables and collapsing the four-way role grid into one capability table plus a one-line mapping

* feat: condense the AI-steps, security, and contacts-CRM guides by roughly 40 percent, turning sign-in methods, AI step modes, switch deciders, credit and failure behavior, import field mappings, and deal views into tables while keeping every safety boundary and dedupe rule

* feat: condense the meetings, notifications, AI-credits, and AI-assistant guides by roughly 40 percent, merging notification categories and their defaults into one table, collapsing credit costs, spend controls, and plan allowances into tables, and tightening the assistant page around its approval and permission boundaries

* feat: condense the integrations, collaboration, zapier, and make guides by roughly 35 percent, grouping the thirty-row Zapier and Make action lists into eight labelled areas, folding CRM default field mappings and presence indicators into tables, and promoting the destructive-action and unattended-delete warnings into callouts

* fix: correct three factual errors in the development docs: NOTIFICATION_EMAIL_DAILY_CAP=0 means uncapped rather than disabled (overEmailBudget returns false at limit<=0, so documenting it as a kill switch inverted the behavior), and the worker-SSH and warmup-pool migration citations in architecture.mdx pointed at pre-squash filenames that no longer exist or now belong to unrelated migrations, so both now cite the tables in 000001_baseline.up.sql

* feat: add the missing docs SEO primitives: a build-time sitemap.xml covering all 64 pages, a robots.txt that points at it and keeps the llms.mdx and og mirrors out of the index as duplicate content, and per-page canonical plus richer OpenGraph URL/title/description metadata

* fix: use the single real team@warmbly.com address everywhere a human is told to write in, replacing the invented hello/sales/legal/support inboxes across the marketing site, the transactional email footer, and the admin outreach composer default Reply-To (which pointed replies at a mailbox that does not exist), and collapse the contact page's two-inbox framing into one inbox with one published response time
2026-08-05 10:37:27 +02:00
Matthew Meszaros 14587b9cd1 feat: swap the OG and Twitter social image for the new Social.jpg and update its width and height to 1280x640 2026-07-22 17:05:08 +02:00
Matthew Meszaros 2af4bd084e copy: say largest instead of biggest across the marketing site 2026-07-20 11:21:57 +02:00
Matthew Meszaros 3b3fc0fe62 feat: show the iOS app showcase on the homepage, slotted between the integrations feature section and the automations centerpiece so the sky band breaks up two light sections 2026-07-16 18:43:11 +02:00
Matthew Meszaros c68ee02a20 feat: drive the mobile showcase — scale-to-fit phone stage capped at real-device size, story segments that fill and auto-advance the screens with tap-to-jump, cycling push notifications with long quiet gaps, and an IntersectionObserver lifecycle that pauses everything off-screen 2026-07-16 18:43:02 +02:00
Matthew Meszaros 28830a2718 feat: style the mobile showcase motion — screen slide transitions, status-bar glyph cross-fade, notification drop-in under the Dynamic Island, health-ring and chart draw-in states, phone entrance reveal, and prefers-reduced-motion fallbacks 2026-07-16 18:42:51 +02:00
Matthew Meszaros cc1a35e835 feat: add the MobileAppShowcase section markup — sky band with a story-bar switcher and a bottom-cut iPhone whose Home/Inbox/Campaigns screens recreate the SwiftUI app 1:1 on a 393pt canvas (AirSkyWash hero, gradient-stroke stat chips, health rings, unibox and campaign rows, fixed status bar, frosted notification with the real app icon) 2026-07-16 18:42:37 +02:00
Matthew Meszaros fb5e22030e feat: wire per-post cover frontmatter into the nine remaining blog posts so each renders its own grid thumbnail and og/twitter card 2026-07-07 07:15:06 +02:00