astro cloudflare pages moklabs portfolio
Research: Astro 5.x + Cloudflare — Multi-Product Portfolio Site for moklabs.io
MOKA-346 | Priority: Medium | Project: Research Date: 2026-03-20 Author: Deep Research Agent Supports: moklabs.io Landing Page — Build and deploy Astro site
Executive Summary
moklabs.io needs a multi-product portfolio site showcasing 6 AI products. This report covers Astro 5.x architecture, Cloudflare deployment (Pages vs Workers), performance optimization, SEO setup, and messaging patterns for AI venture studios.
Key Decision: Deploy as Astro static site on Cloudflare Workers (not Pages — Astro adapter dropped Pages support in 2026). Use Content Collections for product data and Cloudflare Web Analytics + Zaraz for privacy-friendly analytics.
1. Astro 5.x Architecture for Multi-Product Sites
1.1 Why Astro for moklabs.io
- Zero JS by default — Pure HTML output, instant page loads
- Islands Architecture — Interactive components only where needed (product demos, animations)
- Content Collections — Type-safe structured data for products, team, blog
- 5x faster builds in Astro 5.0 vs 4.x (Content Layer API)
- 25-50% less memory during build
- Native image optimization — WebP/AVIF generation, responsive sizes
1.2 Content Collections Structure
src/
├── content/
│ ├── products/
│ │ ├── argus.md
│ │ ├── octantos.md
│ │ ├── remindr.md
│ │ ├── narrativ.md
│ │ ├── neuron.md
│ │ └── agentscope.md
│ ├── team/
│ │ └── ...
│ └── blog/
│ └── ...
├── content.config.ts
└── pages/
├── index.astro # Hero + product grid
├── products/
│ └── [slug].astro # Product detail pages
├── about.astro
├── blog/
│ ├── index.astro
│ └── [slug].astro
└── contact.astro
1.3 Product Content Schema
// src/content.config.ts
import { defineCollection, z } from 'astro:content'
import { glob } from 'astro/loaders'
const products = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/products' }),
schema: z.object({
name: z.string(),
tagline: z.string(),
description: z.string(),
category: z.enum(['security', 'developer-tools', 'productivity', 'creative', 'ai-infra', 'knowledge']),
status: z.enum(['launch-ready', 'beta', 'mvp', 'phase-0']),
icon: z.string(),
color: z.string(),
features: z.array(z.object({
title: z.string(),
description: z.string(),
})),
cta: z.object({
text: z.string(),
url: z.string(),
}),
order: z.number(), // GTM priority order
}),
})
export const collections = { products }
2. Cloudflare Deployment
2.1 Pages vs Workers (Critical Decision)
As of 2026, the Astro Cloudflare adapter (@astrojs/cloudflare) no longer supports Cloudflare Pages. Cloudflare recommends Workers for new projects.
| Feature | Cloudflare Workers | Cloudflare Pages (Legacy) |
|---|---|---|
| Astro adapter support | Yes (current) | No (dropped in 2026) |
| Static sites | Yes (assets directory) | Yes |
| SSR/on-demand | Yes (full support) | Limited |
| Preview deploys | Via Wrangler | Built-in with GitHub |
| Custom domains | Yes | Yes |
| Web Analytics | Yes | Yes |
| Build-in CI/CD | No (use GitHub Actions) | Yes (GitHub integration) |
Recommendation for moklabs.io:
- Static site (SSG) — No adapter needed, deploy directly via Wrangler
- Deploy to Cloudflare Workers with assets
- Use GitHub Actions for CI/CD (build +
wrangler deploy)
2.2 Deployment Setup
// wrangler.jsonc
{
"name": "moklabs-io",
"compatibility_date": "2026-03-01",
"assets": {
"directory": "./dist"
}
}
# .github/workflows/deploy.yml
name: Deploy to Cloudflare
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install
- run: pnpm build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy
2.3 Custom Domain Setup
# Add custom domain via Wrangler CLI
npx wrangler domains add moklabs.io
# Or configure in Cloudflare dashboard:
# Workers & Pages → moklabs-io → Settings → Domains
DNS (already on Cloudflare): Add CNAME moklabs.io → moklabs-io.<account>.workers.dev
3. Performance Optimization
3.1 Target: Lighthouse 95+ on All Metrics
| Metric | Target | Strategy |
|---|---|---|
| LCP | < 2.5s | Preload hero image, inline critical CSS |
| FID/INP | < 100ms | Zero JS default, islands only for interactive |
| CLS | < 0.1 | Explicit image dimensions, font-display: swap |
| TTFB | < 200ms | Cloudflare edge serving, static HTML |
3.2 Image Optimization
---
// Use Astro's built-in Image component
import { Image } from 'astro:assets'
import heroImage from '../assets/hero.png'
---
<!-- Above-fold: eager loading -->
<Image
src={heroImage}
alt="Moklabs AI Products"
width={1200}
height={630}
loading="eager"
format="avif"
quality={80}
/>
<!-- Below-fold: lazy loading -->
<Image
src={productImage}
alt={product.name}
width={600}
height={400}
loading="lazy"
format="webp"
/>
3.3 Font Optimization
---
// Use astro-google-fonts-optimizer or self-host
---
<head>
<!-- Self-hosted fonts (recommended for privacy + performance) -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-weight: 100 900;
font-display: swap;
}
</style>
</head>
3.4 Critical CSS
# Install critical CSS extraction
pnpm add -D critical
# Add to build pipeline (astro.config.mjs integration or post-build script)
4. SEO Setup
4.1 Essential Integrations
pnpm add @astrojs/sitemap astro-robots-txt astro-seo
// astro.config.mjs
import { defineConfig } from 'astro/config'
import sitemap from '@astrojs/sitemap'
import robotsTxt from 'astro-robots-txt'
export default defineConfig({
site: 'https://moklabs.io',
integrations: [
sitemap({
filter: (page) => !page.includes('/draft/'),
}),
robotsTxt(),
],
})
4.2 Meta Tags Template
---
// src/layouts/BaseLayout.astro
import { SEO } from 'astro-seo'
interface Props {
title: string
description: string
image?: string
}
const { title, description, image = '/og-default.png' } = Astro.props
const canonicalURL = new URL(Astro.url.pathname, Astro.site)
---
<html lang="en">
<head>
<SEO
title={`${title} | Moklabs`}
description={description}
canonical={canonicalURL.href}
openGraph={{
basic: {
title: `${title} | Moklabs`,
type: 'website',
image: new URL(image, Astro.site).href,
},
optional: {
description,
siteName: 'Moklabs',
},
}}
twitter={{
card: 'summary_large_image',
title: `${title} | Moklabs`,
description,
image: new URL(image, Astro.site).href,
}}
/>
<!-- JSON-LD Structured Data -->
<script type="application/ld+json" set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "Organization",
"name": "Moklabs",
"url": "https://moklabs.io",
"description": "AI venture studio building privacy-first products",
"foundingDate": "2026",
"sameAs": ["https://github.com/moklabs"],
})} />
</head>
4.3 Product JSON-LD
<!-- On product detail pages -->
<script type="application/ld+json" set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": product.name,
"description": product.description,
"applicationCategory": "SecurityApplication",
"operatingSystem": "macOS, Windows, Linux",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD",
},
"author": {
"@type": "Organization",
"name": "Moklabs",
},
})} />
5. Analytics Setup (Privacy-Friendly)
5.1 Cloudflare Web Analytics
Free, privacy-first, no cookies, GDPR-compliant by default.
Setup for Workers deployment:
- Go to Cloudflare Dashboard → Web Analytics
- Create a site for
moklabs.io - Get the JS snippet or beacon token
- Add to Astro layout:
<!-- src/layouts/BaseLayout.astro -->
<body>
<slot />
<!-- Cloudflare Web Analytics -->
<script
defer
src="https://static.cloudflareinsights.com/beacon.min.js"
data-cf-beacon='{"token": "YOUR_TOKEN"}'
/>
</body>
5.2 Zaraz (Optional — for additional tools)
Zaraz offloads third-party scripts to Cloudflare’s edge:
- Google Analytics without client-side GA script
- Meta Pixel, LinkedIn Insight, etc.
- Requires custom domain (moklabs.io)
- Enable in Dashboard → Zaraz → Settings
Note: Zaraz requires a custom domain associated with the project.
6. Messaging Framework for AI Venture Studio
6.1 Portfolio Site Messaging Patterns (from existing research)
Based on our earlier research on AI Venture Studio Portfolio Sites:
Hero messaging formula:
[What we build] + [Who benefits] + [Why it matters]
Example for Moklabs:
“Privacy-first AI products for teams that refuse to compromise. Six products. One mission. Your data stays yours.”
6.2 Product Grid Strategy
| Element | Pattern |
|---|---|
| Card layout | Icon + Name + Tagline + Status badge + CTA |
| Ordering | By GTM priority (Argus → OctantOS → Remindr → Narrativ → Neuron → AgentScope) |
| Status badges | ”Launch Ready”, “Beta”, “MVP”, “Coming Soon” |
| CTA hierarchy | Primary: “Try Argus” / Secondary: “Learn More” |
6.3 Trust Signals
- Open source — Link to GitHub repos (credibility for developers)
- Privacy-first — “All processing happens on your device” (differentiator)
- Built with AI — “Moklabs is an AI-native venture studio. Our agents write code, review PRs, and ship features.” (unique story)
- Real products — Show screenshots, demos, or GIFs (not just descriptions)
6.4 Page Structure Recommendation
Homepage:
├── Hero (tagline + product count + primary CTA)
├── Product Grid (6 cards, GTM order)
├── Philosophy/Approach (privacy-first, AI-native, open source)
├── Tech Stack / Architecture (for developer credibility)
├── Blog Preview (latest 3 posts)
└── Footer (GitHub, contact, newsletter)
Product Detail (/products/argus):
├── Hero (screenshot + tagline + CTAs)
├── Problem Statement
├── Features (3-5 key features with visuals)
├── How It Works (architecture diagram)
├── Pricing (if applicable)
└── Get Started CTA
7. Recommended NPM Dependencies
{
"dependencies": {
"astro": "^5.6",
"@astrojs/sitemap": "^3.5",
"@astrojs/tailwind": "^6.0",
"astro-seo": "^0.8",
"astro-robots-txt": "^1.0",
"tailwindcss": "^4.0"
},
"devDependencies": {
"wrangler": "^4.0",
"sharp": "^0.33",
"critical": "^8.0"
}
}
Note: No @astrojs/cloudflare adapter needed for static sites. Just build and deploy via Wrangler.
8. Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Astro Pages adapter deprecation confusion | Medium | Low | Use Workers directly; no adapter needed for static |
| AVIF generation slow on CI | Medium | Low | Pre-optimize images; use WebP as default, AVIF as bonus |
| Zaraz requires custom domain setup | Low | Low | Set up custom domain first; use CF Web Analytics as fallback |
| Content Collections schema changes in Astro 5.x | Low | Low | Pin Astro version; review changelogs before upgrading |
Sources
- Astro Content Collections
- Astro Content Collections 2026 Guide
- Deploy Astro to Cloudflare
- Astro on Cloudflare Pages
- Astro Cloudflare Workers Guide
- Cloudflare Pages GitHub Integration
- Astro Performance Optimization: 8 Tips for Perfect Lighthouse
- Astro Image Optimization Guide
- Astro Google Fonts Optimizer
- Astro SEO Complete Guide
- Astro SEO Optimization (AstroJS.dev)
- Astro Sitemap Integration
- Cloudflare Web Analytics
- Cloudflare Zaraz
- Enable Zaraz on Pages
- AI Fund Portfolio
- Forum Ventures AI Studio
- Cloudflare Pages + Workers Review 2026
- Website Conversion Design for 2026