From fcd5db2576ee9b81f1036686475b1d1d22afa899 Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:06 +0530 Subject: [PATCH 01/13] Phase 1: add Worker API for enquiry form storage --- src/index.js | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/index.js diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..e9c68eb --- /dev/null +++ b/src/index.js @@ -0,0 +1,93 @@ +export default { + async fetch(request, env) { + const url = new URL(request.url); + + if (url.pathname === "/api/enquiry") { + if (request.method !== "POST") { + return json({ ok: false, error: "Method not allowed." }, 405, { Allow: "POST" }); + } + return handleEnquiry(request, env, url); + } + + // Serve the existing static website without changing its routes. + return env.ASSETS.fetch(request); + } +}; + +async function handleEnquiry(request, env, url) { + const origin = request.headers.get("Origin"); + if (origin && origin !== url.origin) { + return json({ ok: false, error: "Cross-origin requests are not accepted." }, 403); + } + + const contentType = request.headers.get("Content-Type") || ""; + if (!contentType.toLowerCase().includes("application/json")) { + return json({ ok: false, error: "Send the enquiry as JSON." }, 415); + } + + const length = Number(request.headers.get("Content-Length") || 0); + if (length > 12000) return json({ ok: false, error: "Enquiry is too large." }, 413); + + let data; + try { + data = await request.json(); + } catch { + return json({ ok: false, error: "Invalid request body." }, 400); + } + + if (!data || typeof data !== "object" || Array.isArray(data)) { + return json({ ok: false, error: "Invalid enquiry." }, 400); + } + if (String(data.website || "").trim()) { + // Quietly accept automated honeypot submissions without storing them. + return json({ ok: true, reference: "ENQ-RECEIVED" }); + } + + const name = clean(data.name, 100); + const email = clean(data.email, 254).toLowerCase(); + const phone = clean(data.phone, 25); + const service = clean(data.service, 150); + const businessName = clean(data.businessName, 150); + const businessType = clean(data.businessType, 100); + const message = clean(data.message, 3000); + const consent = data.consent === true; + + if (name.length < 2) return json({ ok: false, error: "Please enter your full name." }, 400); + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { + return json({ ok: false, error: "Please enter a valid email address." }, 400); + } + if (phone && !/^[+0-9() .-]{7,25}$/.test(phone)) { + return json({ ok: false, error: "Please enter a valid phone number." }, 400); + } + if (!service) return json({ ok: false, error: "Please choose a service." }, 400); + if (message.length < 5) return json({ ok: false, error: "Please describe your requirement." }, 400); + if (!consent) return json({ ok: false, error: "Please agree to the enquiry privacy notice." }, 400); + if (!env.DB) return json({ ok: false, error: "Enquiry storage is not configured yet. Please try again later." }, 503); + + const reference = "ENQ-" + new Date().getUTCFullYear() + "-" + crypto.randomUUID().replace(/-/g, "").slice(0, 10).toUpperCase(); + + try { + await env.DB.prepare( + `INSERT INTO Leads + (reference, name, email, phone, service, business_name, business_type, message, status) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'new')` + ).bind(reference, name, email, phone || null, service, businessName || null, businessType || null, message).run(); + } catch (error) { + console.error("Could not save GOAXIS enquiry", error); + return json({ ok: false, error: "We could not save your enquiry. Please try again later." }, 500); + } + + return json({ ok: true, reference }); +} + +function clean(value, maxLength) { + if (typeof value !== "string") return ""; + return value.trim().replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, "").slice(0, maxLength); +} + +function json(body, status = 200, extraHeaders = {}) { + return new Response(JSON.stringify(body), { + status, + headers: { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store", ...extraHeaders } + }); +} From 2dd86e069e4c07aa6c75fc6f907d747392f0b08b Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:09 +0530 Subject: [PATCH 02/13] Phase 1: add D1 Leads table migration --- migrations/0001_phase1_enquiries.sql | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 migrations/0001_phase1_enquiries.sql diff --git a/migrations/0001_phase1_enquiries.sql b/migrations/0001_phase1_enquiries.sql new file mode 100644 index 0000000..32cce2a --- /dev/null +++ b/migrations/0001_phase1_enquiries.sql @@ -0,0 +1,17 @@ +CREATE TABLE IF NOT EXISTS Leads ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + reference TEXT NOT NULL UNIQUE, + name TEXT NOT NULL, + email TEXT NOT NULL, + phone TEXT, + service TEXT NOT NULL, + business_name TEXT, + business_type TEXT, + message TEXT NOT NULL, + status TEXT NOT NULL DEFAULT 'new', + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX IF NOT EXISTS idx_leads_created_at ON Leads(created_at); +CREATE INDEX IF NOT EXISTS idx_leads_status ON Leads(status); +CREATE INDEX IF NOT EXISTS idx_leads_email ON Leads(email); From eaaee51c04121ce166e8063a6150c66c75a4cf44 Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:11 +0530 Subject: [PATCH 03/13] Configure Worker assets and D1 binding for Phase 1 --- wrangler.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 wrangler.toml diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 0000000..372e680 --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,14 @@ +name = "goaxis" +main = "src/index.js" +compatibility_date = "2026-10-19" + +[assets] +directory = "." +binding = "ASSETS" +run_worker_first = ["/api/*"] + +[[d1_databases]] +binding = "DB" +database_name = "goaxis-consultancy-db" +database_id = "f81de195-6559-486c-b6a9-be4fac6e5111" +migrations_dir = "migrations" From e7849fa7ea4225d42afbe1432cabb3c8adc227ca Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:13 +0530 Subject: [PATCH 04/13] Connect public enquiry forms to Phase 1 API --- forms.js | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 forms.js diff --git a/forms.js b/forms.js new file mode 100644 index 0000000..7394bbd --- /dev/null +++ b/forms.js @@ -0,0 +1,75 @@ +document.addEventListener("DOMContentLoaded", () => { + const forms = ["enquiry-form", "service-enquiry-form"] + .map(id => document.getElementById(id)) + .filter(Boolean); + + for (const form of forms) { + const feedback = form.querySelector("#form-feedback, #service-feedback, .form-feedback"); + const submit = form.querySelector('button[type="submit"]'); + + // Bot honeypot; real users never see or fill this field. + if (!form.querySelector('[name="website"]')) { + const trap = document.createElement("div"); + trap.setAttribute("aria-hidden", "true"); + trap.style.cssText = "position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden"; + trap.innerHTML = ''; + form.appendChild(trap); + } + + form.addEventListener("submit", async event => { + event.preventDefault(); + if (!form.reportValidity()) return; + + const data = new FormData(form); + const requiredConsent = form.querySelector('input[type="checkbox"][required]'); + const payload = { + name: String(data.get("name") || ""), + email: String(data.get("email") || ""), + phone: String(data.get("phone") || ""), + service: String(data.get("service") || ""), + businessName: String(data.get("businessName") || ""), + businessType: String(data.get("businessType") || ""), + message: String(data.get("message") || data.get("details") || ""), + consent: Boolean(requiredConsent && requiredConsent.checked), + website: String(data.get("website") || "") + }; + + if (feedback) { + feedback.textContent = "Sending your enquiry securely…"; + feedback.setAttribute("data-state", "loading"); + } + if (submit) { + submit.disabled = true; + submit.setAttribute("aria-busy", "true"); + } + + try { + const response = await fetch("/api/enquiry", { + method: "POST", + headers: { "Content-Type": "application/json", "Accept": "application/json" }, + credentials: "same-origin", + body: JSON.stringify(payload) + }); + const result = await response.json().catch(() => ({})); + if (!response.ok || !result.ok) { + throw new Error(result.error || "We could not send your enquiry. Please try again."); + } + if (feedback) { + feedback.textContent = "Thank you. Your enquiry was received. Reference: " + result.reference; + feedback.setAttribute("data-state", "success"); + } + form.reset(); + } catch (error) { + if (feedback) { + feedback.textContent = error instanceof Error ? error.message : "Network error. Please try again."; + feedback.setAttribute("data-state", "error"); + } + } finally { + if (submit) { + submit.disabled = false; + submit.removeAttribute("aria-busy"); + } + } + }); + } +}); From 8a9f3346534783fe14dcd8b6f28170aade3bb6b2 Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:41 +0530 Subject: [PATCH 05/13] Connect homepage enquiry form to Phase 1 API --- index.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 8fdee99..27af9e0 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,7 @@ + @@ -83,13 +84,13 @@

Build your business.
We'll help you
move forward.

START WITH A CONVERSATION

Your next business step
can start today.

Tell us what you need →
-

CONTACT GOAXIS

Tell us a little
about your plans.

Share what you are working on and what kind of support you’re looking for.

Email & phoneContact details will be added before launch.
Service areaOnline support; availability will be confirmed for each request.
Preview form only. It does not send or save your information yet. Online submission will be connected in a later part.
+

CONTACT GOAXIS

Tell us a little
about your plans.

Share what you are working on and what kind of support you’re looking for.

Email & phoneContact details will be added before launch.
Service areaOnline support; availability will be confirmed for each request.
Your details will be used to respond to this enquiry. Please do not include passwords, bank details or sensitive identity numbers.

YOUR ENQUIRY

How can we help?

- +
G.Make your next move with clarity.Back to top ↑
From 17a0fb46a27dd9e18f3be821aa3aafb2470a7c64 Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:44 +0530 Subject: [PATCH 06/13] Connect service quotation form to Phase 1 API --- service.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service.html b/service.html index da43c8f..1ad1776 100644 --- a/service.html +++ b/service.html @@ -1,7 +1,7 @@ -Service Details | GOAXIS CONSULTANCY +Service Details | GOAXIS CONSULTANCY
BUSINESS SUPPORT, MADE SIMPLE Explore all services ↗
← All services

GOAXIS SERVICE

Service details

Select a service to see its scope and enquiry form.

Professional fee: Quotation required
Any government/third-party fee is separate and will be explained before proceeding.

WHAT TO EXPECT

Clear steps.
Informed decisions.

Before you submit

Please do not include Aadhaar numbers, PAN numbers, passwords, bank details or upload identity documents in this initial enquiry. We will explain secure document-sharing steps if your request proceeds.

-

REQUEST A QUOTATION

Tell us what you need.

Fields marked * are required. This form currently validates in your browser only; it does not send or save your information.

No payment is taken on this page. A written quote and scope should be agreed before any paid work begins.

+

REQUEST A QUOTATION

Tell us what you need.

Fields marked * are required. We use these details to review and respond to your quotation request.

No payment is taken on this page. A written quote and scope should be agreed before any paid work begins.

\ No newline at end of file From d41eb250c5272ec4e005bd439c46359adbb923d3 Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:47 +0530 Subject: [PATCH 07/13] Remove preview-only submit handler from homepage --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 8d61ae3..bb9955f 100644 --- a/app.js +++ b/app.js @@ -1 +1 @@ -document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll(".menu-toggle").forEach(b=>b.addEventListener("click",()=>{const nav=document.getElementById(b.getAttribute("aria-controls"));if(!nav)return;const open=nav.classList.toggle("open");b.setAttribute("aria-expanded",String(open));}));document.querySelectorAll("#current-year").forEach(el=>el.textContent=String(new Date().getFullYear()));const form=document.getElementById("enquiry-form");if(form)form.addEventListener("submit",e=>{e.preventDefault();const out=document.getElementById("form-feedback");if(out)out.textContent="This is a frontend preview. Your enquiry has not been sent or saved. Please contact the business directly once contact details are published.";});}); \ No newline at end of file +document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll(".menu-toggle").forEach(b=>b.addEventListener("click",()=>{const nav=document.getElementById(b.getAttribute("aria-controls"));if(!nav)return;const open=nav.classList.toggle("open");b.setAttribute("aria-expanded",String(open));}));document.querySelectorAll("#current-year").forEach(el=>el.textContent=String(new Date().getFullYear()));}); \ No newline at end of file From c14176e52e2d1993e7fec1beedd5db6a21b0333e Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:49 +0530 Subject: [PATCH 08/13] Remove preview-only handler from service quotation form --- part2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/part2.js b/part2.js index c25ab5c..c617b9d 100644 --- a/part2.js +++ b/part2.js @@ -1 +1 @@ -const serviceData={gst:["TAX & BUSINESS","GST Registration Assistance","Guidance on eligibility, the information generally required, and application-readiness steps."],udyam:["MSME","Udyam Registration Assistance","Understand the official MSME registration route and the information required."],fssai:["FOOD BUSINESS","FSSAI Assistance","Guidance on identifying the applicable registration or licence route and preparing a document checklist."],iec:["IMPORT & EXPORT","IEC Assistance","Support understanding the Importer Exporter Code application steps and document requirements."],apeda:["EXPORT READINESS","APEDA & Export Documentation","Guidance on RCMC and export documentation, subject to product eligibility and current rules."],documents:["DOCUMENTATION","Business Documents","Quotation, proforma invoice, business profile and related documentation support."],other:["CUSTOM SUPPORT","Other Business Requirements","Describe your requirement so the possible next steps can be reviewed."]};document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll("#current-year").forEach(e=>e.textContent=new Date().getFullYear());const key=new URLSearchParams(location.search).get("service")||"other";const d=serviceData[key]||serviceData.other;const cat=document.getElementById("service-category"),title=document.getElementById("service-title"),desc=document.getElementById("service-description"),scope=document.getElementById("service-scope"),field=document.getElementById("service-field");if(cat)cat.textContent=d[0];if(title)title.textContent=d[1];if(desc)desc.textContent=d[2];if(scope)scope.innerHTML="
  • Initial requirement review
  • Checklist of likely information and documents
  • Scope and quotation confirmed before paid work
  • Government decisions and approvals are not guaranteed
