Skip to content
TAA

Article

Civo Cloud Manager: 16 Languages, a New Icon, and a Paywall

This week I shipped a seven-day free trial, localized Civo Cloud Manager into 16 languages, and rebuilt the marketing site from scratch. Here is what that actually involved.

September 14, 2026, Marcel R. G. Berger, 6 min read

  • macos app development
  • civo-cloud-manager
  • swift
  • swiftui
  • build-in-public
  • localization
Share

Midweek I pushed the new green Cloud Shield icon to the repo. By the end of the week the marketing site had six additional language routes, the price had come off the page entirely, and the app itself had a working seven-day free trial behind a fully localized paywall. That is the short version. The long version involves a Keychain edge case that took me two attempts to get right, a legal identity migration I had been putting off, and a deliberate decision to remove a number from the website that I had spent time calculating in the first place.

This week was almost entirely Civo Cloud Manager, a native macOS app I am building for developers who run workloads on Civo Cloud. Kubernetes live dashboard, S3 file browser, menu-bar firewall, Touch-ID-protected credentials. Swift 6, SwiftUI, zero third-party dependencies. You can read more about it on the app page.

macOS App Development in Full: What Shipped This Week

The Free Trial and the Paywall

The biggest functional change was adding a seven-day free trial. This sounds simple. It is not. StoreKit 2 handles the trial period on Apple’s side, but the paywall UI (every label, every help row, every confirmation string) still has to be written and localized by hand. I had to be careful to separate the network management features from the firewall features in the paywall itself, because they are distinct capabilities with different upgrade paths. Getting that distinction clear in English is one thing. Getting it clear in Japanese or Arabic is another.

I ran the full localization through sixteen languages: the standard European set plus Japanese, Korean, Simplified Chinese, Traditional Chinese, and Arabic. Every purchase help row, every quota editor label, every CPU core unit string: all of it localized. The CPU core unit string is a good example of where this gets fiddly. In German it is “Kerne”, in Japanese it is “コア”, and the surrounding sentence structure is completely different. You cannot just slot a translated word into a fixed string template. Each language needs its own phrasing. I used build-based localization validation to catch missing keys before they reach users rather than after.

The Keychain and TLS Changes

Two lower-level fixes this week that I want to name explicitly, because they are exactly the kind of thing that never shows up in a changelog but matters a lot.

First: the app now preserves SSH encryption keys when Keychain access fails. Previously, if Keychain access was denied or unavailable, the key would be silently lost. That is a bad failure mode. Quiet data loss is always worse than a visible error. The fix was to hold the key in memory long enough to retry or surface the failure cleanly, rather than dropping it at the first sign of trouble.

Second: Kubernetes server certificate validation. The app now validates server certificates before accepting TLS trust, rather than accepting a connection and checking afterward. I should have had this stricter from the start. I did not. The commit is there in the history, and I am not going to dress it up as a planned improvement. It was a gap I closed.

Firewall Persistence

The firewall module got two changes that are related but distinct. First, the app now persists firewall closure deadlines across restarts. If you set a rule and then quit the app, the deadline survives. Before this week, it did not: a restart would silently forget when a firewall rule was supposed to expire. Second, failed firewall rule deletions are now retried automatically, and manual retry resets are flushed to disk before the error state is cleared. This second part took me two attempts to get right. The first version reset the error state optimistically before confirming the flush had completed. That introduced a window where the UI looked clean but the persistent state was still dirty. I caught it in testing, reverted, and restructured so the flush completes before the reset fires.

The Marketing Site

The marketing site for Civo Cloud Manager got a significant rebuild in parallel. The accent color moved from orange to Civo’s own brand lime. Obvious in retrospect, and I am mildly annoyed I shipped orange at all. The app icon was updated to match the new Cloud Shield design. A dead mockup that had been sitting in the page was finally removed. The site now ships all language routes with the full topic cluster rather than a subset, and I added six new language routes to match the app’s expanded localization.

The most deliberate change was the last commit of the week: I removed the price from the website. I had a specific price displayed on the marketing site, and I took it off this week. The reason is straightforward. The app now has a free trial. The price is visible inside the app via the paywall, which is exactly where the decision context is. Showing a number on a webpage before someone has even launched the app is asking them to evaluate cost before value. That is the wrong order. The price is still the same. It is just no longer the first thing a visitor sees.

Side Notes

I migrated the app’s legal identity to DigitalFreedom Global LLC this week, which touched the privacy policy, terms of service, and all localized legal documents. Sixteen languages means sixteen versions of updated legal text. The regression tests now specifically catch reordered legal dates, a subtle failure mode where a translated date string ends up in the wrong sequence and the document reads as if the effective date comes after the updated date. It sounds like a corner case. It is the kind of thing that causes problems with App Review.

Architecture Diagrams

I updated the internal architecture diagrams and aligned the in-app help text with current behavior. This is maintenance work that accumulates if you ignore it. The diagrams were showing the request routing before I fixed the duplicate-parameter bug in the Civo region resolver. Small thing, but wrong diagrams are worse than no diagrams.

If You Are Considering a Native macOS App

Weeks like this one are a good illustration of what native macOS app development actually involves at a professional level. The feature work (trial, paywall, new icon) is visible. The certificate validation, the Keychain failure handling, the localization regression tests: that is the invisible layer that keeps the app from failing users quietly. If you are a business considering a custom macOS or iOS app, I am happy to talk through what that scope looks like for your use case.

The Civo Cloud Manager app is available on the Mac App Store. The repository is public at github.com/marcelrgberger/civo-cloud-manager if you want to see the code behind any of the above.

Share