Olympus Tents & Events

Off Manus, onto our own stack

Eleven applications were rebuilt to run without Manus, which is being shut down. Every one is live below on a staging subdomain. The production cutover — pointing the real addresses at the new sites — is the last step, and it is described in section 01.

11Apps live
48Files rescued
456DB rows restored
20.9kLines removed
~$30Per month

01The production cutover

Everything below runs on staging addresses. The real addresses — the olympustentsandevents.com subdomains customers actually visit — still point at Manus and will die with it. Moving them is a DNS change, made by hand in Squarespace, which is where that domain's records live. Cloudflare hosts the staging domain only; it has no control over the live one.

Nine records change, and every one gets the same new value. One record is deleted.

SubdomainChange its Data field toServes
tentscname.vercel-dns.comTent rentals
tables-chairscname.vercel-dns.comTables & chairs
dinnerware-tabletopscname.vercel-dns.comDinnerware
thank-youcname.vercel-dns.comLead conversion page
privacycname.vercel-dns.comPrivacy policy
terms-conditionscname.vercel-dns.comTerms & conditions
deliverycname.vercel-dns.comDelivery calculator
timecname.vercel-dns.comTime clock
appcname.vercel-dns.comDocument library
invitationDelete the recordRetired — the Vantage launch RSVP, event has passed

Leave every other record alone. The appmail records, both mail exchangers, the SendGrid and Mailgun entries and www have nothing to do with Manus, and changing them breaks email.

Do this before cutting over the tents page

The tents lead form is the one thing that will be worse after the move than before it. Its GoHighLevel webhook address was stored in Manus's settings rather than in the code, so it did not come across — and the setting is currently empty on the new hosting. Submitting the form returns an error instead of creating a lead.

The other three forms are unaffected: dinnerware, tables & chairs and the Vantage each have their webhook address written into the code, and they work.

Fix: get the tents webhook URL from GoHighLevel and add it as GHL_WEBHOOK_URL to the tents project settings. Until then, either hold the tents record back and change the other eight, or accept that tent enquiries bounce in the meantime.

What to expect

Records carry a 30-minute lifetime, so allow up to an hour. HTTPS certificates are issued automatically once an address resolves — a brief security warning in the first minutes after a record flips is normal and clears itself.

Nothing else needs doing on the hosting side. All nine addresses are already registered against their applications and ownership-verified, so each site answers the moment its record propagates.

The Vantage is a separate job

thevantageatolympus.com is also still on Manus, but it is not in the Squarespace panel — it is on Cloudflare, in an account separate from the one holding the staging domain. It needs its two addresses registered against the Vantage application first, then its own DNS records changed, with Cloudflare's proxy switched off so certificates can be issued. Full instructions were provided separately.

02The sites

All eleven run on *.staging.aetenum.com. Staging hosts are marked noindex so Google will not index them alongside the live sites; the production domains are served indexable.

Before you click through

Two things are still incomplete, both waiting on credentials rather than code: the tents lead form needs its GoHighLevel webhook URL, and the time clock's Google Calendar and QuickBooks connections need their OAuth keys re-issued. Everything else is working.

The time clock and the document library share one staff login, so the same email and password opens both. If you have never been invited to the document library, it will say so and point you at HR rather than showing you an error.

The three newest sites — thank you, privacy and terms — were rebuilt on 14 August from Manus exports and had never been part of this set before.

03What we were handed

Manus is shutting down. What survived was seven private GitHub repositories and nothing else — no running servers, no database, no environment settings, no admin console. The job was to make all seven run again on infrastructure we control, and to prove each one actually works rather than merely loads.

The repos turned out to be seven copies of one Manus scaffold: a React front end, an Express back end, and a folder called server/_core holding Manus's own platform code. That sameness was the single biggest advantage in the whole project — nearly every fix, once found, applied to all seven.

An eighth application surfaced afterwards — the internal document library — delivered as a full export rather than a repository: source code, a database dump, and the uploaded files downloaded out of Manus's storage. It runs on the same scaffold, so the work already done carried straight over; what it added was a second set of real business data to move, and a genuinely new problem described in section 07.

Three more surfaced when the live DNS records were finally read: the privacy policy, the terms and conditions and the thank you page were each a separate Manus site on its own subdomain, not pages inside another site as everyone assumed. They arrived as three more exports and were rebuilt the same way, bringing the total to eleven. Two of the three mattered more than their size suggests:

