Sign in

iiinova is part of the Atmosphere — an open, public network where you own your identity.

Cathy Sarisky

@cathysarisky.mastodon.social.ap.brid.gy
11 followers 3 following 62 posts

[bridged from mastodon.social/@cathysarisky on the fediverse by fed.brid.gy ]

PostsRepliesMedia
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 22/09/2026
Little Green Light <-> Ghost integration. Working? Now we watch the money come in...
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 24/09/2026
Today: Password protected pages for Ghost. Should I roll it out to the toolbox? Anyone interested?
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 29/09/2026
So... is the Mailgun flex plan gone? I asked about it over here: forum.ghost.org/t/sept-2026-mailgun… and got no replies. I still have one. I think lots of self-hosters do, but if it isn't possible to sign up and cancel to get on it, that changes the math on getting a small […]
spectralwebservices.com
Original post on spectralwebservices.com
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 30/09/2026
Today: Stood up a Turnstile-protected sign-up form for Ghost. Turned off free memberships to block the attackers from hitting the API directly, of course. But that meant no send-magic-links endpoint, so THEN I stood up a whole token service to send my own magic links, only creating Ghost users […]
spectralwebservices.com
Original post on spectralwebservices.com
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 04/10/2026
🚨 WDYBTW: Check comment widgets reading post.excerpt from Members API What did you break this week, week of 2026-09-17 www.spectralwebservices.com/blog/wd…
spectralwebservices.com
🚨 WDYBTW: Check comment widgets reading post.excerpt from Members API
What did you break this week, week of 2026-09-17
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 04/10/2026
🚨 WDYBTW: Check your JWKS handling now: Ghost rotates signing keys What did you break this week, week of 2026-09-24 www.spectralwebservices.com/blog/wd…
spectralwebservices.com
🚨 WDYBTW: Check your JWKS handling now: Ghost rotates signing keys
What did you break this week, week of 2026-09-24
002 2
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 05/10/2026
🎉Introducing "What did you break this week?" An AI-generated rundown of the things that are going to have me patching integrations at 10pm on a Friday. www.spectralwebservices.com/blog/in…
spectralwebservices.com
🎉Introducing "What did you break this week?"
An AI-generated rundown of the things that are going to have me patching integrations at 10pm on a Friday.
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 05/10/2026
I bought a Mac! Not because I wanted a Mac. Not because my cats wanted another laptop to sit on (although they did, I'm sure). Nope, I bought a Mac because it was the only reasonable way to deal with obnoxious Safari "quirks" and to get access to dev tools for iPhones and tablets without paying […]
spectralwebservices.com
Original post on spectralwebservices.com
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 07/10/2026
If you've wanted to add a social post card in Ghost and been frustrated that it doesn't survive email, I've got you. toolbox.spectralwebservices.com/emb…
toolbox.spectralwebservices.com
Email-Friendly Embeds — Spotify, Instagram, Bluesky, X, LinkedIn, Bandcamp, SoundCloud, Datawrapper, Flourish and writer headshots that still work in email | SWS Tools
Paste a Spotify, Instagram, Bluesky, X, LinkedIn, Bandcamp, SoundCloud, Datawrapper, Flourish or PDF link and get cards for the Ghost editor: the real embed for your site, and a card that works in email, where embeds never load. Plus cards Ghost doesn't have: a small image with its caption, and an author bio card.
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 06/09/2026
Finally got organized about feedback: spectralwebservices.featurebase.app
spectralwebservices.featurebase.app
Feedback - Spectral Web Services
Give Spectral Web Services feedback on how they could improve their product.
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 30/08/2026
Those of you who's parented probably remember "If you give a mouse a cookie", in which a small request spirals out of control. I had an epiphany on Friday that I wasn't "too far" from a functional image library for Ghost, which I kicked out pretty quickly. But then I wanted it to make fixing alt […]
spectralwebservices.com
Original post on spectralwebservices.com
101 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 28/08/2026
Sneak peek.
211 2
Cathy Sarisky @cathysarisky.mastodon.social.ap.brid.gy · 25/08/2026
Or ya know, maybe we shouldn't...?
Front page of the New York Times.  Featured story is "Study's Alarming Finding: At least 1 in 4 NFL Players gets Brain Disease."  Smaller right side story: "College Football Is Back. Here's Who You Should Root for."
000 0
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 10/06/2026
Heads up for AdSense users: I have a non-TNC client who does serious investigative reporting whose AdSense was on but not set to serve anything. It appears that AdSense is now turning on "Ad Intents" automatically. (These are the little links inserted […] [Original post on spectralwebservices.com]
011 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 18/06/2026
What's 5kb (zipped) and includes impressions and click analytics?
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 12/06/2026
In 14 minutes. Faster if you don't talk as much as I do.
spectralwebservices.com
How to set up the Spectral Web Services search integration
I'm having a ton of fun setting up https://tools.spectralwebservices.com , where I'm collecting all my useful Ghost tools. Today, a video walkthrough (one take with minor splicing, please forgive me the rough spots) showing how to go from zero to advanced search for your site, all in less than 15 minutes. And that's it! Check it out and please let me know how it's working for you! Tip: Entirely optional, but if you'd like to skip the native search loading, a one line theme edit below will slightly speed up your site load. This is totally optional, though, so don't let it slow you down on getting started by following the video above. Find this code (probably in default.hbs): {{ghost_head}} Replace it with: {{ghost_head exclude="search"}}
022 2
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 18/06/2026
Because sometimes you need a quick way to stick a few sponsor messages on the page, without a ton of fuss
spectralwebservices.com
Introducing the Itty Bitty Ad Server for Ghost
Here's the latest tool launch for https://tools.spectralwebservices.com/ - an ad server for Ghost sites that just need to run a few local business ads. I've worked with lots of sites that just need to run a handful of locally-originated ads. Or sponsor messages. Either way, they don't need anything super complicated, but they do need to know how many impressions and clicks their ads got. ### What is it? An itty bitty ad server. If you want super fancy features and a huge learning curve, it might not be for you. If you just want to serve some sponsor messages/ads that you sell yourself, it might be just what you're looking for. As the video shows, if you have your ad images ready to go, you can get online and serving in about 12 minutes. ### Built in: * Responsive ad options - serve a mobile size cube on phones, banner on desktop * Ad analytics - track views and clicks, with 7day and 30day reporting. * Easy integration in Ghost. One copy-paste and you're done! * No theme edits needed. * Privacy! Your site visitors are not tracked. Seriously, ick. * Load your ad images and where they should link to, and you're ready to serve! * Fast loading. The itty bitty ad server code is about 7 kb zipped, and serves from Cloudflare. ### Not included: * Super detailed details on who saw your ad. (When you need geolocation and advanced analytics, you're ready for an advanced platform, not itty bitty ads.) * Bidding, 3rd party networks, payment collection. You don't need any of that for your first few locally-sourced ads/sponsorships * Waiting on someone to approve your site that isn't even live yet * Unexpected ads out of your control (ick) * Crazy steep learning curve. You can do this.
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 11/06/2026
Having so much fun building out tools.spectralwebservices.com. Today, I did a couple Algolia advanced search integrations, and clocked the time to set one up at EIGHT MINUTES. (The indexer might have still been running at the 8 minute mark for one of the two, that had a LOT of posts.) I […]
spectralwebservices.com
Original post on spectralwebservices.com
012 2
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 14/06/2026
Need a popup on Ghost? For free, no tracking, no ads, no branding? Yeah, we got you.
spectralwebservices.com
Meet the Spectral Web Services Popup tool
I built a thing! Another thing! Well, it's all the same thing; it's the tools collection over at https://tools.spectralwebservices.com. Today, I'm pleased to introduce you to my popup tool for Ghost. #### Some backstory... I've deployed a lot of popups for clients. The commercial options, frankly, sort of sucked. But just dropping some extra JavaScript into the theme didn't make it easy for clients to maintain. First, I thought I'd store most of the popup content on Ghost, as pages, and pull the content with the content API. That was OK, but it meant that the settings were in the tool, the buttons were in the tool, but the content was in a couple of Ghost pages. Confusing! So now, everything is in the popup builder. I think it works pretty well. The old method is still supported, at least for v4, but if you're building a new popup, use the 'built-in' option. It's less fussy! I set out to build something simple. Then people kept asking for more options, more power, more control. So many options! Sometimes, with great power comes great complexity. I've spent a lot of time trying to make it possible for you to have great control of your popups, without needing a Ph. D. to configure them. I welcome your feedback on how I did. The other thing that delayed launch for the popups was that I kept thinking up configuration settings and layouts I wanted. How'd I do? Don't worry, the buttons will match YOUR site, not mine. Ready to see it in action?
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 19/04/2026
"What's new?" asks the Ghost/ActivityPub placeholder text? Everything! Having a lot of fun taking a bunch of free-standing tools and making them easier to find and interoperate. And adding some more. And... yeah. tools.spectralwebservices.com
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 20/04/2026
A pretty good portal trick!
001 1
Reposted by Cathy Sarisky
Synaps Media @hello.synapsmedia.com.ap.brid.gy · 25/04/2026
Subdirectory installs arrive Synaps Media. One Domain, Multiple Ghost Sites — No Setup Required
synapsmedia.com
More Sites, Fewer Limits: Introducing Subdirectory Installs
Running multiple Ghost publications under a single domain usually comes with a cost: reverse proxies, custom routing, and ongoing maintenance. That’s no longer the case on Synaps Media. You can now run any of your Ghost sites as a subdirectory of another — without touching infrastructure. ## What this means Let’s say you have two sites: * myblog.com * mijnblog.nl With subdirectory installs, you can run **mijnblog** under **myblog.com/nl** (or any path you choose). This isn’t a workaround or a custom setup. You don’t need to configure a reverse proxy, adjust server rules, or manage routing yourself. You simply enable the feature, and it works. Enabling Subdirectory install for a site on Synaps Media Panel This is possible because Synaps Media already manages your sites as part of a unified multi-site system. Subdirectory installs extend that system to the routing layer — so separate sites can behave like a single structure when needed. ## Why you’d use this Subdirectories are more than a URL preference. They allow multiple sites to operate as a coordinated system instead of isolated instances. ### Shared newsletter quota Sites under the same domain share their email limits. If each site has 2,000 emails per month, combining them under one domain effectively gives you a shared pool of 4,000. Usage is handled automatically: * Emails are first deducted from the sending site * Then from the root site * Then from other connected sites This removes artificial limits between related publications and gives you more flexibility in how you use your quota. ### Unlimited subdirectory sites You can create as many subdirectory sites as you need under a single domain. This makes it easy to structure your content: * language versions (`/en`, `/de`, `/fr`) * separate sections (`/blog`, `/podcast`, `/docs`) * distinct publications under one brand All without additional setup. ### Lower cost with multi-site discount Subdirectory installs also benefit from the existing 10% multi-site discount. In practice, this means you’re not just simplifying your setup, you’re reducing cost while doing it. ## What you don’t need anymore With subdirectory installs, several common requirements disappear: * Reverse proxy configuration * Server-level routing * Additional infrastructure * Ongoing maintenance for custom setups If your root site is already running on Synaps Media, everything is handled for you. ## Where this fits This feature is especially useful if you’re: * Running multi-language publications * Managing multiple brands under one domain * Organizing content into focused sections while keeping SEO consolidated * Migrating from a self-hosted setup with custom routing * Using different themes or branding under a single domain ## Final note A common reason for self-hosting Ghost is the flexibility to control routing and structure. Subdirectory installs on Synaps Media remove that trade-off. You get the same flexibility, without managing the infrastructure behind it. This feature is now available for all Synaps Media publications, without any extra costs, by enabling in the panel. To learn more about Subdirectory Install feature on Synaps Media, you can read our document.
015 5
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 25/04/2026
And you might need to roll your keys, too.
spectralwebservices.com
If you are on less than Ghost 6.19.1, it's way past time to upgrade
Hey self-hosting folks, **REMINDER: I don’t work for Ghost. The content below is my own opinion, not that of the Ghost Foundation, blah blah blah. Might be wrong, and possibly worth only what you paid for it (nothing).** In case you’ve missed it, Ghost had a baaad security vulnerability back in February, disclosed here: SQL injection in Content API### Impact A SQL injection vulnerability existed in Ghost’s Content API that allowed unauthenticated attackers to read arbitrary data from the database. ### Vulnerable Versions This vulne…GitHubTryGhost That’s a bad one. Specifically, it allows an attacker to read your whole site, include admin api keys, and once they’ve got the admin api key, there’s a lot that can go wrong. 💡 If you are in managed hosting (at least Ghost Pro, Synaps, Magic Pages), you got patched as soon as 6.19.1 was released. You can probably give a sigh of relief and stop reading. This post is mostly for self-hosters who haven't upgraded, or who wanted a while before upgrading. So, if you’re self hosting, you should IMMEDIATELY upgrade. Do not pass go, do not collect $200, just upgrade. (The vulnerability is there all the way back to 3.x, so older sites are not safe.) If you updated right when 6.19.1 was released, it might be ok to assume that your site wasn’t compromised before you updated, since the vulnerability probably wasn’t widely known… maybe. If you’re still at < 6.19.1 NOW, you need to seriously consider the possibility that attackers might already have your admin api key, and that upgrading will remove the ability to get a key, but not fix any existing key leakage. My possibly over-cautious thought is that y _ou should probably roll all your keys, including staff tokens_. I’m not sure if this is overly alarmist, but better safe than sorry? My thinking here is that **NOTE: If you have services connected through these keys, you WILL break them by doing this. You’ll need to revisit each service and provide the newly regenerated key/token. Yes, that sounds like a pain.** Staff tokens can be regenerated from the individual staff profile (only for the logged in user). Scroll down and click ‘regenerate’. Suspend any admin or enhanced editor users you can’t get to regenerate their own tokens. (Editors with the enhanced editor role can read the members list.) Your Admin API keys in custom integrations can be regenerated from /ghost > settings > custom - click into each integration and regenerate. You also need to regenerate your Zapier token - in /ghost > settings > integrations, click ‘configure’ next to zapier and regenerate the token. I’ve seen two reports of sites being compromised via Zapier token, specifically. I’m not _sure_ it’s from this vulnerability instead of a Zapier vulnerability/leak, but I’m suspicious. * * * That’s all I know. Wanted to get it out there in case it helps someone. Even if key rolling sounds like too much to do today, please please please do yourself a favor and update to >= 6.19.1. (This is a crosspost with the Ghost forum: https://forum.ghost.org/t/if-you-are-on-ghost-6-19-1-you-really-need-to-update/62706 ) * * * Hey, before you go... If your finances allow you to keep this tea-drinking ghost and the freelancer behind her supplied with our hot beverage of choice, we'd both appreciate it! Buy me a tea ☕️
000 0
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 16/04/2026
I built a tool. You should try it!
spectralwebservices.com
Introducing the newsletter digest builder!
Today, I'm pleased to invite you to try out my Ghost newsletter digest builder. It will read your recent posts and/or pages and create a newsletter draft for you. The eventual plan is that you'll be able to schedule it to run unattended, but right now it must makes drafts when you click the button, because it's beta (er... at best), and you shouldn't let is run unattended before testing it out. Speaking of safety, the tool will prompt you for a contributor staff token. That's what I recommend you give it. A contributor staff token can create a post draft, but can't edit other people's content, send a newsletter, mess with your members, or otherwise make trouble. You _can_ give it an admin api key or higher level token, but for creating drafts, it doesn't need more privileges, so please don't give it more! ### To make a contributor and get your token: 1. Go to /ghost > settings > staff and click 'invite'. Send an invite to an email address you control. (Tip: many email providers will deliver something like yourrealusername+somethingelse@gmail.com to yourrealusername@gmail.com, which is handy if you need another email address but don't have one.) 2. Log out of Ghost (or do everything below in a different browser that isn't logged in). 3. Click (or paste into the alternate browser) the invitation link received in email. Make the contributor account. It'll be the author of the newsletter (although you can change it), so consider a generic name. 4. Once you've logged in your contributor, click the 'person' icon in the lower left corner and open your profile from the menu that opens. 5. Your 'staff user token' should be at the bottom of the profile page. (You only have to do that ONCE. The digest builder will save it for you!) Once you've got your token, head back to the staff builder and follow the setup directions! ### Feedback wanted! The digest builder is very much beta software. I'd love to know what you think of it! What didn't it do that you wanted it to? (Besides scheduling. That's coming.) What other types of content should it let you pull in? Any bugs? Leave a comment below or share your feedback with me wherever we talk. Thanks! Looks like you aren't a member of the site yet! You'll need to make an account before you can play with the digest maker! Sign up, already! Ready to build an awesome newsletter digest? Click the button below and let's get started! Try it out!
001 1
Reposted by Cathy Sarisky
Synaps Media @hello.synapsmedia.com.ap.brid.gy · 12/04/2026
Edit your Ghost theme files right inside your Ghost Admin. No more roundtrips!
synapsmedia.com
Theme Editor built into Ghost Admin: Now live for all Synaps Media sites!
Editing a Ghost theme has always been more complicated than it should be. Even a small change meant going through the full cycle: download the theme, unzip it, edit files, zip it again, and upload it back. It works, but it breaks the flow. Starting today, this is no longer necessary. New "Edit in Browser" item in installed theme menu We’ve added a built-in Theme Editor to all Synaps Media publications, with no setup required. You can now edit your theme files directly from the Ghost Admin, instantly. By clicking "Edit in Browser" button in installed theme list on your Ghost Admin, you will see a file editor right inside your screen. Editing theme files in built-in code editor This is great for quickly editing translations, small updates on your templates, or adding a custom files to your theme like `robots.txt`. You can add/delete/rename files and folders. Edit language files or templates, within a full-featured code editor. No downloads. No uploads. No extra steps. If you’re working on customizing your theme, give it a try. This tool is an open-source project built and published by Synaps Media. If you are curious about the technical background of the project check the article from Murat Çorlu.
013 3
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 09/03/2026
Me to the spouse on Saturday morning after making Ghost themes translatable and asking for PRs with translations: "Docs are good! I figure either I'll get the first theme translation in 6 hours and on the right repo, or maybe 48 hours and on the wrong repo." We're at 48 hours, and no submissions […]
spectralwebservices.com
Original post on spectralwebservices.com
011 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 06/03/2026
Released into the wild... forum.ghost.org/t/theme-translation…
forum.ghost.org
🌐 Theme translations!
Remember when I asked Anyone interested in translating an official theme? I’ve got a better idea! How about if we do 18 at once!? 🎉 Rolling out over the next week or two are fully translation-wrapped themes (done by yours truly), and tooling for maintaining a set of common strings that ALL themes can pull from. If you speak a language other than English fluently, you’re invited to participate! All translation efforts for official themes are going to go to Themes/theme-translations, and...
032 3
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 01/03/2026
Want the "Subscribe" button to say "Sign up, yo"? Here's the options.
spectralwebservices.com
Customizing theme text in Ghost
## Table of Contents * The right ways, for most users: * Option #0: Do you just want your theme translated? * Option #1: Check your custom theme settings * Option #2: Edit the theme directly * Option #3: Take advantage of translations functionality * Weird and hack-y solutions * Option #4: Mis-use translations functionality * Option #5: block, contentFor, and #split. ✨NEW✨ * Add the variable to the theme's package.json: * Add two new partials (in the theme's partials folder) * Wrap your customizable strings * Get the work above live on your site. * Add customizable strings in design & branding * But wait! Is this really the right way to do it? * Aside: Official theme translation updates * Cool stuff: Gift articles and referral programs, a better Youtube embed, and a TOC card. * A staff builder tool for Ghost I've posted previously about the challenges of maintaining a theme that autodeploys to dozens of sites, and how do we let users customize the text sidewide in that situation? The TL;DR: I don't want to make a custom copy of the theme for each of my Tiny News clients just so I can change a couple strings, because that theme is under active development, and GitHub deployment is the only thing that keeps me sane. But before we get into the weird hacks that might fix my edge case, let's review somewhat more-sane options that will mostly work, for most users: ## The right ways, for most users: Let me lead off with several options, just in case you don't know about them. Most users need one of these solutions. ### Option #0: Do you just want your theme translated? If you're wanting to have your site in a different language, you might just be able to set the language in /ghost > settings > Publication language. Note that official themes are _still_ not translatable. There's an update on this at the end of the post. Whether this works (or just moves you to option #2) depends on whether there are strings available for your theme, in your language. ### Option #1: Check your custom theme settings Many themes offer a couple custom strings. Check your theme documentation, or check in /ghost > settings > design & branding (click customize) > theme tab (right side of page). For example, Source lets you change the newsletter subscribe box text on the homepage. ### Option #2: Edit the theme directly Look through the theme files and find the strings you want to replace, and replace them. This means downloading it, unzipping it (with whatever tools you already have), editing it (you can grab a code editor, but just notepad will work), zipping it again, and uploading it. ### Option #3: Take advantage of translations functionality If your theme is already set up for translations (official themes are NOT... yet), download and unzip the theme (links above), but then edit locales/en.json to set the strings. Note that neither option above will let you change text that's within Portal (but see this for a starting point), Comments, or Search. Neither will these. ## Weird and hack-y solutions ### Option #4: Mis-use translations functionality I wrote about this previously, where basically we append a site code to the translation strings, allowing one en.json to serve all the (English-language) sites, with any language customizations included. Custom/Multi-language theme strings?Hijacking the translation function to let users customize their strings.Spectral Web ServicesCathy Sarisky, Ghost Expert ### Option #5: block, contentFor, and #split. The approach below allows you to put all your string overrides into a custom theme variable (yes, just one). It's going to be the custom variable of doom, but it works. #### Add the variable to the theme's `package.json`: "config": { "custom": { "translation_key": { "type": "text", "description": "See documentation for how to use this" } } } (You probably already have a config.custom section. Just add the middle three lines if so.) #### Add two new partials (in the theme's partials folder) {{!-- tr-adapter.hbs --}} {{#split @custom.translation_key separator="//"}} {{#foreach this}} {{#split this separator=":"}} {{#contentFor this.[0]}}{{this.[1]}}{{/contentFor}} {{/split}} {{/foreach}} {{/split}} {{!-- tr.hbs --}} {{#if (block string)}} {{{block string}}} {{else}} {{t string}} {{/if}} Be sure to admire the use of the #split helper here. I contributed that. What are we doing here?? The `tr-adapter` partial loops through the custom variable that contains all the translations, creating a #contentFor section for each one. That section has the translation key as the key for contentFor, and the content is the translated/customized string. The partner of #contentFor is block. Block retrieves the content you added with contentFor. So in the `tr` partial, we check to see if the block has a value. If it does, we use that. If it doesn't, we fall back to the key, which I'm still passing into the built-in t helper, to retain the built in theme translation support, if any. #### Wrap your customizable strings Every "top-level' .hbs file needs `{{> tr-adapter}}` right below `{{!< default }`. (For most themes, that means home.hbs, index.hbs, post.hbs, page.hbs, author.hbs, tag.hbs, plus any custom-some-name-here.hbs files if you have custom templates.) Then, throughout the theme, you'll want to find the strings that should be customizable, and feed them into the tr partial. Old: `Subscribe` or `{{t Subscribe}}` New: `{{> tr string="Subscribe"}}` (This, by the way, is one of those jobs you can turn your LLM code assistant loose on, and expect it to get it pretty much right.) Note: Some strings go into the t helper with variables that should be passed in. It's at least mostly possible to make this happen (you'd just pass all possible values into `tr`, and then pass all possible values into `t`) but I didn't go there for this example, because the theme I was working on didn't have any variables in use. #### Get the work above live on your site. If running locally, reboot to get the changes picked up. If deploying to hosting, use whatever method (GitHub actions? Zip and upload?) you usually use. #### Add customizable strings in design & branding The format for the `translation_key` variable is like this: Subscribe:Sign up, yo!//Account:Manage your membership//posts:articles No leading or trailing spaces. Separate old from new value with a `:` (which means you can't have a : within them, but feel free to swap out the separator if you need to), and separate each entry with `//`. And that's it. You can now customize any strings you wrapped in the `tr` partial, just by changing your custom theme variable. #### But wait! Is this really the right way to do it? It would be cool if it were possible to separately upload an `overrides.json` file from within the Ghost dashboard, without needing to edit the whole theme. It would be even cooler if those overrides also adjusted the Portal, Comments, and Search apps. But none of that's possible today, so there you have it. * * * ## Aside: Official theme translation updates The i18next work that was nominally a blocker for official theme translations is merged. (I donated it.) Now we're waiting on various other prerequisites before we can really kick off a theme string wrapping and translation project. It's coming. No, I don't know how soon. Right now I'm blocked on a combination of the fact that I don't have any funding to do it anyway, the core team wanting to review some of the work necessary to enable theme translations at scale but this not being a priority, and my needing either permissions necessary to actually trigger a release of a theme or someone on the dev team being willing to take requests for releases from me. I'm still hoping we'll have translatable & translated official themes at some point in 2026. Meanwhile, if you're on Ghost Pro's Starter plan and need your theme in a language other than English _right now_ , consider Magic Pages, which offers a substantially less-limited Ghost hosting plan at the same price point. * * * ## Seen around the web ### Cool stuff I didn't do, but wish I had. “Refer A Friend” Campaigns in Ghost for FreeTracking referrals and exporting attribution data from a Ghost site for free.Gift Links for GhostA button that lets Ghost members share paywalled articles via gift links. Simple, free service.ghost-toc/README.md at main · vlavrynovych/ghost-tocLightweight Table of Contents generator for Ghost blog platform. Zero dependencies, collapsible functionality, works via code injection. Just add <toc> tag to your posts! - vlavrynovych/ghost…GitHubvlavrynovych Nice option if your theme doesn't include a table of contents already! Better YouTube Embed - Privacy-First YouTube Embed GeneratorPrivacy-First YouTube Embed Generator This tool from Murat of Synaps Media offers an alternative to the built-in YouTube card. ### And one thing I did build, that you might be interested in: How to create staff members in GhostNeed to create a bunch of contributors? I wrote a thing.Spectral Web ServicesCathy Sarisky, Ghost Expert * * * Share this post: * * * Hey, before you go... If your finances allow you to keep this tea-drinking ghost and the freelancer behind her supplied with our hot beverage of choice, we'd both appreciate it! Buy me a tea ☕️
024 4
Cathy Sarisky @cathysarisky.mastodon.social.ap.brid.gy · 07/02/2026
Kroger, Salem VA. Most of the handicapped spots are like this. Strangely, none of the grocery pickup spots have any snow, despite being similarly positioned. 😡
The handicapped parking spot is completely blocked by a three foot high mound of dirty snow. The Kroger grocery store sign can be seen on the background.
001 1
Reposted by Cathy Sarisky
Street Art Utopia @streetartutopia.mastodon.online.ap.brid.gy · 05/02/2026
London doing the work ! ❤️‍🩹
Photo of a London bus stop shelter at Nutfield Close with a protest-style poster that reads, “You know who’s not in the Epstein files? Immigrants, muslims and trans people. You know who is? Billionaires.” The poster includes cut-out photos of four wealthy, well-known men along the bottom, and the shelter is branded JCDecaux on a sunny street with bare winter trees in the background.
6101169 169
Cathy Sarisky @cathysarisky.mastodon.social.ap.brid.gy · 06/02/2026
So... this is a cool idea, but I'm utterly flummoxed that he's opted to stay on Instagram and isn't even offering his followers another option, somewhere out in the Fediverse. What the heck?? www.resistandunsubscribe.com #resistandunsubscribe
resistandunsubscribe.com
Resist and Unsubscribe
200 2
Reposted by Cathy Sarisky
Sasha Akhavi @sakhavi.aoir.social.ap.brid.gy · 05/02/2026
Wrote my rep: “As David French writes in The NY Times today, the MAGA establishment is threatening the use of ICE to disenfranchise Americans in the coming midterms. To head this possibility off, we must pass the Bevins bill making federal officials accountable in civil court if they infringe […]
aoir.social
Original post on aoir.social
201 2
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 31/01/2026
Hijacking the translation function to let users customize their strings.
spectralwebservices.com
Custom/Multi-language theme strings?
<p>I have an oddball problem most of you probably don't have. I manage a single Github theme repo that auto-deploys to about 30(?) different small newsroom websites, managed by ~60 different people, with at least 90 different opinions on well... everything. (I love my <a href="https://tinynewsco.org" rel="noreferrer">Tiny News Collective</a> fam, but oh my, some days it's a lot.) Sometimes I end up making a custom copy of the theme, for a newsroom whose needs just don't match what's in TNC's house theme. But then I've got to deal with keeping another thing up to date. That seems ok if we're doing a big rearrangement of everything, but when they just want the subscribe button to say something different? Too much.</p><p>Yes, I know about <a href="https://docs.ghost.org/themes/custom-settings" rel="noreferrer">custom theme variables</a>. I don't have enough of them for all the different spots someone would like to tweak the wording.</p><p>Did I mention that I really really don't want to maintain several dozen long-running branches?</p><p>It occurred to me recently that maybe I needed to exploit the translation helper. After all, changing which string displays is exactly what it does, right? </p><p>So I set out to do that. Unfortunately, there's no front-end way to load a custom set of translations that doesn't involve loading the whole theme, and we're doing an autodeploy from a single branch on Github. </p><p>So, I had to get clever. And by clever, I mean hacky.</p><p><em>This approach broadly parallels the one I took for </em><a href="https://theinitium.com/"><em>The Initium</em></a><em>, but there I'm detecting which language should be served based some combination of slug/URL/tag, so that they can run two separate languages sitewide. [</em><a href="https://www.spectralwebservices.com/blog/what-would-it-take-to-make-ghost-multilingual/" rel="noreferrer"><em>This works for everything but email</em></a><em>.]</em></p><p>It works like this: All <code>t</code>-wrapped strings become calls to a <code>tr</code> partial, like so:</p><figure class="kg-card kg-code-card"><pre><code>Before: {{t "Subscribe"}} After: {{&gt; tr trString="Subscribe"}} </code></pre><figcaption><p dir="ltr"><span style="white-space:pre-wrap">(picking a different variable name would make this a little more compact)</span></p></figcaption></figure><p>And then we add new partials:</p><figure class="kg-card kg-code-card"><pre><code class="language-hbs">partials/tr.hbs: {{#foreach (concat trString "_" @custom.mylocale)}} {{&gt; "tr-inner" customTranslatedString=(t this) rawString=this originalTranslatedString=(t ../trString) }} {{/foreach}}</code></pre><figcaption><p dir="ltr"><span style="white-space:pre-wrap">Why #foreach? it sets 'this'. And then I use the nested t-inner partial to set my variables, so that I only call </span><code style="white-space:pre-wrap"><span>t</span></code><span style="white-space:pre-wrap"> twice.</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code>partials/tr-inner.hbs {{#match customTranslatedString rawString}} {{log "no custom translation"}} {{originalTranslatedString}} {{else}} {{log "custom translation found"}} {{customTranslatedString}} {{/match}}</code></pre><figcaption><p dir="ltr"><span style="white-space:pre-wrap">The #match checks if the translated custom string is untranslated, meaning that the locale file doesn't contain it. If that occurs, we return the default translated string. For the example below, Subscribe -&gt; "Subscribe", Subscribe_informal -&gt; "Sign up, yo!", and Subscribe_formal -&gt; "Subscribe". </span></p></figcaption></figure><p>In <code>package.json</code>, add an extra object under <code>custom</code>:</p><pre><code> "mylocale": { "type": "select", "options": ["informal", "formal"], "default": "informal" },</code></pre><p><code>locales/en.json</code>:</p><pre><code>{ "Homepage": "Homepage", "Homepage_informal": "My slappin' homepage", "Homepage_formal": "My very formal homepage" "Subscribe": "Subscribe", "Subscribe_informal": "Sign up, yo!", }</code></pre><p></p><p>End result? If someone wants a couple of custom strings, I can just assign their site an option in package.json and add their string overrides to my en.json. Redeploy and problem sorted! No more forks/branches just to change some words!</p><p>No, I haven't deployed it yet. Still thinking about it.</p><p></p>
011 1
Cathy Sarisky @cathysarisky.mastodon.social.ap.brid.gy · 25/01/2026
I shoveled. The correct answer for the last 24h is somewhere in the vicinity of 3-4 inches. I understand that forecasting is hard (which is why the app was predicting 30 inches yesterday), but how is reporting results also this hard?? (Apple native weather app. Can I even uninstall this thing??)
A screenshot of the Apple weather app, saying we got 21 inches of snow in the last 24 hours.
001 1
Reposted by Cathy Sarisky
Quinn Comendant @com.mastodon.social.ap.brid.gy · 22/01/2026
It’s hard work submitting bug reports. Developers – this is how you treat users who submit quality reports: 1. Implement the fix. 2. Reward their work. #indieDev #webDev #appDev
Screenshot of a Discord DM: “Hey! Wanted to thank you for all the valuable feedback you've shared, so I've granted you lifetime premium (got your user ID from the logs).

If it ever gets reset, just ping me via the contact form. Thanks for helping improve the app!”Screenshot from Spokenly showing that Pro has been activated.
132 3
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 17/01/2026
Hi!👋 If your organization could use a fractional developer specializing in Ghost CMS on a recurring basis (10-40h/month), please hit me up! January is full, but I've got some space on my "dance card" for February.
002 2
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 03/01/2026
spectralwebservices.com
2026 overhaul: Retainer plans and a new client dashboard
New year, new thoughts
001 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 04/01/2026
spectralwebservices.com
Abusing the #split helper for "short codes" in Ghost
First I built a #split helper. Then I decided to see how far I could push it.
000 0
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 06/01/2026
Me: This new client portal is going to save me soooo much time in client management. (Spends some time squishing bugs. Squishes more bugs. Discovers a spot where the API doesn't do what it says it does. Squishes another bug. Writes a workaround.) xkcd.com/1319 or xkcd.com/1445 […]
spectralwebservices.com
Original post on spectralwebservices.com
011 1
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 06/01/2026
spectralwebservices.com
New year, new thoughts
Some reflections on the end of my first full calendar year of freelancing full time, and my goals for 2026.
022 2
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 04/01/2026
Best Ghost hack of 2026 (although the year is young, so...): Short-codes support? www.spectralwebservices.com/blog/ab…
spectralwebservices.com
Abusing the #split helper for "short codes" in Ghost
First I built a #split helper. Then I decided to see how far I could push it.
021 2
Reposted by Cathy Sarisky
Murat Çorlu @social.muratcorlu.com.ap.brid.gy · 19/12/2025
I think I made something.
Screenshot of a web tool named Ghost OG Image Generator. Accepts a Ghost post url, a template and generates an opengraph image for target post
042 4
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 10/12/2025
Big shout out to @hello@synapsmedia.com for joining @hey@magicpages.co in sponsoring me over on Github. I appreciate the love ♥️.... and especially the ☕️. github.com/sponsors/cathysarisky if anyone else is so inclined!
github.com
Sponsor @cathysarisky on GitHub Sponsors
Hi! 👋 I'm Cathy, a certified Ghost Expert. I'm a freelancer/sole proprietor of Spectral Web Services. Ghost is my jam, and your support helps me have more time to fix bugs, make bits of the Ghost...
032 3
Cathy Sarisky @cathysarisky.mastodon.social.ap.brid.gy · 05/12/2025
It’s a little early for 2026 goals, but I’ll ask anyway: page builder for Ghost, or Apple News integration for Ghost? I have partial projects for both…
011 1
Cathy Sarisky @cathysarisky.mastodon.social.ap.brid.gy · 18/11/2025
First time it hasn’t been my fault…
Cloudflare error message showing an error in the data center
031 3
Reposted by Cathy Sarisky
Spectral Web Services @cathy.spectralwebservices.com.ap.brid.gy · 15/11/2025
spectralwebservices.com
A before/after slider in Ghost?
Ghost doesn't have native before/after slider support, but it only takes a little bit of JavaScript to make that happen.
010 1