Landing¶
The marketing site at towitlinks.com, in landing/. It is a separate application from the
agent console and shares no code with it.
Stack¶
SvelteKit 2 on Svelte 4, built with Vite 5 and TypeScript, styled with Tailwind 3 plus
Flowbite (landing/package.json:14-45). Forms use sveltekit-superforms with Zod;
sveltekit-i18n provides English and Spanish; svelte-seo handles metadata;
libphonenumber-js validates phone input.
The adapter is @sveltejs/adapter-node (landing/svelte.config.js:1,14) — this is a
Node SSR server, not a static export. adapter-auto is still a devDependency but unused.
landing/wrangler.jsonc is dead configuration
It names a worker dev-landing with assets.directory: "./build/" and no main
(landing/wrangler.jsonc:7-15). wrangler is not a dependency, no workflow invokes it,
and adapter-node does not emit a Workers asset tree. An identical vestigial file sits
at frontend/wrangler.jsonc. Both arrived in commit d4184849, apparently from the
abandoned feature/ssr-cloudflare branch. The landing is served by a Docker container
behind nginx, not by Cloudflare.
Content¶
One marketing page (landing/src/routes/+page.svelte) composed of Presentation, Features,
Engagement, desktop and mobile Carousels, Setup, Pricing, Services, FAQ and Footer, plus
legal/, legal/policy/ and legal/terms/.
+layout.server.ts resolves the locale from a lang cookie, falling back to
Accept-Language.
It talks to production¶
landing/src/routes/+page.server.ts defines two form actions, contact and feedback,
which POST server-side to https://app.towitlinks.com/api/v1/landing/contact and
.../landing/newsletter (:9,42,74). The URL is hardcoded, so a landing instance running
anywhere — including a developer's laptop — submits against production. Keep that in
mind when testing forms.
Styling¶
landing/tailwind.config.ts defines a custom primary cyan palette, a red ramp that is
actually orange, and brand tokens landing-header, landing-paragraph and
contact-paragraph built on rgba(5,47,71,…). It adds breakpoints xs through xs5 and
3xl, and loads the flowbite/plugin and @tailwindcss/typography plugins.
Fonts — Khula, Mada, Open Sans and Over the Rainbow — are self-hosted in
landing/static/fonts/. Google Analytics runs as G-FLQR7VQLVM
(landing/src/lib/components/analytics.svelte:6,16).
How it ships¶
The root Dockerfile — not landing/Dockerfile, which does not exist — builds this app:
a two-stage Node 18 Alpine build that installs from landing/package.json, runs
npm run build, then copies landing/build into a runtime stage and serves it with
pm2-runtime index.js on port 3000. The root docker-compose.yml runs that single
voip-landing-page container, and landing.nginx proxies
towitlinks.com and www.towitlinks.com to 127.0.0.1:3000.
Because the Dockerfile sits at the repository root, the whole monorepo is the build
context, and the image also copies frontend/ for no reason (Dockerfile:14-15).
The package manager is pnpm locally (pnpm-lock.yaml), but the Docker build runs
npm install. The lockfile therefore does not constrain production builds.