A fourth subdomain, invitation, held the RSVP site for the Vantage launch event in May. The event has passed, so it is being retired rather than rebuilt.

The scaffold was hiding how simple most of them were

On the surface, six of the seven looked database-backed. They shipped a database schema, a database driver, and login plumbing. Looking closer, the schema in five of them was untouched boilerplate that still ended with the generated comment // TODO: Add your tables here, and no page in any of those apps had a login screen.

So the databases were decoration. Removing that dead weight meant five apps needed no database at all — no hosting bill, no credentials, no backups, nothing to break. Of the original seven, only the time clock was a real application; the document library that arrived later is the second.

ApplicationWhat it actually needs
Dinnerware, Tables & Chairs, BrandStatic pages. The server only handed out files.
Privacy, Terms, Thank YouStatic pages. Single-page sites with no server role at all.
Tents, Delivery, VantageStatic pages plus a single API call each.
Time ClockFull application: real data, logins, Google Calendar, QuickBooks.
Internal Docs HubFull application: real data, logins, file storage, AI quiz generation.

04The awkward parts of the Manus export

The exports were complete in the sense that the source code was all there. They were incomplete in every way that matters for actually running the software. Each of the following would have produced a site that looked fine in testing and then quietly broke.

Every page carried 367KB of hidden Manus editor code

The build quietly injected a large script into every page — a second copy of React, a design-preview overlay, and a listener that let an embedding page set browser cookies. That last part is a genuine security concern on a public site, and none of it had any purpose outside the Manus editor.

Removed from production builds. The home page's HTML went from 369,928 bytes to 2,960 — about 99% smaller — and builds got roughly three times faster.

The photographs were not in the repositories

The sites loaded their imagery from Manus-owned servers. Those addresses work today and would have stopped working at shutdown, taking every photo on every site with them. Worse, the tents page was already broken — its four hero images were on temporary Manus URLs that had expired before we started.

All 32 images are now stored in the repositories and served from our own hosting. Nothing points at Manus.

The Vantage gallery was behind a Manus-only door

The ten styled-shoot photographs were fetched through a Manus storage service that required a Manus API key to unlock. With Manus gone, they were unreachable — the single most likely thing to be lost for good.

The same ten images were found in the repository's own assets/gallery/ folder. The export notes said they were stored "in display order," and every photo's caption text matched its filename exactly, so the pairing was confirmed rather than guessed. The gallery is intact.

Six-megabyte photographs

The tent hero images were full-resolution files of about 6.5MB each — roughly 26MB for one page. On a phone that is a very slow page and a real cost to whoever loads it.

Re-encoded to modern WebP at sensible dimensions: 25.8MB down to 0.92MB, a 96% reduction with no visible difference. The tables page dropped from 2.77MB to 0.35MB. The untouched originals are kept in the repositories.

Broken analytics and code that never compiled

Each page tried to load a Manus analytics script; with Manus's settings gone it requested a nonsense address on every visit. Separately, the projects did not pass their own type checks — the tents app shipped with eight errors, including a file that imported the same thing twice and a login screen calling a server function that did not exist.

Analytics tag removed; all eight errors resolved. Every project now type-checks cleanly and its tests pass.

The database was a MySQL cousin, not MySQL

The time clock's data came out as a single 274KB export file, produced by TiDB — a MySQL-compatible database, but not identical. Exports like this often need hand-editing before another database will accept them.

This one did not. Its TiDB-specific markers are written in a comment style that ordinary MySQL ignores, so it imported unmodified: 9 tables, 169 rows — 48 employees, 109 jobs, historical time entries and settings, all intact.

05The new setup

Everything was deliberately created fresh under aaron@olympustentsandevents.com, kept separate from any personal accounts, so ownership and billing sit with the business.

ServiceRoleCost
VercelHosts all eleven applications, plus file storage for the document library; rebuilds automatically on every code change.~$20/mo
RailwayOne MySQL database each for the time clock and the document library, kept separate so an incident with one cannot affect the other. The other nine need none.~$10/mo
ClerkStaff logins, shared by the time clock and the document library — one password for both.Free tier
AnthropicWrites quiz questions from an uploaded document. Charged per use, only when someone uses it.Pennies
CloudflareStaging domain only; eleven subdomain records. It has no control over the live domain.No change
SquarespaceHolds the DNS for the live domain. Where the cutover in section 01 happens.No change

