Skip to content

✨ Added Klipy as a GIF provider alongside Tenor#28109

Merged
renatoworks merged 4 commits into
mainfrom
tenor-klipy-migration
Jun 2, 2026
Merged

✨ Added Klipy as a GIF provider alongside Tenor#28109
renatoworks merged 4 commits into
mainfrom
tenor-klipy-migration

Conversation

@renatoworks
Copy link
Copy Markdown
Contributor

@renatoworks renatoworks commented May 25, 2026

Describe the problem you are solving

This PR adds Ghost-side support for Klipy as a GIF provider in the editor's GIF card, alongside the existing Tenor provider. Google is shutting down the Tenor API on 2026-06-30, so a replacement is needed.

The actual Klipy provider implementation lives in @tryghost/koenig-lexical (paired PR: TryGhost/Koenig#1932). This PR adds the Ghost-side plumbing: a klipy config key, forwarded through both editors to the Koenig card config, plus removal of a dead pre-Lexical Ember service.

No breaking changes. Without a Klipy key configured, behaviour is identical to today: the editor's GIF card continues to use Tenor exactly as before. The new klipy config block defaults to null, and any koenig-lexical version that does not know the field simply ignores it. The Klipy path only becomes active for a deployment that (a) gets the newer koenig-lexical version via a separate dependency bump, and (b) configures a Klipy key.

Each PR in this pair is independently safe to merge: they are backward-compatible in every direction. The dependency bump that connects them is a separate small follow-up (Renovate's auto-PR, or a tiny manual PR), not part of this PR.

Changelog for devs

  • Added a klipy config block (apiKey, contentFilter) to ghost/core/core/shared/config/defaults.json, the public-config service, and the config output serializer, mirroring the existing tenor block
  • Added the optional klipy field to the Config type in admin-x-framework and the test response fixture
  • Forwarded klipy into the editor card config in ghost/admin/app/components/koenig-lexical-editor.js (Ember post editor) and apps/admin-x-settings/src/components/settings/membership/member-emails/member-email-editor.tsx (admin-x welcome-email editor)
  • Removed the orphaned ghost/admin/app/services/tenor.js (the pre-Lexical editor's GIF client, zero injection sites; the current Lexical editor ships its own GIF client)
  • Updated the e2e config API snapshot to include the new klipy block

Changelog for customers

  • Added Klipy as a GIF provider for the editor's GIF card, configurable via the klipy.apiKey config key (becomes active once the paired Koenig dependency bump lands)

Notes

  • Tenor is removed in a later phase, after the June 30 API shutdown. A separate small PR will drop the tenor config key, the Tenor-specific public-config and serializer entries, and the Tenor-specific tests. Until then, Tenor stays as the fallback so deployments without a Klipy key continue to work unchanged.
  • End-to-end rehearsal: all four scenarios were verified manually in the local Ghost editor (Klipy provider, Tenor provider, Tenor fallback when no Klipy key is set, and no GIF card when neither is configured). The rehearsal used a temporary pnpm.overrides link: to the Koenig branch; that override is not included in this PR.
  • Google has confirmed that media.tenor.com will continue serving existing asset URLs to third-party requests after the API shutdown, so existing embedded GIFs in published Ghost content remain safe; no Ghost(Pro) CDN re-host is required. The action Google asks of us is precisely what this migration delivers: replace the search/embed API by June 30.
  • Klipy production API access has been granted; the production key is ready to wire into Ghost config at deploy time.

Technical debt

  • The klipy config block mirrors the tenor shape. If we add further GIF providers, consolidating into a single gifProvider block would reduce duplication; not done here to keep this change minimal and 1:1 with the existing pattern.

PR Scope (mark all that apply)

  • Improves the user experience
  • Enhances the readability of our code
  • Simplifies the maintenance of our software
  • Fixes a bug
  • Provide a core layer to allow one of the points above

Checklist before requesting a review (mark all that apply)

  • I have performed a self-review of my code
  • It's simple enough
  • The PR is not extensive
  • It includes documentation
  • I have added thorough tests.
  • Do we need to implement analytics?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9b90d7fa-bf91-4955-b23e-12694f34b44a

📥 Commits

Reviewing files that changed from the base of the PR and between 89d0168 and 44a450b.

📒 Files selected for processing (5)
  • apps/admin-x-framework/src/api/config.ts
  • apps/admin-x-framework/src/test/responses/config.json
  • apps/admin-x-settings/package.json
  • apps/admin-x-settings/src/components/settings/membership/member-emails/member-email-editor.tsx
  • apps/admin/package.json
✅ Files skipped from review due to trivial changes (3)
  • apps/admin/package.json
  • apps/admin-x-framework/src/test/responses/config.json
  • apps/admin-x-framework/src/api/config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/admin-x-settings/src/components/settings/membership/member-emails/member-email-editor.tsx

Walkthrough

This PR introduces Klipy configuration support across the Ghost platform. The change extends the Config type with an optional klipy object containing apiKey and contentFilter fields, defines defaults, and exposes it through the public configuration service and API serializer. Klipy configuration is then injected into Koenig editor card configurations in both the email editor and main lexical editor components. The TenorService module is removed as a complete deletion.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding Klipy as a GIF provider alongside Tenor, which is the primary objective of the PR.
Description check ✅ Passed The description comprehensively explains the problem (Tenor API shutdown), solution (adding Klipy support), backward compatibility, and scope of changes, all directly related to the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tenor-klipy-migration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.70%. Comparing base (8ba93e3) to head (44a450b).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #28109      +/-   ##
==========================================
+ Coverage   73.62%   73.70%   +0.07%     
==========================================
  Files        1536     1535       -1     
  Lines      130863   130745     -118     
  Branches    15654    15641      -13     
==========================================
+ Hits        96348    96361      +13     
+ Misses      33527    33395     -132     
- Partials      988      989       +1     
Flag Coverage Δ
admin-tests 54.65% <ø> (+0.44%) ⬆️
e2e-tests 73.70% <100.00%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Member

@kevinansfield kevinansfield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks good 👌 If not squash-merging everything, I'd at least squash the Klipy config key and e2e test update together so there's an atomic commit to revert if needed. Otherwise good to merge 🙌

ref https://linear.app/ghost/project/replace-tenor-with-klipy-for-gif-cards-c48db5d2a3d5/overview

- Google is shutting down the Tenor API on 2026-06-30, so the editor GIF card needs a replacement provider
- exposes a `klipy` config block (apiKey, contentFilter) through public-config and the config serializer, mirroring the existing `tenor` block
- forwards `klipy` into the card config of the Ember post editor and the admin-x welcome-email editor so Koenig can resolve Klipy when a key is set
- Tenor stays in place as a fallback; this adds Klipy alongside it
ref https://linear.app/ghost/project/replace-tenor-with-klipy-for-gif-cards-c48db5d2a3d5/overview

- the `tenor` Ember service was the GIF client for the old pre-Lexical editor
- the current editor (@tryghost/koenig-lexical) ships its own GIF client, so the service has had zero injection sites since the Lexical migration
- dead code removal, no behaviour change
ref https://linear.app/ghost/project/replace-tenor-with-klipy-for-gif-cards-c48db5d2a3d5/overview

- adding klipy to public-config and the output serializer changed the /config/ API response
- the e2e-api config snapshot still only had the tenor block, so config.test.js would have failed CI
- regenerated and verified by running test/e2e-api/admin/config.test.js (3 passing)
- the klipy GIF provider migration requires the corresponding Koenig editor releases that add klipy support
- bumped @tryghost/koenig-lexical and the kg-* / html-to-mobiledoc packages to their .2 patch releases
- added the same-day releases to minimumReleaseAgeExclude so the 1-day cooldown does not block install
@renatoworks renatoworks force-pushed the tenor-klipy-migration branch from 89d0168 to 44a450b Compare June 2, 2026 13:59
@renatoworks renatoworks enabled auto-merge (squash) June 2, 2026 14:00
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/admin-x-settings/package.json`:
- Line 65: The PR/AI summary is missing the pnpm catalog migration note for the
lucide-react dependency: update the PR summary/description to state that in
apps/admin-x-settings/package.json the lucide-react version was changed from
pinned "0.577.0" to the pnpm "catalog:" strategy; mention this
dependency-management change alongside the Klipy/GIF-related work so reviewers
see it (edit the PR description or AI-generated summary text to include
"lucide-react: 0.577.0 → catalog:" and a short note that this is a pnpm catalog
migration).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9b90d7fa-bf91-4955-b23e-12694f34b44a

📥 Commits

Reviewing files that changed from the base of the PR and between 89d0168 and 44a450b.

📒 Files selected for processing (5)
  • apps/admin-x-framework/src/api/config.ts
  • apps/admin-x-framework/src/test/responses/config.json
  • apps/admin-x-settings/package.json
  • apps/admin-x-settings/src/components/settings/membership/member-emails/member-email-editor.tsx
  • apps/admin/package.json
✅ Files skipped from review due to trivial changes (3)
  • apps/admin/package.json
  • apps/admin-x-framework/src/test/responses/config.json
  • apps/admin-x-framework/src/api/config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/admin-x-settings/src/components/settings/membership/member-emails/member-email-editor.tsx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/admin-x-settings/package.json`:
- Line 65: The PR/AI summary is missing the pnpm catalog migration note for the
lucide-react dependency: update the PR summary/description to state that in
apps/admin-x-settings/package.json the lucide-react version was changed from
pinned "0.577.0" to the pnpm "catalog:" strategy; mention this
dependency-management change alongside the Klipy/GIF-related work so reviewers
see it (edit the PR description or AI-generated summary text to include
"lucide-react: 0.577.0 → catalog:" and a short note that this is a pnpm catalog
migration).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9b90d7fa-bf91-4955-b23e-12694f34b44a

📥 Commits

Reviewing files that changed from the base of the PR and between 89d0168 and 44a450b.

📒 Files selected for processing (5)
  • apps/admin-x-framework/src/api/config.ts
  • apps/admin-x-framework/src/test/responses/config.json
  • apps/admin-x-settings/package.json
  • apps/admin-x-settings/src/components/settings/membership/member-emails/member-email-editor.tsx
  • apps/admin/package.json
✅ Files skipped from review due to trivial changes (3)
  • apps/admin/package.json
  • apps/admin-x-framework/src/test/responses/config.json
  • apps/admin-x-framework/src/api/config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/admin-x-settings/src/components/settings/membership/member-emails/member-email-editor.tsx
🛑 Comments failed to post (1)
apps/admin-x-settings/package.json (1)

65-65: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if lucide-react is used in GIF/Klipy related code

echo "=== Searching for lucide-react usage in GIF or Klipy related contexts ==="
rg -n "lucide-react" -A 3 -B 3 | rg -i "(gif|klipy|tenor)" -C 5

echo ""
echo "=== Checking git history for this change ==="
git log --all --full-history --oneline -- "apps/admin-x-settings/package.json" | head -10

Repository: TryGhost/Ghost

Length of output: 847


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="apps/admin-x-settings/package.json"
echo "=== Current lucide-react entry (around line 65) ==="
nl -ba "$FILE" | sed -n '55,75p' | sed -n '/lucide-react/,+3p'

echo
echo "=== Search for pinned lucide-react versions in the current file ==="
rg -n '"lucide-react"\s*:\s*"' "$FILE" || true
rg -n 'lucide-react.*0\.577\.0' "$FILE" || true

echo
echo "=== Value in the commit that moved lucide-react to the pnpm catalog ==="
# commit from earlier output: 46904c97 "Moved `lucide-react` to default pnpm catalog (`#28152`)"
git show "46904c97:$(echo "$FILE")" --no-color 2>/dev/null | rg -n '"lucide-react"\s*:' || true

echo
echo "=== Check whether any GIF/Klipy-related changes touch lucide-react ==="
# quick contextual check: look for lucide-react changes in the last ~30 commits touching that file
git log -n 30 --oneline -- "$FILE" --no-color | head -50

Repository: TryGhost/Ghost

Length of output: 171


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="apps/admin-x-settings/package.json"

echo "=== Current lucide-react entry in $FILE (near lucide-react) ==="
rg -n '"lucide-react"\s*:' "$FILE" || true
sed -n '55,75p' "$FILE"

echo
echo "=== Does the current file contain pinned lucide-react 0.577.0? ==="
rg -n 'lucide-react.*0\.577\.0' "$FILE" || true
rg -n '0\.577\.0' "$FILE" || true

echo
echo "=== lucide-react value in commit 46904c97 ==="
git show "46904c97:$FILE" --no-color | rg -n '"lucide-react"\s*:' || true

echo
echo "=== List commits touching lucide-react in this file (latest 40) ==="
git log -n 40 --oneline -- "$FILE" --no-color | head -40

Repository: TryGhost/Ghost

Length of output: 1118


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="apps/admin-x-settings/package.json"

echo "=== lucide-react value around line in working tree ==="
rg -n '"lucide-react"\s*:' "$FILE"

echo
echo "=== lucide-react value at commit 46904c97 ==="
git show "46904c97:$FILE" --no-color | rg -n '"lucide-react"\s*:'

echo
echo "=== lucide-react value at parent of 46904c97 (to check 0.577.0) ==="
PARENT="$(git rev-parse '46904c97^')"
echo "Parent sha: $PARENT"
git show "${PARENT}:$FILE" --no-color | rg -n '"lucide-react"\s*:'
echo
echo "=== Is 0.577.0 present in parent commit's file? ==="
git show "${PARENT}:$FILE" --no-color | rg -n '0\.577\.0' || true

echo
echo "=== Commits touching this file (lucide-react related changes should appear here) ==="
git log -n 20 --oneline --no-color -- "$FILE" | head -20

echo
echo "=== lucide-react imports/usage in repo (limited), to see if tied to Klipy/GIF ==="
rg -n "from ['\"]lucide-react['\"]|['\"]lucide-react['\"]" -- 'apps' | head -50

echo
echo "=== lucide-react usage in files containing klipy/gif/tenor keywords ==="
rg -n --files-with-matches "lucide-react" apps | while read -r f; do
  if rg -qi "(gif|klipy|tenor)" "$f"; then
    echo "MATCH: $f"
  fi
done | head -50

Repository: TryGhost/Ghost

Length of output: 5998


Fix PR/AI summary to include lucide-react dependency strategy change.

apps/admin-x-settings/package.json updates lucide-react from pinned 0.577.0 to catalog: (pnpm catalog migration). The summary should mention this dependency-management change (it’s adjacent to the Klipy/GIF-related work in the file history).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/admin-x-settings/package.json` at line 65, The PR/AI summary is missing
the pnpm catalog migration note for the lucide-react dependency: update the PR
summary/description to state that in apps/admin-x-settings/package.json the
lucide-react version was changed from pinned "0.577.0" to the pnpm "catalog:"
strategy; mention this dependency-management change alongside the
Klipy/GIF-related work so reviewers see it (edit the PR description or
AI-generated summary text to include "lucide-react: 0.577.0 → catalog:" and a
short note that this is a pnpm catalog migration).

@renatoworks renatoworks merged commit eac5627 into main Jun 2, 2026
55 checks passed
@renatoworks renatoworks deleted the tenor-klipy-migration branch June 2, 2026 14:24
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.

2 participants