This guide details the technical configuration, Cloudflare D1 & KV bindings, Edge functions setup, and customization for the Keypress Theme platform template.
- Quick Start
- Global Settings (
src/config/site.ts) - Environment Variables (
.env.example) - Cloudflare D1 Database & KV Setup
- Edge API Functions
- Contact Form & Webhook Setup
- Firebase Push Notifications Setup
- Google AdSense Integration
Install dependencies (requires Node.js v22.12.0+):
npm installStart the local development server:
npm run devBuild production bundle and Pagefind search index:
npm run buildCustomize website branding, domain, logo, and social handles in src/config/site.ts:
export const SITE_CONFIG: SiteConfig = {
name: "Keypress Theme — Modern Web Publishing Platform",
domain: "https://demo-blog.quicdecode.com", // Canonical domain
cdnDomain: "https://demo-cdn.quicdecode.com", // CDN subdomain for images
contactEmail: "contact@quicdecode.com", // Shown on legal & contact pages
title: "Keypress Theme — Modern Web Publishing Platform",
description: "A modern, fully functional web publishing platform built with Astro and Cloudflare Pages...",
defaultOgImage: "/default-og-image.jpg",
themeColor: "#1a73e8",
// Multi-color logo letters (Google-inspired)
logoLetters: [
{ char: "K", color: "text-[#1a73e8]" },
{ char: "P", color: "text-[#d93025]" },
],
logoTextSuffix: "Keypress",
socials: {
github: "https://github.com/sanp-dev",
}
};Copy .env.example to .env for local development:
cp .env.example .envAvailable keys:
PUBLIC_GA_ID: Google Analytics measurement ID (e.g.G-XXXXXXXXXX).PUBLIC_CLARITY_ID: Microsoft Clarity project ID.GA4_PROPERTY_ID,GA4_CLIENT_EMAIL,GA4_PRIVATE_KEY: GA4 Data API credentials for popular posts feature (Optional).R2_ACCOUNT_ID,R2_ACCESS_KEY_ID,R2_SECRET_ACCESS_KEY: Cloudflare R2 bucket credentials for media assets (Optional).FIREBASE_SECRET,FIREBASE_URL,GEMINI_API_KEY: Push notifications & AI services (Optional).
Note on Licensing: This project is released under the Project Source-Available License. You are free to use, modify, and deploy it for your own website.
This platform is optimized for Cloudflare Pages and utilizes two edge bindings:
DB(Cloudflare D1 Database): Used for storing newsletter email subscriptions.POST_VIEWS(Cloudflare KV Namespace): Used for real-time article view counting and tracking.
- Navigate to Cloudflare Dashboard → Workers & Pages → Select your Pages Project.
- Go to Settings → Functions → D1 Database Bindings:
- Click Add binding.
- Variable name:
DB - D1 Database: Select your created D1 database (e.g.,
my-blog-db).
- Under KV Namespace Bindings:
- Click Add binding.
- Variable name:
POST_VIEWS - KV namespace: Select your created KV namespace.
If you are setting up new databases via command line:
# Create D1 database for email subscribers
npx wrangler d1 create my-blog-db
# Create KV namespace for page view tracking
npx wrangler kv namespace create MY_BLOG_KVAfter creation, attach them to your Cloudflare Pages project settings as shown above.
API routes located in functions/api/:
functions/api/subscribe.js: Handles newsletter subscriptions using D1 bindingDB. Creates tablesubscribersautomatically.functions/api/track-view.js: Tracks article pageviews asynchronously using KV bindingPOST_VIEWS.functions/api/contact.js: Receives contact form submissions and forwards them securely to a webhook.
To receive contact form submissions via email or Google Sheets:
- Create a Google Apps Script (script.google.com):
function doPost(e) { var data = JSON.parse(e.postData.contents); MailApp.sendEmail("your-email@domain.com", "Contact: " + data.subject, "Name: " + data.name + "\nEmail: " + data.email + "\nMessage: " + data.message ); return ContentService.createTextOutput(JSON.stringify({ status: "success" })) .setMimeType(ContentService.MimeType.JSON); }
- Deploy as Web App (Access: Anyone).
- Set environment variable in Cloudflare Pages Dashboard:
CONTACT_FORM_WEBHOOK_URL=https://script.google.com/macros/s/.../exec
Push notification UI component (src/components/PushNotification.astro) and Service Worker (public/firebase-messaging-sw.js):
- Create a Firebase project at console.firebase.google.com.
- Add Web App and copy
firebaseConfigandvapidKey. - Replace dummy keys in
public/firebase-messaging-sw.jsandsrc/components/PushNotification.astro.
Configure AdSense in src/config/site.ts:
googleAdsenseId: "", // Set your client ID (e.g. ca-pub-0000000000000000) or leave ""
adsenseLazyLoad: false, // Set true to lazy-load AdSense
showAdPlaceholders: true, // Set to false to hide ad placeholder boxes when googleAdsenseId is emptyUse the reusable <AdSense /> component in layout templates:
---
import AdSense from "../components/AdSense.astro";
---
<AdSense slot="1234567890" format="auto" responsive="true" />The platform includes full support for AMP & interactive Web Stories located under src/pages/webstories/.
- Data Source: At build-time, pages fetch story items from
public/webstories/story-list.jsonor external endpoints. - Fallback Engine: If no JSON feed is available, built-in fallback stories ensure pages build cleanly without error.
- Categorization: Web stories are dynamically grouped by category slug (
/webstories/[category]/).
If your website does not use Web Stories, you can disable them cleanly from src/config/site.ts:
enableWebStories: false, // Set to false to disable Web Stories completelyWhen set to false:
- Header Navigation: The
"WEBSTORIES"link is automatically hidden from the main navigation header menu. - Build-Time Skipping: Astro skips generating
/webstories/HTML files and returns 0 paths ingetStaticPaths(). No unused Web Stories code or pages are built. - XML Sitemap Exclusion:
/webstories/URLs are automatically excluded fromsitemap-index.xml.js. - 404 Guard: Direct access to
/webstories/routes redirects automatically to 404.
IndexNow allows instant URL indexing by Bing, Yandex, and other search engines when you publish or update content.
- Generate your IndexNow API key from Bing Webmaster Tools or IndexNow Key Generator.
- The key is a plain text string (e.g.,
a1b2c3d4e5f6g7h8i9j0). - Create a
.txtfile named exactly as your API key inpublic/directory:
public/<your-api-key>.txt
The file content must also contain the same key string. Example:
# If your IndexNow key is: a1b2c3d4e5f6g7h8i9j0
# Create file: public/a1b2c3d4e5f6g7h8i9j0.txt
# File content: a1b2c3d4e5f6g7h8i9j0A placeholder file public/indexnow-api-key.txt is included as a reference. Replace it with your actual key file.
Note: The demo template includes a placeholder file. You must rename it to match your actual IndexNow API key and update its content accordingly.