Free Simple Private Ephemeral Obscured
📋
whisperblinks.io

Change log

A running record of what's shipped — new tools, design improvements, and under-the-hood fixes.

  1. New

    JTN IPTV Viewer public project page

    Added /jtn-iptv-viewer, a public software page for the Windows IPTV viewer project from JTN Techs. The page explains lawful Xtream and M3U playlist use, free starter lists, build requirements, source commands, installer ZIP creation, local user data, and the legal-use disclaimer.

    Linked the page from the homepage public-projects section, sidebar, footer, and sitemap.xml, with responsive project-page styling in wwwroot/app.css.

  2. New

    Photo Scrub for private image sharing

    Added /metadata-remover, a no-upload image scrubber for rebuilding JPG, PNG, and WebP files without common hidden metadata such as EXIF, GPS, text, and editing blocks. The page includes search-focused metadata, FAQ content, and a local download flow for the clean copy.

    Registered the tool across ToolManifest.cs, the landing page, /tools, the no-signup roundup, About page, web app manifest, structured data, and sitemap.xml.

  3. Fix

    Clean build warnings and finish the polish queue

    Fixed the remaining build warnings by awaiting QR preset generation in Components/Pages/Qr.razor and removing the unused isInitiator field from Components/Pages/Call.razor. The project now builds without the prior warning noise.

    Added a reusable no-signup internal-link band to Components/Shared/ToolSeo.razor so tool pages point visitors toward the no-signup roundup, all tools page, and /my-items. Improved the empty state in Components/Pages/MyItems.razor with preview cards for Burn Note, Paste Bin, and Wink Links plus clearer next actions.

  4. Fix

    Branded email, Brevo status, and nav audit

    Reworked the session-link email in Program.cs into a branded HTML message with a whisperblinks header, clear open button, raw-link fallback, security note, and the requested footer line. The send endpoint still uses Brevo, but the email now feels like a first-party product message instead of a plain paragraph.

    Updated Components/Pages/Status.razor with an external Brevo health check using the configured BREVO_API_KEY, reporting not-configured, auth-failed, degraded, unreachable, or operational states. Also added /changelog to the sidebar About group and added /approach plus /changelog to wwwroot/sitemap.xml while keeping noindex/status/session pages out.

  5. Fix

    Mobile polish, email feedback, and cleaner builds

    Added shared small-screen rules in wwwroot/app.css for .tool-split, tool headings, URL bars, and session modals so common tool pages fit better on narrow phones. The new rules keep form controls inside their containers and let long generated links wrap instead of forcing horizontal scrolling.

    Updated Components/Pages/MyItems.razor with a lightweight "Recently sent" receipt list for session emails, showing only masked addresses and local send times. Also added .gitignore and removed generated bin/, obj/, and capacitor/ output from Git tracking so builds stop dirtying the working tree.

    Strengthened POST /api/sessions/email in Program.cs with JSON rate-limit responses, a small request-size guard, per-session send limits, and per-recipient daily limits on top of the existing IP limit.

  6. Fix

    Manifest-driven nav and clearer email receipts

    Updated Components/Layout/NavMenu.razor so sidebar tool links render from Components/Shared/ToolManifest.cs, keeping the sidebar aligned with the landing-page tool list. The nav now automatically includes manifest tools like /qr and /screenshare without hardcoding each route twice.

    Improved the session email confirmation in Components/Pages/MyItems.razor so successful sends show a masked destination, such as ja***@example.com, in both the active-session card and the new-session modal.

  7. Fix

    Clearer session-link security copy

    Updated Components/Pages/MyItems.razor with a quiet .mi-session-privacy notice in active sessions, explaining that the session URL is the key to the item list. The new-session modal warning now tells users to treat the URL like a password before they copy, download, email, or open it.

    Added matching styles in wwwroot/app.css so the warning reads as important but not alarmist, using the existing border, accent, and text tokens.

  8. New

    Email option in the new-session modal

    Updated Components/Pages/MyItems.razor so the "Save this URL" state now includes an email field beside the existing copy, download, and open actions. Users can send the just-created session link before leaving the modal, using the same hardened wbSession.emailLink() flow as the in-session email card.

    Added modal-specific styles in wwwroot/app.css under .wb-sess-email, keeping the email affordance compact and consistent with the existing session URL warning.

  9. Fix

    Clearer session email diagnostics

    Updated Program.cs so POST /api/sessions/email returns specific setup and provider failure messages instead of a generic send error. Brevo failures are now logged with their response status and body, while the browser receives safe error codes for configuration, sender verification, provider auth, and rate limiting.

    Added GET /api/sessions/email/status as a lightweight deploy check for BREVO_API_KEY, EMAIL_FROM, and PUBLIC_BASE_URL configuration. Bumped wwwroot/js/my-items.js to 20260527b so users get the improved browser messages after deploy.

  10. Fix

    Manifest-driven nav and clearer email receipts

    Updated Components/Layout/NavMenu.razor so sidebar tool links render from Components/Shared/ToolManifest.cs, keeping the sidebar aligned with the landing-page tool list. The nav now automatically includes manifest tools like /qr and /screenshare without hardcoding each route twice.

    Improved the session email confirmation in Components/Pages/MyItems.razor so successful sends show a masked destination, such as ja***@example.com, in both the active-session card and the new-session modal.

  11. Fix

    Clearer session-link security copy

    Updated Components/Pages/MyItems.razor with a quiet .mi-session-privacy notice in active sessions, explaining that the session URL is the key to the item list. The new-session modal warning now tells users to treat the URL like a password before they copy, download, email, or open it.

    Added matching styles in wwwroot/app.css so the warning reads as important but not alarmist, using the existing border, accent, and text tokens.

  12. New

    Email option in the new-session modal

    Updated Components/Pages/MyItems.razor so the "Save this URL" state now includes an email field beside the existing copy, download, and open actions. Users can send the just-created session link before leaving the modal, using the same hardened wbSession.emailLink() flow as the in-session email card.

    Added modal-specific styles in wwwroot/app.css under .wb-sess-email, keeping the email affordance compact and consistent with the existing session URL warning.

  13. Fix

    Clearer session email diagnostics

    Updated Program.cs so POST /api/sessions/email returns specific setup and provider failure messages instead of a generic send error. Brevo failures are now logged with their response status and body, while the browser receives safe error codes for configuration, sender verification, provider auth, and rate limiting.

    Added GET /api/sessions/email/status as a lightweight deploy check for BREVO_API_KEY, EMAIL_FROM, and PUBLIC_BASE_URL configuration. Bumped wwwroot/js/my-items.js to 20260527b so users get the improved browser messages after deploy.

  14. Fix

    Session email script cache bust

    Bumped the wwwroot/js/my-items.js asset version in Components/App.razor from 20260430a to 20260527a so browsers load the new wbSession.emailLink() helper after deploy. Also advanced the service worker cache name in wwwroot/service-worker.js to wb-v2 so installed/PWA clients clear stale static assets.

  15. New

    Session links can be emailed from My Items

    Added an in-session email card to Components/Pages/MyItems.razor so a user can send their secret /s/{token} session URL to an inbox they trust. The form calls a new wbSession.emailLink() helper in wwwroot/js/my-items.js, which posts to a Brevo-backed POST /api/sessions/email endpoint.

    The endpoint validates the recipient address, rate-limits sends to 5/hour per IP, and requires BREVO_API_KEY plus EMAIL_FROM configuration before sending. The email copy warns that anyone with the link can open the session's item list, matching the bearer-token privacy model already used by sessions.

  16. New

    Secure Note SEO pass — long-form content and SoftwareApplication schema

    Reworked /secure for organic search. New page title and meta description target encrypted-note, password-sharing, and one-time-secret queries; added Twitter Card meta and a SoftwareApplication JSON-LD block in HeadContent alongside the existing FAQPage schema emitted by ToolSeo.

    H1 changed from "One password. One note." to "Encrypted secure notes. One password." and the lede now names the real use cases (password, API key, and private-message sharing). Added a .tool-longform section above ToolSeo with ~500 words of explanatory copy, an H2-structured outline, internal links to /burn, /paste, /transfer, /wink-links, and /my-items, and an expanded 8-question FAQ. New styles live in wwwroot/app.css under .tool-longform.

  17. New

    Comparison pages and a no-signup tools roundup

    Added five new SEO landing pages aimed at comparison searches. Four "vs" pages — /compare/pastebin-alternative, /compare/wetransfer-alternative, /compare/privnote-alternative, and /compare/bitly-alternative — each with an honest feature-comparison table, a "why people switch" explainer, an FAQ with FAQPage JSON-LD, and a call-to-action to the matching tool.

    Also added a roundup at /best-no-signup-tools that lists every tool from ToolManifest. The four comparison pages are linked from their matching tool pages (Paste, File Transfer, Burn, Wink Links) via a new optional link slot on the ToolSeo component, and all five pages plus the previously-missing /screenshare, /chalk, and /tools were added to sitemap.xml.

  18. Design

    Keyword audit and metadata tightening across tool pages

    Audited every tool page's title, H1, and meta description against its target search terms. Fixed the biggest misses: the QR page H1 was "QR Note" and is now "QR Code Generator"; Flux's title went from a bare "Flux" to "Real-Time Webhook Stream, No Account"; and Chalk and Wink Links now carry real search terms in their titles ("Shared Checklist", "Free URL Shortener") instead of brand-only names.

    Also tightened the keywords meta on Burn, Paste, File Transfer, and Clipboard to include high-intent phrases people actually search — pastebin alternative, anonymous file transfer, wetransfer alternative, sync clipboard between devices, self destructing notes — and added keyword meta to Flux, Chalk, and Wink Links, which had none.

  19. Fix

    One H1 per tool page

    Several tool pages had multiple <h1> tags — the SEO headline plus in-form state headings like "Link Created" or "Room Expired". Demoted those state headings to <h2> on Burn, Paste, Clipboard, File Transfer, and Secure Note, so each page now exposes exactly one true <h1>. Styling is driven by class, so the pages look identical.

  20. New

    FAQ and use-case sections on every tool page

    Added a reusable ToolSeo.razor component and placed it on all 12 tool pages — Burn, Paste, Wink Links, Chalk, Clipboard, File Transfer, Call, Screen Share, Flux, Secure Note, QR, and Encrypted Chat. Each page now has a "What people use it for" list and a collapsible FAQ tuned to how people actually search ("self-destructing notes", "free pastebin no signup", "anonymous file sharing", and so on).

    The component also emits FAQPage JSON-LD structured data so search engines can render the questions as rich results. Styling lives in app.css under .tool-seo. This gives each tool its own keyword-rich, indexable content instead of relying on the shared landing page.

  21. Design

    Keyword-clear H1 on the landing and tools pages

    Added a search-friendly section heading above the tool grids on / (Landing.razor) and /tools (Tools.razor): an <h1> reading "Free Online Tools — No Signup Required" with a subheadline describing the utilities (sharing, communication, file transfer, QR codes, encrypted notes, collaboration).

    On the landing page the stylized "Send it. Forget it." tagline was demoted from <h1> to <p> (styling unchanged) so each page keeps exactly one true <h1>. New .seo-intro styles live in app.css.

  22. New

    SEO refresh for the new screen share tool

    Updated <HeadContent> on /screenshare: new title (Free Screen Share – Remote Support, No Download), expanded description, and a fresh keywords meta covering "free screen share", "screenshare no download", "remote support free", "help family with computer", "WebRTC screen share", "6 digit screen share code", and the brand phrase "help me help you". Added Open Graph and Twitter Card tags so link previews on social and chat apps render properly.

    Also widened the /tools and / landing meta to mention the new tool plus terms search engines actually see queried — "free", "no account", "no download", "remote support" — without disturbing the existing voice/note/burn keywords.

  23. New

    Help Me Help You — 1:1 screen share

    New tool at /screenshare for screen-share-only sessions. Start a room, get a 6-digit code, share it with the other person; once they join, either side can hit Share my screen. Pure WebRTC peer-to-peer (uses getDisplayMedia, video only, no audio, no recording). Reuses the existing CallHub for SignalR signaling with its own JS namespace (ssState/ssInit/ssStartShare) so it doesn't entangle with the voice/video Call tool. Added to ToolManifest in the Share group, so it shows up on the landing page and sidebar automatically.

    Mobile note: Mac, Windows, Linux, and Android Chrome can both share and view. iPhone/iPad can view a shared screen but can't share their own — Apple doesn't expose getDisplayMedia on iOS Safari. The setup screen calls this out so users aren't surprised.

    Also added a hand-built card for it on /tools (slate-indigo #4F46E5 accent, monitor+stand icon) right after Voice & Video Call, and updated the page's meta description to include "1:1 screen share" for SEO.

  24. Fix

    Admin page contrast fix

    Section titles like "Transfer Rooms", "Flux Streams", "Wink Links", and "Allowed IP Addresses" on /admin were near-invisible — styles used #e8e8f0 (near-white) text on the site's light page background. Switched all text sitting on the page background (titles, section headings, table headers and cells, login labels, IP info, footer) to dark #111/#222/#444; text inside the dark cards and inputs (.adm-stat, .adm-empty, .adm-input, .adm-count, .adm-refresh-btn) stays light. No layout or wrapper changes.

  25. New

    Optional one-time recovery keyword for sessions

    New on /my-items: while in a session, you can set a one-time recovery keyword (min 8 chars). If you ever land on a new device without your /s/{token} URL, type the keyword on /my-items and the session will be pulled in. Single-use — redeeming clears it, and the in-session card prompts you to set a new one. Replace or clear it any time. We never display the keyword again after it's set, only that one is set.

    Implementation: new nullable RecoveryHash / RecoveryTokenCiphertext / RecoveryTokenNonce columns on Session via the AddSessionRecovery migration. Lookup is by SHA-256 of the keyword; the URL token is encrypted with AES-GCM under a key derived from the keyword via HKDF (info string whisperblinks.session.recovery.v1) so the server alone can't recover it. Endpoints: GET/POST/DELETE /api/sessions/recovery and POST /api/sessions/recover. Recover is rate-limited to 5/hr per IP with a fixed-delay 404 on misses to flatten timing. Keyword collisions across sessions are rejected at set time so redemption is unambiguous.

  26. New

    New "Approach" page — the principles behind every tool

    Added /approach at Components/Pages/Approach.razor, linked from the sidebar (Components/Layout/NavMenu.razor) and footer (Components/Shared/Footer.razor). It walks through the six steps we run every time we ship a tool — start with a question, strip it down, encrypt at the edge, make it expire, ship without friction, listen and iterate — plus a "what we don't build" list (no analytics, no ads, no social hooks).

    Also wired up better session/local-storage sync on /my-items: ending a session now clears local items too, and revisiting /s/{token} repopulates local from the server via a new wbSession.syncLocalFromSession() helper in wwwroot/js/my-items.js. Restored the persistent "In session" banner with a MutationObserver so Blazor's interactive re-renders no longer strip it. Footer now also credits JTNtechs.com.

  27. New

    Persistent sessions — your items across devices, still no account

    New "Make a session" flow on /my-items: pick a label, and the server hands back a secret URL at /s/{token}. Save that URL and you're back in — from any device, any browser. No username, no password. Sessions are stored in new Sessions and SessionItems tables via the AddSessions migration.

    Tokens are 256-bit CSPRNG values (32 bytes from RandomNumberGenerator, base64url-encoded) stored only as SHA-256 hashes — a DB leak can't replay live URLs. Session labels are encrypted with AES-GCM using a key derived from the URL token via HKDF-SHA256, so even admin can't read them from the DB: without the URL, no decryption. See Services/SessionTokenService.cs.

    Tool pages are untouched. The existing wbItems.add(...) call now mirrors to POST /api/sessions/items whenever a session is active (state kept in a new wbSession localStorage helper). Creating a session sweeps current local items into the server index. A slim sticky banner at the top of every page shows the active session with "View items" and "End session". Full flow: create, import, list via GET /api/sessions/info, add/remove items, and a "Delete session" action that cascades the index. Idle sessions expire after 90 days with cleanup in the existing background timer.

    Security posture: per-IP rate limits on create (5/hr), lookup (60/min), and write (120/min); constant-time token compare with a small fixed delay on 404 to flatten enumeration timing; Cache-Control: no-store, Referrer-Policy: no-referrer, and X-Robots-Tag: noindex scoped to /s/*. The Admin page gains an aggregate "Sessions" card — counts only, no IDs, no labels, no tokens.

  28. New

    Chalk — shared encrypted list

    New tool at /chalk: a real-time collaborative list anyone can check off. Create a list in one click — a 6-character room code and an AES-256 encryption key are generated; the key lives in the URL fragment so the server only ever stores ciphertext. Items can be marked done (tracked by display name), stashed to a collapsible section, or restored. All changes broadcast instantly via a new ChalkHub SignalR hub. Lists expire and are purged after 7 days.

  29. New

    Push notifications — room join alerts on Android & iOS

    Added end-to-end push notification support for native apps. When a user creates a chat or call room, their device token is registered server-side via POST /api/push/register and stored in a new DevicePushToken table (24-hour TTL with automatic cleanup). When someone joins, ChatHub and CallHub trigger PushNotificationService, which sends an FCM HTTP v1 notification using RSA-signed service-account JWTs — no new NuGet packages needed. Tapping a notification deep-links directly into the room. Activated by setting the FIREBASE_SERVICE_ACCOUNT_JSON environment variable; gracefully disabled when unset.

  30. New

    Capacitor native shell — Android & iOS app foundation

    Added a capacitor/ directory alongside the .NET project containing a Capacitor 5 native shell. The shell points to the live whisperblinks.io server, so all SignalR chat, WebRTC calls, and encryption run identically across web, Android, and iOS. Native permissions configured: camera and microphone (Info.plist / AndroidManifest.xml) for the Call tool, and push-notification groundwork for future incoming-call alerts. Open in Xcode with npm run open:ios or in Android Studio with npm run open:android from the capacitor/ directory.

  31. New

    PWA — installable on Android and iOS

    Added a service worker (service-worker.js) with cache-first static asset delivery and a network-first navigation strategy. SignalR hubs and Blazor internals are excluded from interception so real-time chat and calls are unaffected. Added iOS homescreen meta tags to App.razor (apple-mobile-web-app-capable, apple-mobile-web-app-status-bar-style, apple-mobile-web-app-title) and fixed the Apple touch icon to use the 192×192 asset. Added an on-brand offline fallback page (offline.html) shown when the network is unavailable. The app can now be installed from Chrome on Android (install prompt fires automatically) and from Safari on iOS via Share → Add to Home Screen.

  32. New

    Landing — "How It Works" stamp-card section

    Added a three-step explainer between the tool grid and the footer. Each card carries a circular stamp icon, a Fraunces heading, a short description, and a pair of monospace tags (e.g. aes-256 / auto-delete). The section uses a 3-column grid that collapses to single-column below 820 px. No dependencies added — pure HTML + CSS tokens.

  33. New

    Change log — standalone page at /changelog

    Moved the update log out of the footer toggle and into its own page. The footer now carries a plain "Change log" nav link alongside About, Privacy, and Contact. The page uses the same timeline layout with date, badge, title, and description — scoped styles only, no global CSS changes.

  34. Design

    Footer & About page polish

    Footer text upgraded from ghost-grey to full ink tokens; font sizes bumped to meet 4.5:1 contrast on the paper background. The Contact section on /about now routes to the dedicated contact form instead of a bare mailto link. Separator dots made fully opaque; copyright line gained a dashed rule above it.

  35. Design

    Chat — full palette rewrite

    All 537 lines of Chat.razor inline styles converted from the old dark-indigo theme (#28283f) to paper/ink tokens. Own-message bubbles now use a warm brick tint; other-message bubbles sit on the secondary paper surface. The send button, toggle switch, room-code display, and typing indicator all follow the single-accent constraint. Font family replaced: Space Grotesk → IBM Plex Mono for codes and room labels.

  36. Design

    WinkLinks & Tools pages — dark theme removed

    Both pages had inline <style> blocks written for the old #0f0f1a background. Replaced every purple/indigo tint and glass-morphism card with var(--bg-secondary), var(--border), and var(--accent). Button gradients replaced with flat brick. Font family switched from Space Grotesk to IBM Plex Mono for short codes and URLs.

  37. Fix

    /my-items readability overhaul

    Replaced 40+ rgba(129,140,248,…) purple tints in MyItems.razor with semantic paper tokens. Item labels, filter chips, bulk-action buttons, and the clear-all confirm dialog are now legible against the paper background. The page title switched to Fraunces; the danger colour was toned to the brick family (#8a2a1a) to stay on-palette.

  38. New

    Brand identity — logo & favicon

    Introduced the "held-dot" mark: two bracket strokes cradling a brick accent dot — a visual shorthand for the bracketed ephemeral data at the heart of the product. Three SVG artefacts shipped: favicon.svg (thicker strokes, larger dot for 16–32 px legibility), logo.svg, and logo-horizontal.svg with the Fraunces wordmark. WhisperBlinksLogo.razor updated to render the mark in currentColor so it adapts to any surface automatically.

  39. Design

    Typography system — Fraunces + IBM Plex

    Retired Inter and Geist. Display headings (H1/H2) now use Fraunces 500/600 — an optical serif with a warm, editorial feel that anchors the paper palette. UI copy uses IBM Plex Sans 400–700; code snippets, room codes, and timestamps use IBM Plex Mono. Gradient-clipped text removed site-wide; all heading colours resolved to var(--text-primary).

  40. New

    New landing page — grouped tool grid

    Replaced the animated blueprint landing with a clean paper-and-ink tool grid at /. Tools are organised into three sections — Send to someone, Share live, and Keep private — each card showing the tool name, a one-sentence explainer, and two claim chips (e.g. "One-time · 10 min"). The old animated landing is preserved at /classic-new for reference.

  41. Fix

    ToolManifest.cs — single source of truth

    Created a static C# record list that owns every tool's slug, name, href, group, one-liner, and two claim chips. The sidebar nav and landing grid both read from it, eliminating the copy drift that had routes and descriptions diverging across files. Adding a new tool now requires a single line in one file.

  42. Design

    Secure Note, Burn, Paste — explainer split layout

    All three tool pages wrapped in the tool-split shell: a left aside carries the kicker, headline, lede, and three fact bullets; the right section holds the existing form untouched. Burn's amber warning was demoted to a quiet italic line below the input — it only surfaces at full intensity at the moment of consequence (when a note is created).

  43. Design

    Nav menu overhaul — grouped tool sections

    Replaced the Blazor template Counter/Weather links with four grouped sections: Send, Share live, Keep, and About. NavMenu.razor.css fully rewritten for the paper palette — the dark-purple sidebar overlay is gone, the active link uses brick accent, and hamburger icon strokes are darkened to ink. Groups are labelled with muted uppercase caps for quick scanning.

An unhandled error has occurred. Reload X

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.