Replace v1 with v2 codebase

Full rewrite: swap out the v1 framework (src/, controllers/, views/,
twig/, sass/, skeleton/) for the working v2 codebase from phpproject
(App/, novaconium/, public/).
This commit is contained in:
code
2026-07-14 01:58:25 +00:00
parent d9c4b64d9c
commit fbd4e92e9f
460 changed files with 30107 additions and 4661 deletions
+63
View File
@@ -0,0 +1,63 @@
{% extends layout %}
{% block title %}Contact{% endblock %}
{% block description %}Get in touch — send a message using the contact form.{% endblock %}
{# Every block below is optional — the layout already supplies a sensible
default for each (see /admin/docs/seo). Shown here uncommented as a
reference for every override a page can make; delete what you don't
need. #}
{% block robots %}index, follow{% endblock %}
{% block canonical %}{{ request_path|default('/') }}{% endblock %}
{% block og_type %}website{% endblock %}
{% block og_title %}{{ block('title') }}{% endblock %}
{% block og_description %}{{ block('description') }}{% endblock %}
{% block og_url %}{{ block('canonical') }}{% endblock %}
{% block twitter_card %}summary{% endblock %}
{% block twitter_title %}{{ block('title') }}{% endblock %}
{% block twitter_description %}{{ block('description') }}{% endblock %}
{% import '_layout/icons.twig' as icons %}
{% block content %}
<article>
<h1 class="icon-heading">{{ icons.email() }}Contact</h1>
<p>This form is handled entirely by <code>App/pages/contact/index.php</code>, a sidecar demonstrating the classic POST/redirect/GET pattern: it validates <code>$_POST</code>, calls <code>Lib\Mailer::send()</code> on success, and redirects to <code>/contact?sent=1</code> — so refreshing the page after submitting never resubmits the form. Because this page has a sidecar, it's never served from the static cache; see <a class="icon-link" href="/admin/docs/sidecars">{{ icons.book() }}Sidecars</a> and <a class="icon-link" href="/admin/docs/libraries">{{ icons.book() }}Libraries</a> for the full contract. It's also a working example of self-hosted spam prevention (honeypot field + submission-timing check, no external CAPTCHA service) — see <a class="icon-link" href="/admin/docs/sidecars">{{ icons.book() }}Sidecars</a>' "Spam prevention" section.</p>
{% if sent %}
<p><strong>Thanks — your message has been sent.</strong></p>
{% endif %}
{% if securityError %}
<p><strong>Your session expired before submitting — please try again.</strong></p>
{% endif %}
<form method="post" action="/contact">
<input type="hidden" name="{{ csrfField }}" value="{{ csrfToken }}">
<div class="hp-field" aria-hidden="true">
<label for="website">Leave this field blank</label>
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
</div>
<input type="hidden" name="rendered_at" value="{{ renderedAt }}">
<p>
<label for="name">Name</label><br>
<input type="text" id="name" name="name" value="{{ old.name }}">
{% if errors.name %}<br><small>{{ errors.name }}</small>{% endif %}
</p>
<p>
<label for="email">Email</label><br>
<input type="text" id="email" name="email" value="{{ old.email }}">
{% if errors.email %}<br><small>{{ errors.email }}</small>{% endif %}
</p>
<p>
<label for="message">Message</label><br>
<textarea id="message" name="message" rows="5">{{ old.message }}</textarea>
{% if errors.message %}<br><small>{{ errors.message }}</small>{% endif %}
</p>
<button type="submit">Send</button>
</form>
</article>
{% endblock %}