Standalone Astro marketing site with React islands, styled with Tailwind v4 and deployed to Cloudflare Pages. See MAINTENANCE.md for the architectural overview and AGENTS.md for contributor conventions.
- Node.js 20+ and pnpm
pnpm install
pnpm dev # Astro dev server on http://localhost:3000To exercise the contact-form API route locally (Cloudflare Pages Functions), run
the Wrangler dev server instead, which loads .dev.vars:
pnpm build
pnpm wrangler pages dev ./distpnpm run verify # eslint + astro check (types) + astro buildRun this before every commit and deploy.
The contact form posts to /api/contact, handled by
functions/api/contact.ts. It emails submissions via
Resend and includes a honeypot field for spam protection.
The endpoint returns HTTP 503 until all three secrets below are set.
| Variable | Purpose |
|---|---|
RESEND_API_KEY |
Resend API key (re_…) |
CONTACT_TO_EMAIL |
Inbox that receives submissions |
CONTACT_FROM_EMAIL |
Verified Resend sender address (its domain must be verified) |
Setup steps:
- Create a Resend account and verify your sending domain (add the DNS records Resend provides to your DNS host).
- Generate an API key.
- Local: copy .dev.vars.example to
.dev.varsand fill in the values..dev.varsis gitignored — never commit secrets. - Production: in the Cloudflare dashboard, go to your Pages project → Settings → Environment variables and add the three keys as encrypted secrets for the Production (and Preview) environments.
Optimized WebP variants live in public/ and are committed directly, so the build needs no image tooling. They were generated with sharp:
pnpm run optimize:imagesThe committed assets are:
- Hero background —
cube27-bg.webp(1600px master) plus downscaled tierscube27-bg-640/960/1280.webp, wired up viasrcset/sizesin the hero. - Logo —
cube27_logo.webp, used both for on-page display and as the schema.org structured-data logo. - Partner logos —
images/logos/opt/{n}.webpfor the Trusted Partners marquee, whitespace-trimmed so each mark fills its frame (no card chrome). - Life at Cube27 photos —
images/office/opt/life-NN.webp(ordered numerically) for the culture gallery.
The heavy source masters (original logo PNGs, office JPGs) have been removed
from the repo to keep it lean — the optimized opt/*.webp are now the assets of
record. To add or re-optimize images, drop the source files back into
public/images/logos/ or public/images/office/ and re-run the script; it
regenerates the hero tiers from cube27-bg.webp and skips any step whose source
is absent. If you change the number of images, update the count on
<PartnerMarquee> (home) and <LifeAtCube27> (about) accordingly.
Push to the connected GitHub repository; Cloudflare Pages builds and deploys
automatically. Build output is ./dist (see wrangler.jsonc).
- HTTPS/SSL: Cloudflare provisions Universal SSL automatically for
*.pages.devand for custom domains once they are added and their DNS is proxied through Cloudflare — no certificate upload is required in the standard case. - Custom domain: add
www.cube27.comunder the Pages project's Custom domains tab. Thesitevalue in astro.config.mjs is already set tohttps://www.cube27.com(used for canonical URLs, the sitemap, and structured data).