Astro + Tailwind source for the Abstract Machines website and blog.
- Astro (v5)
- Tailwind CSS
src/pages/: Routes (Astro pages).src/components/: Shared UI components.src/layouts/: Page layouts.src/styles/: Identity stylesheets (identity-*.css) shared by the layout and pages.src/content/blogs/: Blog posts (Markdown).src/content.config.ts: Blog frontmatter schema.public/: Static assets (images, favicons, etc).
npm install
npm run devAstro runs on http://localhost:4321 by default.
During development, images and videos missing from public/ are fetched from
https://www.absmach.eu, so the logo and background animations work without local
R2 credentials. An internet connection is required for these assets.
The applied AI design is the public website at http://localhost:4321/.
It uses AM blue, self-hosted typography, a full-screen Paris architecture film,
and editorial photography.
/: homepage, selected work, and product catalogue./products/: searchable AI, Infrastructure, and Hardware categories./products/{slug}/: eleven product pages, including Propeller./research/and/research/{elastic,confidential6g}/: research programmes./company/: company background and engineering approach./stories/{nokia,intel,ericsson,target}/: sourced engineering stories./contact/: enquiry form with product and topic preselection.
The contact form submits to the existing /api/contact endpoint. SMTP settings
and delivery requirements are described below. Local browser checks should
intercept submissions rather than sending real mail.
The former /preview/ai/ page routes redirect permanently to the public pages.
Existing product URLs continue to resolve; /synth, /projects, and the two
project detail URLs redirect to their new counterparts. Redirects cover both trailing-slash forms and are excluded
from the sitemap. Public pages have canonical URLs, social metadata, and no
preview-only indexing restriction. Blog posts, guides, solutions, pricing,
legal pages, RSS, and documentation remain available at their existing URLs.
IdentityLayout.astro owns the main navigation, footer, and public metadata.
The product catalogue lives in src/data/identity-products.ts; product pages
and portfolio cards share ProductVisual.astro. The homepage and portfolio
show four AI products, four Infrastructure products, and three Hardware products.
Product tabs, category search, mobile navigation, video controls, and media credits work across the public pages. The silent video pauses offscreen and when the tab is hidden. Reduced-motion and Save-Data preferences keep the still poster until the visitor chooses to play.
Existing media URLs remain at public/preview/ai/media/ to preserve asset
caching. The optimized Paris film is approximately 2.9 MB; editorial photos are
WebP. src/data/identity-photos.ts supplies image attributes from the manifest
used by the footer credits. Attribution and source/license records are in
video-source.json and photos-sources.json. Product imagery and artwork are
recorded in media/products/sources.json; project, story, and membership
provenance is stored in their respective media folders. Font licenses and
source records remain in public/preview/ai/fonts/.
npm run build
npm run check:site
npm run previewUse the package scripts for Pages Functions workflows:
npm run cf:dev
npm run cf:deploycf:dev: Builds the site and starts local Pages dev server fromdist/usingwrangler.jsonc.cf:deploy: Builds and deploysdist/to theabsmachCloudflare Pages project usingwrangler.jsonc.
Note: wrangler pages deploy does not accept compatibility flags as CLI arguments. Keep them in wrangler.jsonc and in Cloudflare Pages project settings.
wrangler.jsonc (project config):
name: Cloudflare Pages project name (the*.pages.devsubdomain).pages_build_output_dir: deploy output directory (./dist).compatibility_dateandcompatibility_flags(for examplenodejs_compat) for Functions runtime.vars: non-secret defaults for Functions (for contact form, useTEAM_CONTACT_EMAILandMAIL_FROM_EMAIL).
Wrangler automatically reads wrangler.jsonc when commands are run from the project root.
The contact page submits to POST /api/contact via src/pages/api/contact.js.
The endpoint uses nodemailer over SMTP (Google SMTP supported).
Each successful submission sends:
- one email to your team inbox (
TEAM_CONTACT_EMAIL) - one confirmation copy to the user who submitted the form email
Request payload fields:
nameemailmessage
Required environment variables:
SMTP_HOST: SMTP server host (for Google:smtp.gmail.com).SMTP_PORT: SMTP server port (465for SSL,587for STARTTLS).SMTP_SECURE:truewhen using SSL port (usually465), otherwisefalse.SMTP_USER: SMTP username (for Google: full Gmail/Workspace email).SMTP_PASS: SMTP password (for Google: app password).MAIL_FROM_EMAIL: From address used when sending both emails.TEAM_CONTACT_EMAIL: Team inbox that receives contact requests.
For local smtp4dev testing (Docker -p 2525:25), use:
SMTP_HOST=127.0.0.1
SMTP_PORT=2525
SMTP_SECURE=false
SMTP_USER=
SMTP_PASS=
MAIL_FROM_EMAIL=info@absmach.eu
TEAM_CONTACT_EMAIL=info@absmach.euSMTP_USER and SMTP_PASS are optional for local test servers.
For Cloudflare Pages production:
- Non-secret values are already in
wrangler.jsoncundervars:SMTP_HOST,SMTP_PORT,SMTP_SECURE,MAIL_FROM_EMAIL,TEAM_CONTACT_EMAIL. - Set only SMTP credentials as secrets on the project:
wrangler pages secret put SMTP_USER
wrangler pages secret put SMTP_PASSBackward compatibility: NO_REPLY_EMAIL, CONTACT_FROM_EMAIL, and CONTACT_TO_EMAIL are still accepted, but new projects should use MAIL_FROM_EMAIL and TEAM_CONTACT_EMAIL.
Production does not use .dev.vars.
.dev.varsis local-only forwrangler pages dev.- For production, configure values in Cloudflare Pages: Dashboard -> Pages -> your project -> Settings -> Variables and Secrets -> Production.
- No separate production env file is required in the repo.
For local Cloudflare Pages function testing, copy .dev.vars.example to .dev.vars and fill the values.
nodemailer requires Node compatibility in Cloudflare Workers. Enable nodejs_compat:
- In Cloudflare Pages project settings: Workers runtime compatibility flags.
- Or in local dev:
wrangler pages dev dist --compatibility-flag=nodejs_compat.
Images are served from Cloudflare R2 (not committed to this repo) via
src/pages/img/[...path].ts, which keeps existing /img/... URLs working unchanged.
Maintainers publishing new/updated images: see scripts/README.md.
See WRITING.md for frontmatter and writing guidelines.
@astrojs/sitemapgeneratesdist/sitemap-index.xml(and chunk files likedist/sitemap-0.xml) duringnpm run build.src/pages/robots.txt.tsis prerendered as/robots.txtand points to/sitemap-index.xml.
src/pages/rss.xml.tsis prerendered as/rss.xml(blog feed).