";if(field)field.value=d[1];const form=document.getElementById("service-enquiry-form");if(form)form.addEventListener("submit",e=>{e.preventDefault();const out=document.getElementById("service-feedback");if(out)out.textContent="Preview only: this enquiry has not been sent or saved. Contact details and a secure submission service must be configured before launch.";});document.querySelectorAll(".menu-toggle").forEach(b=>b.addEventListener("click",()=>{const n=document.getElementById(b.getAttribute("aria-controls"));if(n)n.classList.toggle("open")}));}); \ No newline at end of file +const serviceData={gst:["TAX & BUSINESS","GST Registration Assistance","Guidance on eligibility, the information generally required, and application-readiness steps."],udyam:["MSME","Udyam Registration Assistance","Understand the official MSME registration route and the information required."],fssai:["FOOD BUSINESS","FSSAI Assistance","Guidance on identifying the applicable registration or licence route and preparing a document checklist."],iec:["IMPORT & EXPORT","IEC Assistance","Support understanding the Importer Exporter Code application steps and document requirements."],apeda:["EXPORT READINESS","APEDA & Export Documentation","Guidance on RCMC and export documentation, subject to product eligibility and current rules."],documents:["DOCUMENTATION","Business Documents","Quotation, proforma invoice, business profile and related documentation support."],other:["CUSTOM SUPPORT","Other Business Requirements","Describe your requirement so the possible next steps can be reviewed."]};document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll("#current-year").forEach(e=>e.textContent=new Date().getFullYear());const key=new URLSearchParams(location.search).get("service")||"other";const d=serviceData[key]||serviceData.other;const cat=document.getElementById("service-category"),title=document.getElementById("service-title"),desc=document.getElementById("service-description"),scope=document.getElementById("service-scope"),field=document.getElementById("service-field");if(cat)cat.textContent=d[0];if(title)title.textContent=d[1];if(desc)desc.textContent=d[2];if(scope)scope.innerHTML="
  • Initial requirement review
  • Checklist of likely information and documents
  • Scope and quotation confirmed before paid work
  • Government decisions and approvals are not guaranteed
