GitHub plus Cloudflare D1, without mystery.
This checklist is written for the first real setup: code moves through GitHub, Cloudflare Pages deploys it, and D1 stores newsletter, Human-AI Academy certificate, and Compliance Notice records.
SCHMALLEGGER_DB connected to schmallegger-public. Keep this exact binding name for Pages Functions.SCHMALLEGGER_DB for newsletter, Academy, and Compliance Notice intake.First-time setup checklist.
Work top to bottom. If a screen uses slightly different words, keep the meaning: repository, project, branch, root directory, binding, redeploy, test.
1. GitHub Desktop: publish the code
- Open GitHub Desktop.
- Choose repository Product-HUB.
- Choose branch main.
- Click Fetch origin. If GitHub offers Pull, pull first.
- Review changed files. Expected changes are under
sites/www.schmallegger.net. - Commit with a clear message, for example Add public newsletter and D1 intake.
- Click Push origin.
2. Cloudflare Pages: confirm the website project
- Open Cloudflare Dashboard.
- From the Cloudflare dashboard, open Workers & Pages. If Cloudflare shows the new sidebar, use Compute / Workers & Pages.
- Open project schmallegger-net.
- Open Settings, then Build or Pages configuration.
- Confirm Git repository irinaonline/Product-HUB.
- Confirm production branch main.
- Confirm framework preset None.
- Confirm build command
exit 0. - Confirm build output directory
.. - Confirm root directory
sites/www.schmallegger.net.
3. D1: create the public intake database
- From the Cloudflare dashboard, open Workers & Pages, then D1 SQL Database. If D1 is shown under Storage & Databases, open it there. Keep Cloudflare D1 setup docs as the reference link.
- Click Create database.
- Name it
schmallegger-public. - If Cloudflare asks for data location, use Specify jurisdiction and choose European Union for public intake data such as newsletter, Academy certificate, communication, and Compliance Notice records.
- Open the new database console.
- Run the schema from
functions/schema/schmallegger-public-d1.sql. The Pages Functions can also create the tables automatically, but running the schema once makes the setup visible and auditable.
4. Bind D1 to the Pages project
- Go back to Workers & Pages and open schmallegger-net.
- Open Settings, then Bindings.
- Click Add, then choose D1 database. Cloudflare documents this under Pages Functions D1 bindings.
- Set variable name to
SCHMALLEGGER_DB. - Select D1 database
schmallegger-public. - Save. If Cloudflare shows Production and Preview environments, add it to Production first and Preview second.
- Redeploy the latest production deployment so the binding becomes active.
5. Optional KV: confirmation-token helper
- From the Cloudflare dashboard, open Workers & Pages, then KV. If KV is shown under Storage & Databases, open it there. Keep Cloudflare KV binding docs as the reference link.
- Create namespace
schmallegger-public-kv. - Open schmallegger-net -> Settings -> Bindings.
- Add a KV namespace binding named
SCHMALLEGGER_KV. - Select
schmallegger-public-kvand save. - Redeploy. This is helpful but not mandatory when D1 is connected.
6. Test the public intake
- Open the newsletter page.
- Submit a test subscriber with consent checked.
- Open the Academy page.
- Complete or mark modules, enter a test result percentage, create the certificate preview, and submit the intake.
- Open the Compliance Notice page.
- Submit a small technical test notice with consent checked.
- Open the D1 console and run the verification queries below.
KISS structure with Navision-style clarity.
Small tables, stable keys, explicit fields, and enough event history to understand what happened later.
| Table | Purpose | Important fields | Growth path |
|---|---|---|---|
newsletter_subscribers | One row per email subscriber. | email, first_name, last_name, interest, status, consent | Later CRM contact link, unsubscribe, topic preferences. |
communication_messages | One row per general public message. | topic, urgency, subject, message, status, consent | Later Cockpit Communication Desk, CRM queue, and follow-up history. |
newsletter_events | Audit trail for subscription actions. | created_at, email_norm, event_kind, detail | Later campaign events, confirmation, unsubscribe, source tracking. |
academy_certificate_requests | Human-AI Academy certificate intake. | course, completed_count, total_modules, test_score, grade, grade_label | Later PDF certificate generation and private Cockpit review. |
compliance_notices | Good-faith website review notices. | category, jurisdiction, page_url, summary, status, page_revision | Later Cockpit review queue and resolution history. |
Newsletter check
SELECT created_at, first_name, last_name, email, interest, status
FROM newsletter_subscribers
ORDER BY created_at DESC
LIMIT 50;
Communication check
SELECT created_at, status, topic, urgency, subject, email
FROM communication_messages
ORDER BY created_at DESC
LIMIT 50;
Academy certificate check
SELECT created_at, first_name, last_name, course, test_score, grade, grade_label
FROM academy_certificate_requests
ORDER BY created_at DESC
LIMIT 50;
Compliance Notice check
SELECT created_at, status, category, jurisdiction, page_url, summary, page_revision
FROM compliance_notices
ORDER BY created_at DESC
LIMIT 50;
Many languages, one governed public voice.
The selector now exposes production locales for English, Spanish, German, and Russian, plus heritage easter eggs for Styrian, Viennese, and Llanito. The important discipline: the switcher can be playful, but published translations stay reviewed.
| Locale | Purpose | Public rule |
|---|---|---|
en-US | North America and default public fallback. | Production-ready. |
en-GB | Gibraltar and UK-facing business tone. | Production-ready after copy review. |
es-ES | Spain and Spanish-speaking Gibraltar visitors. | Production-ready after copy review. |
de-AT | Austrian German and Vienna homebase context. | Production-ready after copy review. |
ru-RU | Russian family, heritage, and international reach. | Production-ready after copy review. |
de-AT-x-styrian | Styrian German heritage easter egg. | Visible, reviewed, and intentionally charming. |
de-AT-x-viennese | Viennese German heritage easter egg. | Visible, reviewed, and intentionally charming. |
es-GI-x-llanito | Gibraltarian Llanito identity signal. | Visible as a signature surprise, never auto-guessed. |
Static shell first. Database where it earns its place.
Cloudflare is generous enough for our public learning and contact lanes, but the discipline is still simple: do not make every page view ask the database unless the answer must be live.
| Lane | Best first choice | Why | Next step |
|---|---|---|---|
| Global header, footer, navigation, brand language | Static HTML/CSS/JS | Fast, cacheable, and practically free to serve. | Keep generated from one source so pages stay consistent. |
| Newsletter, Academy certificate, Compliance Notice, contact intake | D1 records | These are changing records with consent, status, and audit value. | Review in Cloudflare first, then later surface in Cockpit Central. |
| Translated page copy | Static snapshot first | Readers should not pay a database request for every paragraph. | Store approved translations in D1 later, then publish cached static snapshots. |
| Frequently changed content blocks | D1 authoring, cached public output | Easy to maintain without making the public page slow or quota-heavy. | Add a small content block table only after the first manual translation round. |
| Short-lived verification tokens | KV, optional | Good for confirmation links and temporary state. | Use after we choose the transactional email provider. |
Email confirmation is the next separate lane.
The site already stores the records. Automatic confirmation email needs a transactional email provider such as Resend, Brevo, or Mailgun. That becomes a small provider decision, not a database redesign.