Skip to content

feat: add email obfuscation with clipboard copy and toast#3532

Open
asboyer wants to merge 5 commits intoalshedivat:mainfrom
asboyer:feat/email-obfuscation
Open

feat: add email obfuscation with clipboard copy and toast#3532
asboyer wants to merge 5 commits intoalshedivat:mainfrom
asboyer:feat/email-obfuscation

Conversation

@asboyer
Copy link
Contributor

@asboyer asboyer commented Feb 15, 2026

Summary

Closes #3531

Adds an opt-in protect_email toggle to _config.yml that obfuscates email addresses across the site to prevent spam harvesting by web scrapers. When enabled:

  • Social links (navbar/footer): mailto: links rendered by jekyll-socials are transformed client-side into obfuscated elements — clicking copies the email to clipboard instead of opening a mail client
  • CV pages: Email displays as user [at] domain [dot] tld instead of plaintext, for both RenderCV and JSONResume formats
  • Search command palette: Email entry copies to clipboard instead of opening mailto:
  • Toast notification: A slide-up "email copied to clipboard" toast confirms the action

No changes to external plugins required — social link obfuscation is handled entirely client-side. Defaults to false, so no breaking change for existing users.

Files changed

File Change
_config.yml protect_email: false toggle
_layouts/default.liquid data-protect-email body attribute for JS detection
assets/js/common.js mailto→obfuscated transform, clipboard copy handler, toast function
_sass/_components.scss Toast slide-up styles, email-protect cursor, email-sep/text colors
_layouts/cv.liquid [at]/[dot] obfuscation for RenderCV and JSONResume email fields
_scripts/search.liquid.js Conditional clipboard copy instead of mailto in search

Screenshots

CV email obfuscation

Screenshot 2026-02-15 at 12 02 48 AM

Search palette email

Screenshot 2026-02-15 at 12 02 57 AM

Toast notification

Screenshot 2026-02-15 at 12 03 54 AM

Test plan

  • Set protect_email: true in _config.yml
  • Social email icon click copies email to clipboard and shows toast (does not open mailto)
  • CV page shows user [at] domain [dot] tld instead of plaintext email
  • Search palette email entry copies to clipboard instead of opening mailto
  • Set protect_email: false — everything reverts to current behavior
  • Test in both light and dark mode
  • Test toast appears and auto-dismisses after ~2 seconds

Add `protect_email: false` to _config.yml under the Layout section.
When enabled, a `data-protect-email="true"` attribute is added to the
<body> tag in the default layout, allowing client-side JavaScript to
detect the setting and transform mailto links into obfuscated elements.

This is the foundation for email obfuscation — no behavioral change
until downstream JS and templates consume this flag.
Add client-side email protection logic to common.js:
- On page load, when data-protect-email is set on <body>, all
  mailto: links (including those rendered by jekyll-socials) are
  transformed into obfuscated elements with data-eu/data-ed attributes,
  preventing email harvesting by scrapers.
- Clicking any .email-protect element reconstructs the email from
  split parts and copies it to the clipboard, with a fallback for
  browsers without the Clipboard API.
- A slide-up toast ("email copied to clipboard") confirms the action.

Add supporting styles to _components.scss:
- .email-protect cursor, .email-sep/.email-text colors for the
  [at]/[dot] display used in CV pages.
- #email-copied-toast fixed-position slide-up animation.
When protect_email is enabled, email addresses in the CV layout are
displayed as "user [at] domain [dot] tld" instead of plaintext. This
applies to both the RenderCV (cv.email) and JSONResume (basics.email)
contact information sections.

The obfuscated display uses .email-protect spans with data-eu/data-ed
attributes, so clicking copies the email to clipboard via the handler
added in the previous commit. When protect_email is false (default),
rendering is unchanged.
When protect_email is enabled, the email entry in the ninja-keys search
palette copies the address to clipboard and shows a toast instead of
opening a mailto: link. The email is split at build time so the full
address never appears in the generated JavaScript.

When protect_email is false (default), the existing mailto behavior
with encode_email is preserved.
The toggle was set to true during testing. Reset to false so the
feature is opt-in and existing users see no behavior change.
@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@netlify
Copy link

netlify bot commented Feb 15, 2026

Deploy Preview for relaxed-lollipop-b6bc17 failed. Why did it fail? →

Name Link
🔨 Latest commit 10734f8
🔍 Latest deploy log https://app.netlify.com/projects/relaxed-lollipop-b6bc17/deploys/6991557c6a30810007d4df99

@asboyer asboyer force-pushed the feat/email-obfuscation branch from 5354d20 to 10734f8 Compare February 15, 2026 05:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add email obfuscation to prevent spam harvesting

1 participant