Academy Setup

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.

Last reviewed:

Local Product-HUB GitHub main branch Cloudflare Pages D1 public intake
D1 binding verified. Production now shows a D1 database binding named SCHMALLEGGER_DB connected to schmallegger-public. Keep this exact binding name for Pages Functions.
Do not touch MXGoogle Workspace mail, calendar, and identity stay with Google. Website DNS only.
One D1 authorityUse SCHMALLEGGER_DB for newsletter, Academy, and Compliance Notice intake.
GitHub is transportCommit and push from GitHub Desktop. Cloudflare deploys from main.
KISS firstNewsletter and certificate records before CRM, marketing automation, or licenses.
Step-by-step

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

  1. Open GitHub Desktop.
  2. Choose repository Product-HUB.
  3. Choose branch main.
  4. Click Fetch origin. If GitHub offers Pull, pull first.
  5. Review changed files. Expected changes are under sites/www.schmallegger.net.
  6. Commit with a clear message, for example Add public newsletter and D1 intake.
  7. Click Push origin.

2. Cloudflare Pages: confirm the website project

  1. Open Cloudflare Dashboard.
  2. From the Cloudflare dashboard, open Workers & Pages. If Cloudflare shows the new sidebar, use Compute / Workers & Pages.
  3. Open project schmallegger-net.
  4. Open Settings, then Build or Pages configuration.
  5. Confirm Git repository irinaonline/Product-HUB.
  6. Confirm production branch main.
  7. Confirm framework preset None.
  8. Confirm build command exit 0.
  9. Confirm build output directory ..
  10. Confirm root directory sites/www.schmallegger.net.

3. D1: create the public intake database

  1. 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.
  2. Click Create database.
  3. Name it schmallegger-public.
  4. 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.
  5. Open the new database console.
  6. 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

  1. Go back to Workers & Pages and open schmallegger-net.
  2. Open Settings, then Bindings.
  3. Click Add, then choose D1 database. Cloudflare documents this under Pages Functions D1 bindings.
  4. Set variable name to SCHMALLEGGER_DB.
  5. Select D1 database schmallegger-public.
  6. Save. If Cloudflare shows Production and Preview environments, add it to Production first and Preview second.
  7. Redeploy the latest production deployment so the binding becomes active.

5. Optional KV: confirmation-token helper

  1. 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.
  2. Create namespace schmallegger-public-kv.
  3. Open schmallegger-net -> Settings -> Bindings.
  4. Add a KV namespace binding named SCHMALLEGGER_KV.
  5. Select schmallegger-public-kv and save.
  6. Redeploy. This is helpful but not mandatory when D1 is connected.

6. Test the public intake

  1. Open the newsletter page.
  2. Submit a test subscriber with consent checked.
  3. Open the Academy page.
  4. Complete or mark modules, enter a test result percentage, create the certificate preview, and submit the intake.
  5. Open the Compliance Notice page.
  6. Submit a small technical test notice with consent checked.
  7. Open the D1 console and run the verification queries below.
Database Map

KISS structure with Navision-style clarity.

Small tables, stable keys, explicit fields, and enough event history to understand what happened later.

TablePurposeImportant fieldsGrowth path
newsletter_subscribersOne row per email subscriber.email, first_name, last_name, interest, status, consentLater CRM contact link, unsubscribe, topic preferences.
communication_messagesOne row per general public message.topic, urgency, subject, message, status, consentLater Cockpit Communication Desk, CRM queue, and follow-up history.
newsletter_eventsAudit trail for subscription actions.created_at, email_norm, event_kind, detailLater campaign events, confirmation, unsubscribe, source tracking.
academy_certificate_requestsHuman-AI Academy certificate intake.course, completed_count, total_modules, test_score, grade, grade_labelLater PDF certificate generation and private Cockpit review.
compliance_noticesGood-faith website review notices.category, jurisdiction, page_url, summary, status, page_revisionLater 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;
Locale Strategy

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.

LocalePurposePublic rule
en-USNorth America and default public fallback.Production-ready.
en-GBGibraltar and UK-facing business tone.Production-ready after copy review.
es-ESSpain and Spanish-speaking Gibraltar visitors.Production-ready after copy review.
de-ATAustrian German and Vienna homebase context.Production-ready after copy review.
ru-RURussian family, heritage, and international reach.Production-ready after copy review.
de-AT-x-styrianStyrian German heritage easter egg.Visible, reviewed, and intentionally charming.
de-AT-x-vienneseViennese German heritage easter egg.Visible, reviewed, and intentionally charming.
es-GI-x-llanitoGibraltarian Llanito identity signal.Visible as a signature surprise, never auto-guessed.
Implementation rule: the static site remains fast. D1 can later hold reviewed translation/content blocks, but public pages should receive cached/static snapshots instead of querying the database for every paragraph on every view.
Cost And Content Strategy

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.

LaneBest first choiceWhyNext step
Global header, footer, navigation, brand languageStatic HTML/CSS/JSFast, cacheable, and practically free to serve.Keep generated from one source so pages stay consistent.
Newsletter, Academy certificate, Compliance Notice, contact intakeD1 recordsThese are changing records with consent, status, and audit value.Review in Cloudflare first, then later surface in Cockpit Central.
Translated page copyStatic snapshot firstReaders should not pay a database request for every paragraph.Store approved translations in D1 later, then publish cached static snapshots.
Frequently changed content blocksD1 authoring, cached public outputEasy 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 tokensKV, optionalGood for confirmation links and temporary state.Use after we choose the transactional email provider.
Free-tier discipline: static assets remain the default, Pages Functions are used only for forms and small APIs, and D1 queries should be indexed, paged, and batched. Before larger public traffic or automated publishing, recheck the current Cloudflare limits in the official docs.
Next Upgrade

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.

Open newsletter page