Roughly $30 a month for all eleven — the three sites added last are static pages and cost nothing extra to host. The Vercel paid tier is not optional: its free plan forbids commercial use, and the time clock's automatic calendar sync needs scheduling that only the paid tier allows.

What changed inside the code

06Rebuilding the time clock

This was the only genuinely difficult application, and the only one with real business data at stake.

Logging in

Staff signed in through Manus's own login service. There was no way to keep that, so it was replaced with Clerk.

The risk in swapping a login system is losing the connection between a person and their history. Here the numbers made it manageable: the database held 48 employees but only 2 user accounts — only two people had ever actually logged in; the rest exist as employee records. The new system matches people by email address, so those two accounts keep their identity, their admin rights, and their attached time entries.

Helpfully, the whole application asks "who is this?" in exactly one place in the code, so the swap touched one file rather than being spread across the app.

The automatic calendar sync

The app pulled jobs from Google Calendar every 15 minutes using a timer inside the always-on server. On-demand hosting has no always-on process for a timer to live in, so the sync now runs as a scheduled task that calls the application on the same 15-minute cadence. The sync logic itself is untouched — only what starts it changed. The endpoint is protected by a secret, and refuses unauthorized calls.

The data

Restored into the new database and verified row by row. One deliberate detail: the export file contains employee names, hours and location data, so it is explicitly excluded from anything deployed to the web. It stays in the repository for recovery only.

07The document library

The eighth application is where staff read handbooks and SOPs, sign to say they have read them, and take a short quiz to confirm it. It carried 287 rows of real records: 12 staff, 12 signed acknowledgements, and 33 quiz attempts across 40 questions. All of it restored and verified row by row.

Three Manus services were doing real work inside it, and each needed a genuine replacement rather than deletion.

What Manus providedReplaced with
Staff loginClerk — the same login as the time clock, so staff have one password for both
File storage for documents and signaturesVercel Blob, on our own hosting
An AI that reads a document and writes quiz questions from itAnthropic's API, called directly

The signatures were the thing most at risk

Every handbook, every uploaded video and all twelve signed acknowledgements lived on Manus's file storage. The database recorded where each one was, and every one of those addresses pointed at a Manus server. They work today; at shutdown all twelve signatures — the actual evidence that a named employee accepted a policy on a given date — would have become dead links, with the records still claiming they existed.

All 16 files were re-uploaded to our own storage under the exact same filenames the database already referenced, so only the addresses changed. A check afterwards confirmed no record anywhere still points at Manus, and that every file is a real PDF or image rather than an error page wearing one's clothes.

One login for two apps, which needed a door on it

Sharing the time clock's login is convenient for staff, but it has a consequence worth being explicit about: it means anyone who can clock in can also reach the document library. And the app's own default was to give a new arrival the "sales" department, which would have shown them every document marked as company-wide — which is the default setting, and is set on both handbooks.

So signing in and being allowed in were separated. A person who has never been invited now gets an account with no access at all and a plain message telling them to ask HR for an invite link. The check sits at the lowest level of the app rather than on each page, so any screen added later is closed by default instead of relying on someone remembering to lock it. The twelve existing staff were admitted automatically and notice nothing.

What it means for the bill

The document library runs on its own database, separate from the time clock, so an incident with one cannot take out the other. That is the $5 difference between the old figure and the new one.

08Problems hit along the way

Five things broke that no amount of local testing would have caught, because each only appears in real hosting.

Every API crashed the moment it was deployed
ERR_MODULE_NOT_FOUND: Cannot find module '/var/task/server/app'

The three sites with APIs worked perfectly on a laptop and failed instantly in production. The development tools are lenient about how files reference each other; the production runtime is strict. Nothing in local testing could reveal it — builds, type checks and tests were all green.

Corrected across all four affected projects.

Deployments silently refused to run
BLOCKED — TEAM_ACCESS_REQUIRED

Deployments kept landing in a "blocked" state with no error message. Two separate causes: the account was still mid-upgrade, and then Vercel's rule that whoever authored a code change must be a member of the paid team — the changes were being authored under a personal identity.

Upgrade completed and authorship corrected to the business account.

Missing images reported themselves as working

