Shared Coding Principles Reference

Coding Principles

This page mirrors the coding-principles source in the same visual-plus-raw format as the design specs page, so you can browse the engineering rules quickly and still hand the exact source to AI when needed.

Core Principles

The high-level rules that all local apps should follow before anyone gets fancy.

Core idea
Predictable beats clever
Keep structure consistent across all apps.
Thin controllers, meaningful services, and clean data access layers.
Prefer clear and boring over clever and fragile.
Security needs to be built in, not bolted on afterwards.
Follow existing patterns before inventing new ones.
Refactor duplication before it spreads.
Update docs and changelog when behaviour changes.
Always do a final regression sweep before calling work done.
AI Build Rules

Use these as the default behavioural contract when asking AI to change app code.

Use the existing controller / service / repository / view split unless there is a very good reason not to.
Prefer extending current shared helpers and patterns rather than adding one-off solutions.
Return predictable result shapes from handlers and services.
Avoid god classes. Split large services before they become the final boss.
Log meaningful events, especially for admin actions, failures, and sensitive flows.
Keep configuration centralised in env or config files. No mystery constants hidden in random files.
In development, errors should be clear, specific, and easy to trace. In production, errors should be generic for users and detailed only in logs.

Principle Areas

These are the big buckets every app change should line up with.

Architecture

Structure first
Thin controllers

Controllers should receive the request, call the right service, and return the response. They should not contain business logic, SQL, or giant piles of conditional chaos.

Services hold business rules

Put actual application logic in services. If a rule matters to how the app behaves, it belongs in a service or dedicated domain class, not scattered across templates and handlers.

Repositories own data access

Database queries should live in repository-style classes or clearly defined data access layers. No random inline SQL in controllers, views, or utility files.

Views render only

Templates should display data, not work it out. Keep logic in the backend so the HTML stays readable and the rules stay testable.

Code Quality

Readable wins
Prefer boring code

Simple, obvious code beats clever code nearly every time. If someone has to squint at it for 30 seconds, it is probably too fancy.

Single responsibility

Each class and function should do one job well. If a service validates input, writes files, sends emails, updates the database, and makes tea, it needs splitting up.

Consistent naming

Names should explain intent. Use predictable suffixes like Controller, Service, Repository, ViewModel, ActionResult, or Handler so the codebase feels designed, not accidental.

Avoid duplication

If logic appears in more than one place, centralise it. Duplication is how bugs breed and maintenance becomes a tax.

Security

No cowboy stuff
Validate all input

Never trust request data. Validate early, normalise where needed, and fail clearly. User input should not get a free pass just because the form looked nice.

Escape output properly

Anything shown in HTML should be escaped unless it is explicitly trusted and sanitised. XSS is still a thing, sadly.

Use parameterised queries

No string-built SQL. Ever. Use prepared statements or query builders properly so injection risks stay in the bin.

Protect auth flows

Login, logout, password reset, sessions, and callback handlers need deliberate review. Rate limiting, CSRF protection, secure session handling, and correct redirects are not optional extras.

Change Discipline

Build properly
Follow existing patterns

New code should match the architecture, naming, and UX conventions already in the app. Do not reinvent the wheel just because this page feels special.

Update docs with changes

If behaviour, architecture, endpoints, jobs, config, or admin flow changes, update the docs and changelog in the same piece of work.

Do a final sweep

Before calling a task done, re-check for regressions, old references, dead code, and half-finished wiring. The first fix often misses a corner.

Leave the area cleaner

If you touch messy code, improve it a bit. Not a wild rewrite — just enough to stop the mess getting worse.

PHP-Specific Principles

Use strict typing where practical

Use typed properties, typed parameters, and return types wherever the codebase supports it.

Prefer explicit classes over magic

Avoid over-reliance on magic methods, hidden globals, and side-effect-heavy includes.

Prefer guard clauses

Fail fast on invalid state rather than nesting half the file inside giant conditionals.

Database + Security

Queries belong in repositories

