# Multiweb — AI agent rules

FULL RULES: read /CLAUDE.md before your first edit. /AGENTS.md is the short version.

WHAT THIS IS
Reusable PHP website template + admin panel. No database (flat JSON in
data/site.json). No build step, no framework, no npm. Shared hosting, PHP 8.0+.
Every client gets a totally different DESIGN on the SAME ENGINE.

THE RULE
Every file opens with a tag in its first ten lines. Read it before editing:
  [ENGINE] DO NOT REWRITE   shared machinery, identical on every client site
  [SKIN] SAFE TO REWRITE    this client design, replace it freely
  [CONFIG] EDIT THIS FILE   meant to be changed per client
If you are changing how the site LOOKS and the file says [ENGINE], wrong file.
Machine-readable map: .ai-manifest.json

ENGINE (never rewrite):
  includes/functions.php auth.php mailer.php defaults.php modules.php
  blocks.php pages.php business.php integrations.php backup.php
  admin/** seo/** booking-submit.php .htaccess

SKIN (rewrite per client):
  assets/css/site.css  assets/js/site.js
  includes/head.php header.php footer.php theme.php
  index.php  gallery.php  photography.php  page.php

ENGINE HOOKS — five calls inside skin files marked "ENGINE HOOK — KEEP THIS
LINE". Dropping one silently disables a feature. Carry them into any rewrite:
  mw_head_code()        last in <head>
  mw_body_code()        before </body>
  mw_maintenance_gate() top of every public page, before output
  mw_pages_nav()        both nav loops in header.php
  mw_pages_footer()     footer nav

NEVER
  - rename kc_* or mw_* (both prefixes are intentional)
  - delete keys from includes/defaults.php (orphans saved client data)
  - add a framework, build step, npm, Composer or a database
  - put markup in includes/blocks.php (it returns data; markup goes in the theme)
  - omit kc_csrf_field() on an admin form
  - escape the Integrations custom-code fields (raw HTML is intentional)

ALWAYS
  - new admin POST handlers go in admin/actions-modules.php, not actions.php
  - sanitise with mw_field_clean() before writing to site.json
  - escape output with e()
  - use kc_img() for uploaded images
  - add a content type by adding a schema to site.config.php, not a new screen

VERIFY
  find . -name "*.php" -exec php -l {} \; | grep -v "No syntax errors"
  then boot php -S and check every page, including on a fresh install with
  data/site.json deleted (must render placeholders, not warnings)