An early check pronounced every image healthy. It was wrong. These sites answer unknown addresses with the home page rather than an error, so a missing image still replies "200 OK" — it just replies with a web page instead of a picture. Checking the status alone made deleted files look present.

Re-checked by asking what each address actually returned, not whether it answered. That immediately exposed four broken tent images and eleven broken Vantage gallery photos. Every image on every site is now confirmed to be a real image.

A file-exclusion rule that was too greedy

To stop 171MB of original photographs being uploaded on every deployment, they were excluded by folder name — which also matched a different folder of the same name that the sites genuinely needed, quietly deleting the tents logo and favicon.

The rule now points at one specific folder. Self-inflicted, caught by the same verification pass.

Every site was set to hide itself from Google

To keep the staging copies out of search results while they were being reviewed, each site was told to instruct search engines not to index it. That instruction was attached to the site rather than to the staging address — so the moment a real address pointed at one, the live marketing pages would have carried it too, and Google would have removed them from search. The sites would have looked perfect and quietly disappeared from results over the following weeks.

The instruction is now conditional on the address being a staging one. Verified rather than assumed: a throwaway non-staging address was pointed at one of the sites, and confirmed to receive no such instruction while the staging address still did. It was removed afterwards. The tents, tables & chairs, dinnerware and Vantage sites all carried this; the internal tools keep it deliberately, and the thank-you page keeps it too so it cannot be found in search and fire false conversions.

The exports contained live credentials

Two of the three newest exports shipped a settings file holding working cloud access keys, an interface key and a signing secret in plain text. This is the same thing the document library's export did earlier. Anyone with a copy of the zip had those credentials.

Deleted before anything was committed, and the file is on the ignore list in every repository so it cannot be added by accident. The keys themselves should be treated as compromised — they were readable by anyone who handled the file.

Links and page addresses pointing at nothing

Several footer and navigation links pointed at main-site pages that return "not found" — /tents, /tabletop, /contact. Separately, the dinnerware site declared its own official address as dinnerware.olympustentsandevents.com, which has never existed; the real one is dinnerware-tabletops. Left alone, that tells Google the page's canonical home is an address that cannot be reached.

Links repointed at the pages that do exist and each one re-checked. Address declarations corrected on dinnerware and added to tents and the Vantage, which had none at all.

HTTPS certificates on two-level subdomains

Cloudflare's automatic certificates cover name.aetenum.com but not name.staging.aetenum.com. Left at the default, every one of these addresses would have shown a browser security warning, and the usual fix is a $10/month add-on.

Routing the traffic slightly differently lets the host issue the certificates instead, at no cost. Anticipated before the first record was created, so it never became a visible problem.

09How each one was checked

"It loads" is not proof. Every claim above was tested against the live addresses:

10What is left

ItemEffectNeeded
The DNS cutoverUntil it happens, customers still reach the Manus sites, which die at shutdownThe nine record changes and one deletion in section 01, made in Squarespace
GoHighLevel webhook (tents)Lead form returns an error instead of creating a lead. Worth fixing before the tents record is cut overThe webhook URL from the GHL account, added as GHL_WEBHOOK_URL
The Vantage domainthevantageatolympus.com still points at ManusIts two addresses registered, then its Cloudflare records changed with the proxy off
Google & QuickBooks keysCalendar and accounting sync are off; clocking in/out is unaffectedRe-issue from Google and Intuit
Clerk production keysCurrently on development keys — fine for review, not for daily staff use. Affects the time clock and the document libraryPromote now that the permanent addresses are settled
Exposed export credentialsCloud and interface keys shipped in plain text inside three Manus exportsRotate them; they were readable by anyone who handled the zips
Google Ads conversion labelAds counts leads through the imported analytics conversion, which works. Firing an Ads conversion directly would be more preciseThe conversion label from Google Ads — optional, and must not be added alongside the current setup or leads double-count
Diesel priceQuotes use a rate checked into the code (the Utah AAA diesel average on 14 Aug 2026) because AAA blocks automated lookupsNothing, unless the rate drifts — it is overridable per deployment and editable on the quote itself
Document library file privacyFiles sit at long, unguessable web addresses, matching how Manus did it. Anyone holding a link can open it without signing inA decision on whether that is acceptable; locking it down is a known, contained change
Word documents in the quiz builderThe AI quiz generator reads PDFs, text and images. A Word file is refused with a clear message rather than mangledSave as PDF before uploading, or a small conversion step