";if(field)field.value=d[1];document.querySelectorAll(".menu-toggle").forEach(b=>b.addEventListener("click",()=>{const n=document.getElementById(b.getAttribute("aria-controls"));if(n)n.classList.toggle("open")}));}); \ No newline at end of file From bec925d6da9d99d57993c42f6b13aeeba7ba8f9b Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:52 +0530 Subject: [PATCH 09/13] Update privacy draft for Phase 1 enquiry storage --- privacy.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privacy.html b/privacy.html index 806979e..12c4911 100644 --- a/privacy.html +++ b/privacy.html @@ -1 +1 @@ -Privacy Policy Draft — GOAXIS CONSULTANCY
\ No newline at end of file +Privacy Policy Draft — GOAXIS CONSULTANCY
\ No newline at end of file From 698e657dadf66fb2d54ea716a502697e766a8cc9 Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:05:55 +0530 Subject: [PATCH 10/13] Document Phase 1 Worker API and safe deployment steps --- README.md | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f972adb..a548ce0 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,28 @@ -# GOAXIS CONSULTANCY — Cloudflare Pages static deployment +# GOAXIS CONSULTANCY — Phase 1 Working Forms -This repository is configured as a **static frontend** for Cloudflare Pages. It does not include a production backend, secure authentication, enquiry storage, admin API, or verified payment processing. +Repository: `arpit-ae/axis`. The public site is served as static assets by a Cloudflare Worker; Phase 1 adds a Worker API route at `POST /api/enquiry` and a D1 `Leads` table. -## Cloudflare Pages settings -- Connect GitHub repository: `arpit-ae/axis` -- Production branch: `main` -- Framework preset: `None` -- Build command: leave blank (or `exit 0` if the dashboard requires a command) -- Build output directory: `/` (repository root; in Cloudflare's UI use `.` if accepted) -- Root directory: leave blank +## Files added +- `src/index.js`: Worker API plus static asset fallback. +- `forms.js`: sends the homepage and service quotation forms to the API. +- `migrations/0001_phase1_enquiries.sql`: creates the enquiry table and indexes. +- `wrangler.toml`: Worker asset and D1 binding configuration. -Cloudflare Pages will rebuild automatically when commits land on `main`. Do **not** use `npx wrangler deploy` for this static Pages site; that command targets Workers. If deploying from CLI, use `npx wrangler pages deploy . --project-name=goaxis-consultancy --branch=main` after authenticating Wrangler and confirming the Pages project name. +## Safety before production +- Confirm this Wrangler config targets the intended Cloudflare account and existing `goaxis` Worker. +- Confirm the D1 database ID in Cloudflare before applying migrations. +- Apply the D1 migration only after checking existing migration/table state. +- Preview-test the homepage and service forms, and verify their records in D1. +- Review and complete the Privacy Policy and Terms before collecting real customer information. +- The customer login/signup and admin pages remain prototypes; this phase does not implement secure authentication, admin access, payments or a customer dashboard. +- Do not run a production deploy until the binding and migration have been verified. -## Before accepting real customers/payments -- Replace placeholder contact details and review draft Terms/Privacy pages. -- Build and configure a server-side API for enquiry submissions, customer accounts and admin access. -- Configure verified payment-gateway webhooks; never trust a browser return URL as proof of payment. -- Add Cloudflare Pages Functions/Workers and configure D1/R2 bindings and secrets only when backend code is ready. -- Do not treat the demo login/signup pages as secure authentication. +## Suggested local checks +```sh +node --check app.js +node --check forms.js +node --check part2.js +node --check src/index.js +``` -The enquiry forms are preview-only and do not transmit or save personal information. The admin page is only a shell and must not be used for real operations. +Production uses Cloudflare Worker static assets. The API handles `/api/*`; other requests are passed to the existing static asset service. \ No newline at end of file From d966c5a2a76c91415a74db069b17edfc933aa81f Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:06:23 +0530 Subject: [PATCH 11/13] Protect internal Worker and migration files from static asset access --- src/index.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/index.js b/src/index.js index e9c68eb..5bc0aaa 100644 --- a/src/index.js +++ b/src/index.js @@ -9,6 +9,17 @@ export default { return handleEnquiry(request, env, url); } + // Do not publish deployment configuration, migrations, or Worker source files. + if ( + url.pathname === "/README.md" || + url.pathname === "/wrangler.toml" || + url.pathname.startsWith("/src/") || + url.pathname.startsWith("/migrations/") || + url.pathname.startsWith("/.github/") + ) { + return new Response("Not found", { status: 404 }); + } + // Serve the existing static website without changing its routes. return env.ASSETS.fetch(request); } From aa8c3e456ee402be7b6b8fb8234575ccc0a43eb3 Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:06:25 +0530 Subject: [PATCH 12/13] Route API and internal paths through Worker before asset fallback --- wrangler.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrangler.toml b/wrangler.toml index 372e680..4516e76 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -5,7 +5,7 @@ compatibility_date = "2026-10-19" [assets] directory = "." binding = "ASSETS" -run_worker_first = ["/api/*"] +run_worker_first = ["/api/*", "/src/*", "/migrations/*", "/README.md", "/wrangler.toml", "/.github/*"] [[d1_databases]] binding = "DB" From 541133f1e01b497bbf43b2035b7f55ddddfdc90e Mon Sep 17 00:00:00 2001 From: arpit-ae Date: Mon, 19 Oct 2026 15:06:32 +0530 Subject: [PATCH 13/13] Add automated Phase 1 syntax and wiring checks --- .github/workflows/phase1-checks.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/phase1-checks.yml diff --git a/.github/workflows/phase1-checks.yml b/.github/workflows/phase1-checks.yml new file mode 100644 index 0000000..81b768e --- /dev/null +++ b/.github/workflows/phase1-checks.yml @@ -0,0 +1,28 @@ +name: Phase 1 checks +on: + pull_request: + branches: [main] + push: + branches: [feature/phase1-working-forms] +jobs: + syntax-and-wiring: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - name: Check JavaScript syntax + run: | + node --check app.js + node --check forms.js + node --check part2.js + node --check src/index.js + - name: Check Phase 1 wiring + run: | + grep -q 'src="forms.js" defer' index.html + grep -q 'src="forms.js" defer' service.html + grep -q 'id="enquiry-form"' index.html + grep -q 'id="service-enquiry-form"' service.html + grep -q 'POST /api/enquiry' README.md + grep -q 'CREATE TABLE IF NOT EXISTS Leads' migrations/0001_phase1_enquiries.sql