Skip to content

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.