Keep SQL in dedicated repository-style classes or clearly named query services.

Use parameterised queries only

Never build SQL by concatenating request input.

Never trust request data

Validate, normalise, and authorise everything coming in.

Escape output by default

Anything rendered into HTML should be escaped unless explicitly sanitised.

Delivery Discipline

Update docs when behaviour changes

Documentation and changelog updates are part of the same work, not a future task.

Remove dead code properly

Replacements are not finished until the old path is actually gone.

Prefer extension over random patching

Add new behaviour through clear classes and shared patterns rather than wedging conditionals into fragile code.

Do
  • Use clear folder structure and naming conventions.
  • Refactor repeated logic into shared services or helpers.
  • Keep methods short enough to understand without scrolling forever.
  • Write code as if future-you is already annoyed with present-you.
  • Show detailed, actionable errors in development environments only.
Don't
  • Do not dump business logic into templates.
  • Do not create special-case utility files for one awkward page unless they truly belong.
  • Do not hardcode secrets, URLs, IDs, or environment-dependent values.
  • Do not leave dead code and old auth paths hanging around like haunted furniture.
  • Do not expose stack traces, SQL errors, tokens, or sensitive internals to production users.

Good Flow

  • Controller receives request
  • Request data validated
  • Service performs business logic
  • Repository persists changes
  • Controller returns view or JSON result

Messy Flow

  • Controller validates half the request
  • Inline SQL updates three tables
  • Template calculates totals and permissions
  • Random helper sends email
  • No logging, no tests, no regrets apparently
AI Change Rules
Always follow existing architecture, naming, and UI patterns before creating anything new.
Always update documentation and changelog when behaviour, structure, routes, endpoints, or flows change.
Always remove replaced or obsolete code fully rather than leaving legacy paths behind.
Always do a final sweep for regressions, dead code, stale references, and inconsistent behaviour before considering the change complete.
Do not introduce parallel systems, duplicate helpers, or alternate flows unless explicitly requested.
Prefer improving the current system over bolting on a second one beside it.
Definition Of Done
The feature follows existing architecture and naming rules.
Validation and security concerns are handled properly.
Docs and changelog are updated if behaviour changed.
Old or dead code related to the change is removed.
Logging is added where the action matters.
A final sweep has been done for regressions and missed edges.
Text Version For AI

This is the plain-English handoff summary of the coding principles source.

  • Use a clear controller, service, repository, and view split unless there is a very strong reason not to.
  • Keep controllers thin, templates simple, services meaningful, and data access centralised.
  • Prefer boring, readable, single-responsibility code over clever abstractions and sprawling god classes.
  • Validate request data early, escape output by default, use parameterised queries, and treat auth/session work as high-attention code.
  • Keep naming, folder structure, response shapes, and shared patterns consistent across apps.
  • Use centralised config and env-driven settings rather than hardcoded secrets or mystery constants.
  • Development errors should be specific and useful. Production errors should be generic for users and detailed in logs only.
  • Update docs and changelog when behaviour changes, remove dead code properly, and finish replacements fully.
  • AI-generated changes should extend the existing system, not invent parallel frameworks, duplicate helpers, or alternate flows.
Raw Principles Source

Verbatim contents of `local-app-principles-system-site.jsx` for copy/paste into AI.

