{ "meta": { "author": "Andre Cobham / Arising Media", "updated": "2026-06-09", "version": "3.0" }, "stack": { "base_image": "php:8.3-fpm-alpine", "process_manager": "supervisord", "web_server": "nginx", "database": "SQLite (pdo_sqlite)", "email": "SMTP via msmtp or Resend API", "js": "vanilla (no frameworks)", "css": "tokens.css + main.css", "hosting": "Coolify (Docker) or cPanel (shared hosting)" }, "databases": { "header.db": ["nav_items"], "footer.db": ["footer_columns", "footer_links", "footer_legal"], "pages.db": ["pages", "page_sections"], "blog.db": ["posts", "post_images", "post_schema", "post_stats", "related_posts", "linkedin_drafts", "subscribers"], "one_db_per_domain": true, "never_monolithic": "Do not combine unrelated content domains in one database" }, "deployment": { "docker": { "build_command": "docker compose build", "run_command": "docker compose up -d", "process_manager": "supervisord", "platforms": ["VPS", "DigitalOcean", "Linode", "Coolify", "custom servers"] }, "cpanel": { "requires": [".htaccess", ".cpanel.yml"], "repo_path": "/home/{username}/repositories/{domain}/ (empty)", "webroot": "/home/{username}/public_html/{domain}/", "platforms": ["cPanel", "Bluehost", "HostGator", "SiteGround"] } }, "content_update": { "new_page": [ "Insert row in pages.db: slug, title, hero fields, sections_json", "Re-seed: python3 build/seed_databases.py", "Rebuild Docker: docker build -t {domain}:local .", "For new URL patterns: add location block to infra/nginx.conf" ], "edit_content": [ "All body copy lives in sections_json column of pages.db", "Never put body copy in PHP template files", "Edit CSV source or build/seed_databases.py and re-run" ], "build_scripts": "Use JSON + template + Python for 4+ similar pages (location pages, service pages)" }, "security": { "required_headers": [ "X-Frame-Options: SAMEORIGIN", "X-Content-Type-Options: nosniff", "Referrer-Policy: strict-origin-when-cross-origin", "Permissions-Policy: camera=(), microphone=(), geolocation=()", "Strict-Transport-Security: max-age=31536000; includeSubDomains", "Cross-Origin-Opener-Policy: same-origin", "Cross-Origin-Resource-Policy: same-origin", "Content-Security-Policy (tight, project-specific)" ], "php_hardening": [ "expose_php = Off", "display_errors = Off", "open_basedir = /var/www/html:/var/www/data", "disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec" ], "php_fpm": "clear_env = no (CRITICAL: required for getenv())", "blocking_sensitive_paths": [ "location ~ /\\. { deny all; return 404; }", "location ~* \\.(env|conf|yml|md|sh|py|sql|bak|log|dockerfile)$ { deny all; return 404; }" ] }, "forms": { "spam_protection": "Altcha (self-hosted, proof-of-work SHA-256, no third-party)", "altcha_key_generation": "openssl rand -hex 32", "altcha_csp_requirement": "worker-src 'self' blob: (CRITICAL)", "rate_limiting": { "nginx": "5 requests/min per IP, burst 3", "php": "5/10min per IP, file-backed (/tmp/form-rate-limit/)" }, "security_layers": [ "nginx rate limit: 5r/min per IP", "PHP rate limit: 5/10min per IP", "honeypot field: hidden 'website' input", "time-on-page check: <3s = [REVIEW] in subject", "Altcha proof-of-work: SHA-256 + HMAC verification", "server-side validation: all fields checked, HTML-escaped", "32KB body cap: reject oversized payloads" ], "email_providers": { "resend": "REST API (transactional, PHP curl)", "msmtp": "SMTP relay (for cPanel + existing SMTP)" } }, "seo": { "required_meta_tags": [ "charset UTF-8", "viewport width=device-width, initial-scale=1.0", "title (under 60 chars)", "description (150-160 chars)", "canonical link", "Open Graph: og:type, og:url, og:title, og:description, og:image, og:site_name", "Twitter: card, url, title, description, image", "robots index, follow", "theme-color (mobile)", "favicon.svg, favicon-32.png, apple-touch-icon" ], "required_files": [ "/robots.txt (Disallow /api/, include Sitemap)", "/sitemap.xml (one per page with )", "/llms.txt (llmstxt.org standard)" ], "schema_required": [ "LocalBusiness (home page, location pages)", "Service (service detail pages)", "BreadcrumbList (every page)", "FAQPage (FAQ pages only)" ], "og_image": "1200x630px, brand colors, under 200KB", "title_rules": "{Service} | {Brand} | {City}, {State}", "description_rules": "150-160 chars, action-oriented, include city + service" }, "images": { "format": "AVIF + JPG fallback", "picture_element_required": true, "conversion_command": "convert input.jpg -resize 1920x -quality 80 -define avif:speed=6 output.avif", "size_targets": { "portrait": "original width, 80 quality, 50-120KB", "hero": "1920px max, 80 quality, 150-350KB", "og_social": "1200px, 85 quality, under 150KB" }, "hero_naming": "hero-{page-slug}.avif + .jpg fallback", "attributes_required": ["alt text or alt=\"\"", "loading=\"lazy\" (except hero)", "width and height"] }, "mobile": { "breakpoints": { "320": "mobile-first base", "360": "iPhone SE portrait", "480": "small phones", "600": "phones", "768": "tablets (main mobile breakpoint)", "900": "small laptops, tablet landscape", "1023": "IMPORTANT: switch to mobile menu here", "1024": "sub-desktop" }, "header_nav_switch_at": "max-width: 1023px (not 768px)", "touch_targets_minimum": "44x44px (Apple HIG, WCAG)", "grid_mobile_override": "grid-template-columns: 1fr !important at 900px", "overflow_protection": "overflow-x: clip; max-width: 100%" }, "cookie_consent": { "option1": { "name": "orestbida/cookieconsent", "stars": "4600+", "size": "23KB UMD + 32KB CSS", "license": "MIT", "recommendation": "default choice" }, "option2": { "name": "Osano Cookie Consent", "stars": "3500+", "size": "30KB bundle", "license": "MIT" }, "when_not_needed": "GDPR Article 4(11): strictly necessary cookies (session, CSRF, form state) exempt from consent" }, "testing": { "build_verification": "grep -rn '{{' site/ -- result: empty", "container_health": "docker compose ps, docker logs, curl / returns 200", "url_surface": "public paths 200, sensitive paths 404", "mobile_responsive": "zero horizontal overflow at 320, 360, 390, 768, 900, 1023, 1024, 1200", "form_e2e": "submit real form, verify email arrives", "rate_limit": "request 6 returns 429 Too Many Requests", "seo_surface": "all pages have title, canonical, og:, schema JSON-LD", "cache_busting": "main.css?v= changes on deploy", "pre_launch_gates": [ "All public URLs 200", "All sensitive URLs 404", "No sensitive files in container", "Zero mobile overflow", "Form submits, email arrives", "Rate limit triggers", "All pages have required meta tags", "robots.txt and sitemap.xml exist", "Zero em-dashes in HTML/JSON", "Resend domain fully verified", "Test email lands in primary inbox", "Tested on real iPhone and Android", "Lighthouse scores 90+ on all categories" ] }, "never_use": [ "Node.js / npm on frontend", "WordPress for new builds", "CSS frameworks (Bootstrap, Tailwind, Bulma)", "JS frameworks (React, Vue, Angular, Svelte)", "jQuery, Lodash, Moment, axios, utility libraries", "CSS-in-JS, styled-components", "Build tools requiring node_modules", "Tracking pixels (except client-explicitly-requested)", "Single monolithic database", "Hardcoded copy in PHP templates", "Docker Compose for arisingmedia.us stack", "Google Drive / Sheets for content (evaluated and reverted 2026-06)" ], "secure_app_features": { "when_to_use": "File conversion, encryption, payment processing, user authentication, rate-limited APIs", "php_hardening": [ "CSRF token on every POST endpoint", "Rate limiting (nginx + PHP file-backed)", "Altcha proof-of-work verification", "At-rest encryption (sodium_crypto_secretbox + secretstream)", "Signed download tokens (never expose file paths)", "Server-side validation + HTML-escaped output", "Session httponly + secure flags", "storage/ directory access denied via .htaccess" ], "database": "SQLite with pdo_sqlite, schema migrations in try/catch, BEGIN IMMEDIATE transactions", "environment": { "clear_env": "no (php-fpm-pool.conf)", "secrets": ".env (never hardcoded, never committed)", "trust_proxy": "1 when behind reverse proxy", "encryption_key": "32-byte hex QC_ENCRYPTION_KEY", "altcha_key": "32-byte hex ALTCHA_HMAC_KEY" }, "reference": "quickconvert.us" }, "directory_structure": { "src/api/": "PHP router, contact handler, templates, components, data (SQLite)", "src/assets/": "CSS (tokens.css + main.css), JS (vanilla only), images (AVIF+JPG), altcha, cookieconsent", "build/": "seed_databases.py", "infra/": "nginx.conf, supervisord.conf, php-fpm-pool.conf, entrypoint.sh", ".planning/": "not served, not in Docker image", "root_files": "Dockerfile, docker-compose.yml, .dockerignore, .htaccess, .cpanel.yml, .gitignore, .env (ignored)" } }