export default function LocalAppCodingPrinciples() {
  const principleGroups = [
    {
      title: 'Architecture',
      badge: 'Structure first',
      items: [
        {
          title: 'Thin controllers',
          body: 'Controllers should receive the request, call the right service, and return the response. They should not contain business logic, SQL, or giant piles of conditional chaos.',
        },
        {
          title: 'Services hold business rules',
          body: 'Put actual application logic in services. If a rule matters to how the app behaves, it belongs in a service or dedicated domain class, not scattered across templates and handlers.',
        },
        {
          title: 'Repositories own data access',
          body: 'Database queries should live in repository-style classes or clearly defined data access layers. No random inline SQL in controllers, views, or utility files.',
        },
        {
          title: 'Views render only',
          body: 'Templates should display data, not work it out. Keep logic in the backend so the HTML stays readable and the rules stay testable.',
        },
      ],
    },
    {
      title: 'Code Quality',
      badge: 'Readable wins',
      items: [
        {
          title: 'Prefer boring code',
          body: 'Simple, obvious code beats clever code nearly every time. If someone has to squint at it for 30 seconds, it is probably too fancy.',
        },
        {
          title: 'Single responsibility',
          body: 'Each class and function should do one job well. If a service validates input, writes files, sends emails, updates the database, and makes tea, it needs splitting up.',
        },
        {
          title: 'Consistent naming',
          body: 'Names should explain intent. Use predictable suffixes like Controller, Service, Repository, ViewModel, ActionResult, or Handler so the codebase feels designed, not accidental.',
        },
        {
          title: 'Avoid duplication',
          body: 'If logic appears in more than one place, centralise it. Duplication is how bugs breed and maintenance becomes a tax.',
        },
      ],
    },
    {
      title: 'Security',
      badge: 'No cowboy stuff',
      items: [
        {
          title: 'Validate all input',
          body: 'Never trust request data. Validate early, normalise where needed, and fail clearly. User input should not get a free pass just because the form looked nice.',
        },
        {
          title: 'Escape output properly',
          body: 'Anything shown in HTML should be escaped unless it is explicitly trusted and sanitised. XSS is still a thing, sadly.',
        },
        {
          title: 'Use parameterised queries',
          body: 'No string-built SQL. Ever. Use prepared statements or query builders properly so injection risks stay in the bin.',
        },
        {
          title: 'Protect auth flows',
          body: 'Login, logout, password reset, sessions, and callback handlers need deliberate review. Rate limiting, CSRF protection, secure session handling, and correct redirects are not optional extras.',
        },
      ],
    },
    {
      title: 'Change Discipline',
      badge: 'Build properly',
      items: [
        {
          title: 'Follow existing patterns',
          body: 'New code should match the architecture, naming, and UX conventions already in the app. Do not reinvent the wheel just because this page feels special.',
        },
        {
          title: 'Update docs with changes',
          body: 'If behaviour, architecture, endpoints, jobs, config, or admin flow changes, update the docs and changelog in the same piece of work.',
        },
        {
          title: 'Do a final sweep',
          body: 'Before calling a task done, re-check for regressions, old references, dead code, and half-finished wiring. The first fix often misses a corner.',
        },
        {
          title: 'Leave the area cleaner',
          body: 'If you touch messy code, improve it a bit. Not a wild rewrite — just enough to stop the mess getting worse.',
        },
      ],
    },
  ];

  const buildRules = [
    'Use the existing controller / service / repository / view split unless there is a very good reason not to.',
    'Prefer extending current shared helpers and patterns rather than adding one-off solutions.',
    'Return predictable result shapes from handlers and services.',
    'Avoid god classes. Split large services before they become the final boss.',
    'Log meaningful events, especially for admin actions, failures, and sensitive flows.',
    'Keep configuration centralised in env or config files. No mystery constants hidden in random files.',
    'In development, errors should be clear, specific, and easy to trace. In production, errors should be generic for users and detailed only in logs.',
  ];

  const aiChangeRules = [
    'Always follow existing architecture, naming, and UI patterns before creating anything new.',
    'Always update documentation and changelog when behaviour, structure, routes, endpoints, or flows change.',
    'Always remove replaced or obsolete code fully rather than leaving legacy paths behind.',
    'Always do a final sweep for regressions, dead code, stale references, and inconsistent behaviour before considering the change complete.',
    'Do not introduce parallel systems, duplicate helpers, or alternate flows unless explicitly requested.',
    'Do not reinvent shared components, services, repositories, or admin patterns when an existing approach already fits.',
    'Do not hide uncertainty. If something is ambiguous or risky, make the assumption clear in the code comments or change notes.',
    'Prefer improving the current system over bolting on a second one beside it.',
  ];

  const dosAndDonts = [
    {
      title: 'Do',
      tone: 'bg-green-50 border-green-200',
      badge: 'bg-green-500 text-white',
      items: [
        'Use clear folder structure and naming conventions.',
        'Refactor repeated logic into shared services or helpers.',
        'Keep methods short enough to understand without scrolling forever.',
        'Write code as if future-you is already annoyed with present-you.',
        'Show detailed, actionable errors in development environments only.',
      ],
    },
    {
      title: 'Don’t',
      tone: 'bg-red-50 border-red-200',
      badge: 'bg-red-500 text-white',
      items: [
        'Do not dump business logic into templates.',
        'Do not create special-case utility files for one awkward page unless they truly belong.',
        'Do not hardcode secrets, URLs, IDs, or environment-dependent values.',
        'Do not leave dead code and old auth paths hanging around like haunted furniture.',
        'Do not expose stack traces, SQL errors, tokens, or sensitive internals to production users.',
      ],
    },
  ];

  const phpPrinciples = [
    {
      title: 'Use strict typing where practical',
      body: 'Use typed properties, typed parameters, and return types wherever the codebase supports it. Loose PHP can be handy, but it also lets dumb mistakes wander through the door unnoticed.',
    },
    {
      title: 'Prefer explicit classes over magic',
      body: 'Avoid over-reliance on magic methods, hidden globals, and side-effect-heavy includes. Clear dependencies beat mystery behaviour every time.',
    },
    {
      title: 'Keep includes and bootstrap predictable',
      body: 'Centralise bootstrapping, config loading, shared helpers, and auth/session wiring. Do not let every entry point invent its own startup ritual.',
    },
    {
      title: 'Use shared response patterns',
      body: 'Handlers and controllers should return predictable response objects, arrays, or view models rather than improvised structures that change from file to file.',
    },
    {
      title: 'Separate pure logic from side effects',
      body: 'Validation, formatting, and calculation logic should be easy to test without needing to hit the database, session, or filesystem every time.',
    },
    {
      title: 'Prefer guard clauses',
      body: 'Fail fast on invalid state rather than nesting half the file inside giant if statements like a Russian doll of regret.',
    },
  ];

  const databasePrinciples = [
    {
      title: 'Queries belong in repositories or data layers',
      body: 'Keep SQL in dedicated repository-style classes or clearly named query services. Controllers and views should not be sneaking off to the database.',
    },
    {
      title: 'Use parameterised queries only',
      body: 'Never build SQL by concatenating request input. Prepared statements are the baseline, not a gold-plated luxury upgrade.',
    },
    {
      title: 'Select only what you need',
      body: 'Do not default to SELECT *. Pull back the fields the screen or process actually needs so queries stay lean and intent stays obvious.',
    },
    {
      title: 'Handle writes deliberately',
      body: 'For inserts, updates, and deletes, be explicit about affected rows, expected outcomes, and any dependent operations. Silent failures are a pain to trace.',
    },
    {
      title: 'Use transactions for related writes',
      body: 'If multiple operations must all succeed together, wrap them in a transaction. Half-saved state is how data turns feral.',
    },
    {
      title: 'Log and surface database failures correctly',
      body: 'Detailed query failures belong in logs. User-facing production messages should stay generic and safe.',
    },
  ];

  const securityPrinciples = [
    {
      title: 'Never trust request data',
      body: 'Validate, normalise, and authorise everything coming in. The fact it came from your own form does not make it trustworthy.',
    },
    {
      title: 'Protect secrets and config',
      body: 'Secrets belong in env files or secure config, never hardcoded into controllers, templates, JavaScript, or public repositories.',
    },
    {
      title: 'Review auth and session flows carefully',
      body: 'Login, logout, password reset, SSO callbacks, remember-me flows, and session handling deserve deliberate end-to-end review.',
    },
    {
      title: 'Escape output by default',
      body: 'Anything rendered into HTML should be escaped unless it has been explicitly sanitised and is meant to support safe markup.',
    },
    {
      title: 'Limit sensitive exposure',
      body: 'Do not expose internal IDs, stack traces, tokens, SQL, filesystem paths, or other internals to production users.',
    },
    {
      title: 'Log security-relevant actions',
      body: 'Failed logins, admin changes, permissions changes, suspicious input, and sensitive operations should leave a meaningful audit trail.',
    },
  ];

  const errorHandlingPrinciples = [
    {
      title: 'Development errors should be obvious',
      body: 'In development, error messages should clearly say what failed, where, and what the likely cause is. Helpful errors speed up building and debugging massively.',
    },
    {
      title: 'Production errors should be generic',
      body: 'In production, users should see safe, plain-English messages like “Something went wrong” or “We could not save your changes right now.” No stack traces. No SQL. No internal paths.',
    },
    {
      title: 'Detailed failures belong in logs',
      body: 'The real exception, query error, stack trace, request context, and correlation details should go to logs or monitoring, not to the browser in production.',
    },
    {
      title: 'Use consistent error shapes',
      body: 'Validation errors, API failures, and system exceptions should follow predictable response formats so the frontend and logs are easier to work with.',
    },
  ];

  const documentationPrinciples = [
    {
      title: 'Update docs when behaviour changes',
      body: 'If a feature, endpoint, workflow, config path, background job, admin flow, or architectural decision changes, update the related documentation in the same piece of work.',
    },
    {
      title: 'Docs should explain why',
      body: 'Code already shows what the app does. Documentation should explain why something exists, how the moving parts fit together, and what assumptions matter.',
    },
    {
      title: 'Keep docs in predictable locations',
      body: 'Use a consistent docs structure such as architecture, endpoints, setup, lifecycle, and changelog so the answers are easy to find without a treasure map.',
    },
    {
      title: 'Changelog updates are mandatory',
      body: 'Meaningful changes should be recorded in the changelog so future work has a reliable timeline of what changed and when.',
    },
  ];

  const commentPrinciples = [
    {
      title: 'Comment intent, not the obvious',
      body: 'Comments should explain why a block exists, what edge case it is protecting, or what trade-off was chosen. They should not narrate basic syntax like a sports commentator for foreach loops.',
    },
    {
      title: 'Use comments for non-obvious rules',
      body: 'If a validation rule, workaround, dependency quirk, or performance decision is not obvious from the code, add a short comment so the next person does not have to reverse-engineer your thinking.',
    },
    {
      title: 'Prefer refactoring over comment-padding',
      body: 'If code needs a paragraph to explain what it is doing, the code probably needs restructuring. Clean code beats a swamp with subtitles.',
    },
    {
      title: 'Mark temporary work clearly',
      body: 'Use TODO or FIXME comments only when they are specific and actionable. Vague comments like “sort this later” are just decorative guilt.',
    },
  ];

  const refactoringPrinciples = [
    {
      title: 'Leave touched code better',
      body: 'When working in an area, improve the structure where sensible. Do not launch a reckless rewrite, but do not leave obvious duplication and confusion untouched either.',
    },
    {
      title: 'Break up large classes early',
      body: 'Once a service starts handling too many responsibilities, split it before it becomes a god class that everyone is scared to edit.',
    },
    {
      title: 'Extract repeated logic quickly',
      body: 'As soon as behaviour appears in multiple places, centralise it into a shared helper, service, policy, or repository method.',
    },
    {
      title: 'Refactor around stable patterns',
      body: 'Improve the codebase by moving closer to known architecture patterns rather than creating new mini-frameworks in random folders.',
    },
  ];

  const validationPrinciples = [
    {
      title: 'Validate at the boundary',
      body: 'Incoming request data should be validated as early as possible, ideally before it enters the main business logic flow.',
    },
    {
      title: 'Do not trust frontend validation',
      body: 'Client-side checks are useful for UX, but the backend remains the source of truth. Everything important must be validated server-side too.',
    },
    {
      title: 'Keep validation rules consistent',
      body: 'Validation rules should not drift between create and edit flows, or between API and web paths, unless there is a deliberate reason.',
    },
    {
      title: 'Fail clearly and predictably',
      body: 'Validation failures should return consistent messages and shapes so forms, APIs, and admins all behave in a predictable way.',
    },
  ];

  const consistencyPrinciples = [
    {
      title: 'Use consistent naming',
      body: 'Class, file, route, variable, and template names should follow shared patterns so the structure feels intentional and easy to navigate.',
    },
    {
      title: 'Use consistent folder structure',
      body: 'Apps should share a familiar layout for controllers, services, repositories, templates, config, docs, and public entry points.',
    },
    {
      title: 'Use consistent response patterns',
      body: 'Controllers and handlers should return predictable success, validation, and error shapes rather than improvising per file.',
    },
    {
      title: 'Follow existing product patterns',
      body: 'Admin pages, forms, auth flows, and utility helpers should reuse current house patterns before introducing new ones.',
    },
  ];

  const configPrinciples = [
    {
      title: 'Environment values belong in config',
      body: 'Secrets, URLs, API keys, ports, toggles, and environment-specific settings should live in env files or central config, not hardcoded in random code paths.',
    },
    {
      title: 'Use a central config approach',
      body: 'Load configuration through a shared bootstrap or config layer so every part of the app resolves settings in the same way.',
    },
    {
      title: 'Avoid magic constants',
      body: 'Random literals hidden in services and controllers make behaviour hard to trace. Name important values and place them where they belong.',
    },
    {
      title: 'Use feature toggles deliberately',
      body: 'If a behaviour needs to vary by environment or rollout stage, use a clear config flag rather than a hidden conditional buried in a method.',
    },
  ];

  const extensibilityPrinciples = [
    {
      title: 'Build for likely change',
      body: 'Design code so common future changes are easy, but do not overengineer for five imaginary use cases that may never arrive.',
    },
    {
      title: 'Keep layer boundaries clean',
      body: 'Loose coupling between controllers, services, repositories, and views makes new features easier to add without collateral damage.',
    },
    {
      title: 'Prefer extension over random patching',
      body: 'When possible, add new behaviour through clear classes and shared patterns rather than wedging conditionals into already fragile code.',
    },
    {
      title: 'Preserve stable contracts',
      body: 'Be careful when changing method signatures, response formats, or template data contracts that other parts of the app depend on.',
    },
  ];

  const cleanupPrinciples = [
    {
      title: 'Remove dead code properly',
      body: 'When a feature or flow is replaced, remove the old code, old config, old routes, and old docs rather than leaving them behind as a haunted backup plan.',
    },
    {
      title: 'Delete unused branches and helpers',
      body: 'Old one-off helpers, retired auth paths, and abandoned template branches should be cleaned up once they are no longer used.',
    },
    {
      title: 'Trust version control',
      body: 'Do not keep dead code around “just in case.” That is what Git is for, and it is better at remembering the past than your production codebase.',
    },
    {
      title: 'Finish replacements fully',
      body: 'A replacement is not done until the old path is removed and all references point to the new one consistently.',
    },
  ];

  const examples = [
    {
      title: 'Good flow',
      code: [
        'Controller receives request',
        'Request data validated',
        'Service performs business logic',
        'Repository persists changes',
        'Controller returns view or JSON result',
      ],
    },
    {
      title: 'Messy flow',
      code: [
        'Controller validates half the request',
        'Inline SQL updates three tables',
        'Template calculates totals and permissions',
        'Random helper sends email',
        'No logging, no tests, no regrets apparently',
      ],
    },
  ];

  return (
    <div className="min-h-screen bg-gradient-to-br from-white via-green-50 to-slate-100 text-slate-900">
      <div className="mx-auto max-w-7xl px-6 py-8 lg:px-8">
        <header className="mb-8 overflow-hidden rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-2xl shadow-green-100 backdrop-blur">
          <div className="flex flex-col gap-8 xl:flex-row xl:items-center xl:justify-between">
            <div className="max-w-4xl">
              <div className="mb-4 inline-flex items-center gap-3 rounded-full border border-green-200 bg-green-50 px-4 py-2 text-sm font-medium text-green-700">
                <span className="inline-block h-2.5 w-2.5 rounded-full bg-green-500" />
                Shared Coding Principles Reference
              </div>
              <h1 className="text-4xl font-black tracking-tight text-slate-950 md:text-6xl">
                One coding standard for all your local apps.
              </h1>
              <p className="mt-4 max-w-3xl text-lg leading-8 text-slate-600">
                This is the reference guide for how code should be structured, named, reviewed, secured, and extended across your apps. Same idea as the design system — but for architecture and engineering discipline instead of buttons and pretty gradients.
              </p>
            </div>

            <div className="rounded-[2rem] bg-gradient-to-br from-green-500 via-emerald-500 to-lime-400 p-5 text-white shadow-xl">
              <div className="text-sm uppercase tracking-[0.22em] text-white/80">Core idea</div>
              <div className="mt-2 text-2xl font-black">Predictable beats clever</div>
              <div className="mt-2 text-sm text-white/85">If every app follows the same engineering rules, scaling and maintenance stop being a pain.</div>
            </div>
          </div>
        </header>

        <section className="mb-8 grid gap-6 xl:grid-cols-[1.15fr_0.85fr]">
          <div className="rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
            <h2 className="text-2xl font-bold text-slate-950">Core Principles</h2>
            <div className="mt-5 grid gap-4 md:grid-cols-2">
              {[
                'Keep structure consistent across all apps.',
                'Thin controllers, meaningful services, and clean data access layers.',
                'Prefer clear and boring over clever and fragile.',
                'Security needs to be built in, not bolted on afterwards.',
                'Follow existing patterns before inventing new ones.',
                'Refactor duplication before it spreads.',
                'Update docs and changelog when behaviour changes.',
                'Always do a final regression sweep before calling work done.',
              ].map((rule) => (
                <div key={rule} className="rounded-2xl border border-slate-100 bg-slate-50/70 p-4 text-sm leading-6 text-slate-700">
                  {rule}
                </div>
              ))}
            </div>
          </div>

          <div className="rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
            <h2 className="text-2xl font-bold text-slate-950">AI Build Rules</h2>
            <div className="mt-5 space-y-3 text-sm leading-6 text-slate-700">
              {buildRules.map((rule) => (
                <div key={rule} className="rounded-2xl bg-slate-50 p-4">{rule}</div>
              ))}
            </div>
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Principle Areas</h2>
            <p className="mt-2 text-sm text-slate-600">These are the big buckets every app change should line up with.</p>
          </div>

          <div className="space-y-6">
            {principleGroups.map((group) => (
              <div key={group.title} className="rounded-[2rem] border border-slate-200 bg-slate-50/60 p-6">
                <div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
                  <div>
                    <h3 className="text-2xl font-bold text-slate-950">{group.title}</h3>
                  </div>
                  <div className="inline-flex rounded-full border border-green-200 bg-green-50 px-4 py-2 text-sm font-semibold text-green-700">
                    {group.badge}
                  </div>
                </div>

                <div className="mt-5 grid gap-4 md:grid-cols-2">
                  {group.items.map((item) => (
                    <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                      <div className="text-lg font-bold text-slate-900">{item.title}</div>
                      <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
                    </div>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">PHP-Specific Principles</h2>
            <p className="mt-2 text-sm text-slate-600">These keep PHP apps predictable, testable, and less likely to become a swamp of includes and side effects.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            {phpPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Database / Query Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Database work should be deliberate, safe, and easy to trace when something goes sideways.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            {databasePrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Security Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Security is not a sprinkle-on topping. It needs to be baked into request handling, auth, rendering, logging, and configuration.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            {securityPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Error Handling Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Errors should help developers fix problems quickly without handing production users a bag of internal secrets.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {errorHandlingPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Documentation Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Documentation should stay useful, current, and tied to real changes rather than becoming a dusty side quest nobody trusts.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {documentationPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Code Comment Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Comments should explain intent and awkward edge cases, not narrate painfully obvious code line by line.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {commentPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Refactoring Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Refactoring should be a normal part of delivery, not a mythical future cleanup week that never arrives.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {refactoringPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Validation & Data Integrity Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Validation should be consistent, early, and trusted on the server rather than left to frontend pinky promises.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {validationPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Consistency Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Consistency is what makes a codebase feel designed instead of accidentally assembled over twelve late nights.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {consistencyPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Configuration & Environment Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Environment-specific behaviour should be controlled centrally, not hidden in random conditionals scattered across the app.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {configPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Extensibility Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Build for likely future changes without turning every project into an overengineered shrine to theoretical flexibility.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {extensibilityPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Removal & Cleanup Principles</h2>
            <p className="mt-2 text-sm text-slate-600">Replacing something is not finished until the old path is properly dead and buried.</p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {cleanupPrinciples.map((item) => (
              <div key={item.title} className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="text-lg font-bold text-slate-900">{item.title}</div>
                <p className="mt-3 text-sm leading-7 text-slate-600">{item.body}</p>
              </div>
            ))}
          </div>
        </section>

        <section className="mb-8 grid gap-6 lg:grid-cols-2">
          {dosAndDonts.map((group) => (
            <div key={group.title} className={`rounded-[2rem] border p-8 shadow-xl backdrop-blur ${group.tone}`}>
              <div className={`inline-flex rounded-full px-4 py-2 text-sm font-semibold ${group.badge}`}>{group.title}</div>
              <ul className="mt-5 space-y-3 text-sm leading-6 text-slate-700">
                {group.items.map((item) => (
                  <li key={item} className="rounded-2xl bg-white/80 px-4 py-3 shadow-sm">{item}</li>
                ))}
              </ul>
            </div>
          ))}
        </section>

        <section className="mb-8 grid gap-6 lg:grid-cols-2">
          {examples.map((example) => (
            <div key={example.title} className="rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
              <h2 className="text-2xl font-bold text-slate-950">{example.title}</h2>
              <div className="mt-5 rounded-3xl border border-slate-200 bg-slate-50 p-5">
                <ul className="space-y-2 text-sm leading-6 text-slate-700">
                  {example.code.map((line) => (
                    <li key={line} className="rounded-2xl bg-white px-3 py-2 font-mono text-[13px] text-slate-700 shadow-sm">
                      {line}
                    </li>
                  ))}
                </ul>
              </div>
            </div>
          ))}
        </section>

        <section className="mb-8 rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">AI Change Rules</h2>
            <p className="mt-2 text-sm text-slate-600">These rules exist so AI-generated changes extend the current system properly instead of wandering off and founding a second framework in the shed.</p>
          </div>

          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            {aiChangeRules.map((rule) => (
              <div key={rule} className="rounded-3xl border border-slate-200 bg-white p-5 text-sm leading-6 text-slate-700 shadow-sm">
                {rule}
              </div>
            ))}
          </div>
        </section>

        <section className="rounded-[2rem] border border-white/60 bg-white/85 p-8 shadow-xl backdrop-blur">
          <div className="mb-6">
            <h2 className="text-2xl font-bold text-slate-950">Definition of Done</h2>
            <p className="mt-2 text-sm text-slate-600">A piece of work is not done just because the page loads and nothing is on fire.</p>
          </div>

          <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            {[
              'The feature follows existing architecture and naming rules.',
              'Validation and security concerns are handled properly.',
              'Docs and changelog are updated if behaviour changed.',
              'Old or dead code related to the change is removed.',
              'Logging is added where the action matters.',
              'A final sweep has been done for regressions and missed edges.',
            ].map((item) => (
              <div key={item} className="rounded-3xl border border-slate-200 bg-white p-5 text-sm leading-6 text-slate-700 shadow-sm">
                {item}
              </div>
            ))}
          </div>
        </section>
      </div>
    </div>
  );
}