Files
AsterionWP2026/tools/av-generate-home.php
j.foucher 38c0c5031e feat(pages): generate Phases 8-11 — Technology + Editorial + Forms + Home
Brings the site to its full programmatic page count : 24 EN + 24 FR pages
(48 total), all wired into the WPML CTE workflow established in the previous
commit. Each phase reuses tools/_av-bricks-shared.php builders, adds its own
filter('av_fr_translation_dict') to extend the FR dictionary, and ships a
seed-FR mu-plugin for the initial WPML trid linking.

## Phase 8 — Technology (tools/av-generate-technology.php + seed)
Hub /technology/ + 6 pillar pages (vr-hardware, software-ai, weapons-tracking,
scenarios, instructor-cockpit, after-action-review). Hub uses a 6-card grid
(3+3 layout — added card_count=6 case in av_build_cards_section).
EN : 87-93. FR : 94-100.

## Phase 9 — Editorial (tools/av-generate-editorial.php + seed)
5 top-level pages : /why-asterion/, /about/, /customers/, /trust/, /partners/.
Required adding empty-parent-path support to av_upsert_detail_page() so pages
can be created at the site root (no hub). EN : 107-111. FR : 112-116.

## Phase 10 — Forms (tools/av-generate-forms.php + seed)
4 conversion pages : /request-demo/, /request-te-kit/, /request-quote/,
/contact/. Custom page builder (not the shared detail-page pattern) :
hero + 2-column section (Bricks `form` element on left, promise list on
right) + optional shortcuts row (Contact), eligibility list (T&E Kit), FAQ
accordion (Demo). Form actions=email, emailTo=hello@asterionvr.com.
Field labels, select options, FAQ Q&A all in the FR dict.
EN : 122-125. FR : 126-129.

## Phase 11 — Home page (tools/av-generate-home.php + seed)
Custom-written single page (no data file). Sections : hero + 3-pillar cards
(Operational reality / Modular / Sovereign) + 4 Industries cards + 4
Solutions cards + 4-stat numbers band + Why-Asterion teaser CTA + Customers
teaser CTA + custom navy closer. Set as WP static front via
update_option(show_on_front=page, page_on_front=ID).
EN : 134. FR : 135.

## tools/_av-bricks-shared.php
- av_upsert_detail_page() now accepts empty `$parent_path` → top-level page
- av_build_cards_section() handles card_count=6 → 3-per-row layout

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 19:58:48 +02:00

293 lines
16 KiB
PHP

<?php
/**
* Plugin Name: Asterion — Generate Home page (one-shot)
* Description: /?av_generate_home=1 builds the home page (slug = "home", set as
* WP static front page). Custom-written from the PDF Strategie & Contenu D.1-D.2
* plus synthesis of Industries / Solutions / Technology / Editorial.
*/
defined('ABSPATH') || exit;
require_once __DIR__ . '/_av-bricks-shared.php';
/* -----------------------------------------------------------------
FR strings dict for Home
----------------------------------------------------------------- */
add_filter('av_fr_translation_dict', function ($dict) {
return array_merge($dict, [
// Hero
'Train like you operate.' => 'Entraînez-vous comme vous opérez.',
"PROSERVE\u{2122} is the modular XR training platform engineered for European security forces. Real recoil, autonomous AI, sovereign by design \u{2014} from solo officer to full academy."
=> "PROSERVE\u{2122} est la plateforme XR modulaire conçue pour les forces de sécurité européennes. Recul réel, IA autonome, souveraineté native \u{2014} de l'agent seul à l'académie complète.",
// 3 pillars row
'Three certainties' => 'Trois certitudes',
'A platform engineered around three commitments.' => 'Une plateforme construite autour de trois engagements.',
'Operational reality' => 'Réalité opérationnelle',
'Real recoil. Real weapons. Real consequences. AI civilians and adversaries that perceive and decide. No two drills play out the same way.'
=> "Recul réel. Vraies armes. Conséquences réelles. Civils et adversaires IA qui perçoivent et décident. Aucun exercice ne se joue deux fois pareil.",
'Modular by design' => 'Modulaire par conception',
'From 9 m\u{B2} solo to 900 m\u{B2} academy, same software, same scenarios, same instructor tools. Your investment scales with you.'
=> "De 9 m\u{B2} solo à 900 m\u{B2} académie, même logiciel, mêmes scénarios, mêmes outils instructeur. Votre investissement évolue avec vous.",
'Sovereign & secure' => 'Souverain & sécurisé',
'Designed and produced in France. Operates fully offline. No data leaves your network. GDPR-native by default.'
=> "Conçu et produit en France. Fonctionne entièrement hors ligne. Aucune donnée ne quitte votre réseau. RGPD-natif par défaut.",
// Industries teaser
'Who we serve' => 'Qui nous servons',
'Built for those who carry the weight.' => 'Conçu pour celles et ceux qui en portent le poids.',
// Solutions teaser
'The PROSERVE platform' => 'La plateforme PROSERVE',
'Pick the configuration that fits your unit.' => 'Choisissez la configuration adaptée à votre unité.',
// Numbers band
'By the numbers' => 'En chiffres',
'10 years of XR R&D focused on security forces.'
=> "10 ans de R&D XR consacrés aux forces de sécurité.",
'10 years' => '10 ans',
'XR R&D for security forces' => 'R&D XR pour les forces de sécurité',
'11 environments' => '11 environnements',
'Validated training contexts' => 'Contextes d\'entraînement validés',
'50+ scenarios' => '50+ scénarios',
'Updated four times a year' => 'Mis à jour quatre fois par an',
'GDPR-native' => 'RGPD-natif',
'Fully offline operation' => 'Fonctionnement entièrement hors ligne',
// Why Asterion teaser
'Why teams choose Asterion' => 'Pourquoi les équipes choisissent Asterion',
'A platform built around the operator. Not the other way around.'
=> "Une plateforme construite autour de l'opérateur. Pas l'inverse.",
"Founded in 2016 to solve one specific problem: security forces need more repetition than the ranges, ammunition budgets, and exercise calendars allow. Ten years later, our platform does exactly that \u{2014} at every scale, in every environment, for every role."
=> "Fondée en 2016 pour résoudre un problème précis : les forces de sécurité ont besoin de plus de répétition que ce que les stands, budgets munitions et calendriers d'exercice permettent. Dix ans plus tard, notre plateforme fait exactement cela \u{2014} à toute échelle, dans tout environnement, pour tout rôle.",
'Read the full story' => 'Lire l\'histoire complète',
// Customers teaser
'Trusted by units across Europe' => 'Choisi par des unités en Europe',
'Real deployments. Measured results.' => 'Déploiements réels. Résultats mesurés.',
"From national police academies to special tactical units, PROSERVE is in active service \u{2014} with measurable impact on training volume, tactical accuracy, and operator confidence."
=> "Des écoles nationales de police aux unités tactiques spéciales, PROSERVE est en service actif \u{2014} avec un impact mesurable sur le volume d'entraînement, la précision tactique et la confiance des opérateurs.",
'See customer stories' => 'Voir les retours clients',
// Final closer (separate from shared closer because we override copy)
'Ready to see PROSERVE in action?' => 'Prêt à voir PROSERVE en action ?',
'Schedule a tailored demo or request a Test & Evaluation Kit.'
=> 'Réservez une démo personnalisée ou demandez un kit Test & Evaluation.',
]);
});
/* -----------------------------------------------------------------
URL trigger
----------------------------------------------------------------- */
add_action('template_redirect', function () {
if (empty($_GET['av_generate_home'])) return;
if (! in_array($_SERVER['SERVER_NAME'] ?? '', ['localhost', '127.0.0.1'], true)) wp_die('localhost only');
// Ensure home page exists (slug 'home') AND is set as WP static front page
$home = get_page_by_path('home');
if (! $home) {
$home_id = wp_insert_post([
'post_type' => 'page', 'post_title' => 'Home',
'post_name' => 'home', 'post_parent' => 0,
'post_status' => 'publish', 'post_content' => '',
]);
$action = 'created';
} else {
$home_id = $home->ID;
$action = 'updated';
}
// Set as WP static front page
update_option('show_on_front', 'page');
update_option('page_on_front', $home_id);
$elements = av_build_home_elements();
$write = av_write_bricks_page_elements($home_id, $elements);
header('Content-Type: text/plain; charset=utf-8');
echo "Home page #$home_id ($action) — " . count($elements) . " elements (json={$write['json_len']}, stored={$write['stored_len']})\n";
echo "show_on_front = page, page_on_front = $home_id\n";
echo "Visit / to see the home.\n";
exit;
});
/* -----------------------------------------------------------------
HOME PAGE BUILDER
----------------------------------------------------------------- */
function av_build_home_elements() {
$els = [];
// 1. HERO — full bleed, large tagline
$els = array_merge($els, av_build_hero('home', [
'eyebrow' => '',
'tagline' => 'Train like you operate.',
'hero_lead' => "PROSERVE\u{2122} is the modular XR training platform engineered for European security forces. Real recoil, autonomous AI, sovereign by design \u{2014} from solo officer to full academy.",
'ctas' => [
['label' => 'Book a demo', 'href' => '/request-demo/', 'variant' => 'primary'],
['label' => 'Request a T&E Kit', 'href' => '/request-te-kit/', 'variant' => 'secondary'],
],
]));
// 2. THREE PILLARS — 3-card grid (count===3 → 33% each, clean row of 3)
$els = array_merge($els, av_build_cards_section('homep', 0, [
'eyebrow' => 'Three certainties',
'title' => 'A platform engineered around three commitments.',
'items' => [
['title' => 'Operational reality',
'body' => 'Real recoil. Real weapons. Real consequences. AI civilians and adversaries that perceive and decide. No two drills play out the same way.'],
['title' => 'Modular by design',
'body' => "From 9 m\u{B2} solo to 900 m\u{B2} academy, same software, same scenarios, same instructor tools. Your investment scales with you."],
['title' => 'Sovereign & secure',
'body' => 'Designed and produced in France. Operates fully offline. No data leaves your network. GDPR-native by default.'],
],
], 'var(--color-bg-subtle)'));
// 3. INDUSTRIES — 4 cards linking to /industries/*
$industries_cards = [
'eyebrow' => 'Who we serve',
'title' => 'Built for those who carry the weight.',
'items' => [
['title' => 'Police', 'body' => "National & Municipal \u{2014} Police training, when the schedule won't bend."],
['title' => 'Special Forces', 'body' => "Tactical units \u{2014} Special forces train differently. Their simulation should, too."],
['title' => 'Military', 'body' => "Armed forces \u{2014} Military VR training. Sovereign. Modular. Field-deployable."],
['title' => 'Firefighters', 'body' => "Emergency services \u{2014} Train the worst day. Safely. Repeatedly."],
],
];
$els = array_merge($els, av_build_cards_section('homei', 1, $industries_cards, 'var(--color-bg-default)'));
// Append "Learn more →" link in each industry card
$industry_slugs = ['police', 'special-forces', 'military', 'firefighters'];
foreach ($industry_slugs as $i => $slug) {
$kid = "khomeic1x{$i}";
$lid = "lnhomeic1x{$i}";
$els[] = av_text_link($lid, $kid, "Learn more \u{2192}", "/industries/$slug/");
foreach ($els as &$el) {
if (($el['id'] ?? '') === $kid) {
$el['children'][] = $lid;
}
}
unset($el);
}
// 4. SOLUTIONS — 4 cards linking to /solutions/*
$solutions_cards = [
'eyebrow' => 'The PROSERVE platform',
'title' => 'Pick the configuration that fits your unit.',
'items' => [
['title' => 'MY PROSERVE', 'body' => "Solo training \u{2014} Your first range, in a mini-case."],
['title' => 'PROSERVE FLEX', 'body' => "Team training \u{B7} 1 to 5 \u{2014} Your team, in the same scenario, on any flat surface."],
['title' => 'PROSERVE ACADEMY', 'body' => "Unit training \u{B7} 1 to 16 \u{2014} The full training centre, in your facility."],
['title' => 'PROSERVE+', 'body' => "Customization & options \u{2014} When the catalog doesn't fit your mission."],
],
];
$els = array_merge($els, av_build_cards_section('homes', 2, $solutions_cards, 'var(--color-bg-subtle)'));
$solution_slugs = ['my-proserve', 'proserve-flex', 'proserve-academy', 'customization'];
foreach ($solution_slugs as $i => $slug) {
$kid = "khomesc2x{$i}";
$lid = "lnhomesc2x{$i}";
$els[] = av_text_link($lid, $kid, "Learn more \u{2192}", "/solutions/$slug/");
foreach ($els as &$el) {
if (($el['id'] ?? '') === $kid) {
$el['children'][] = $lid;
}
}
unset($el);
}
// 5. NUMBERS BAND — 4-card grid stats
$els = array_merge($els, av_build_cards_section('homen', 3, [
'eyebrow' => 'By the numbers',
'title' => '10 years of XR R&D focused on security forces.',
'items' => [
['title' => '10 years', 'body' => 'XR R&D for security forces'],
['title' => '11 environments', 'body' => 'Validated training contexts'],
['title' => '50+ scenarios', 'body' => 'Updated four times a year'],
['title' => 'GDPR-native', 'body' => 'Fully offline operation'],
],
], 'var(--color-bg-default)'));
// 6. WHY ASTERION teaser — prose with CTA
$els = array_merge($els, av_build_cta_section('homew', 4, [
'eyebrow' => 'Why teams choose Asterion',
'title' => 'A platform built around the operator. Not the other way around.',
'body' => "Founded in 2016 to solve one specific problem: security forces need more repetition than the ranges, ammunition budgets, and exercise calendars allow. Ten years later, our platform does exactly that \u{2014} at every scale, in every environment, for every role.",
'ctas' => [
['label' => 'Read the full story', 'href' => '/why-asterion/', 'variant' => 'secondary'],
],
], 'var(--color-bg-subtle)'));
// 7. CUSTOMERS teaser
$els = array_merge($els, av_build_cta_section('homec', 5, [
'eyebrow' => 'Trusted by units across Europe',
'title' => 'Real deployments. Measured results.',
'body' => "From national police academies to special tactical units, PROSERVE is in active service \u{2014} with measurable impact on training volume, tactical accuracy, and operator confidence.",
'ctas' => [
['label' => 'See customer stories', 'href' => '/customers/', 'variant' => 'secondary'],
],
], 'var(--color-bg-default)'));
// 8. CLOSER CTA — full navy with custom copy
$els = array_merge($els, av_build_home_closer_cta());
return $els;
}
function av_build_home_closer_cta() {
$sid = "schmhc";
$oct = "ochmhc";
$nrr = "nrhmhc";
$eyb = "ebhmhc";
$hId = "h2hmhc";
$led = "ldhmhc";
$row = "rwhmhc";
$b1 = "b1hmhc";
$b2 = "b2hmhc";
return [
[
'id' => $sid, 'name' => 'section', 'parent' => 0, 'children' => [$oct],
'settings' => array_merge(av_section_padding_responsive(), [
'_background' => ['color' => av_color('var(--color-brand-navy)')],
]),
],
[
'id' => $oct, 'name' => 'container', 'parent' => $sid, 'children' => [$nrr],
'settings' => [
'_direction' => 'column',
'_widthMax' => '1280px',
'_width' => '100%',
'_padding' => av_sp('0', '1.5rem', '0', '1.5rem'),
'_padding:mobile_landscape' => av_sp('0', '1rem', '0', '1rem'),
'_alignItems' => 'flex-start',
],
],
[
'id' => $nrr, 'name' => 'container', 'parent' => $oct, 'children' => [$eyb, $hId, $led, $row],
'settings' => [
'_direction' => 'column',
'_widthMax' => '800px',
'_widthMin' => '0',
'_width' => '100%',
'_margin' => av_sp('0', 'auto', '0', '0'),
'_padding' => av_sp('0', '0', '0', '0'),
'_rowGap' => '1.25rem',
],
],
av_eyebrow($eyb, $nrr, 'Ready to see PROSERVE in action?'),
av_heading($hId, $nrr, 'h2', 'Schedule a tailored demo or request a Test & Evaluation Kit.', 'var(--color-text-on-dark)'),
av_text($led, $nrr, "Book 30 minutes with our team. We'll bring the kit. You bring the doctrine.", 'var(--color-text-on-dark)', '1.125rem', '1.55'),
[
'id' => $row, 'name' => 'container', 'parent' => $nrr, 'children' => [$b1, $b2],
'settings' => [
'_direction' => 'row',
'_columnGap' => '1rem',
'_rowGap' => '1rem',
'_flexWrap' => 'wrap',
'_widthMin' => '0',
'_width' => '100%',
'_padding' => av_sp('0.5rem', '0', '0', '0'),
],
],
av_button($b1, $row, 'Book a Demo', '/request-demo/', 'gold'),
av_button($b2, $row, 'Request a T&E Kit', '/request-te-kit/', 'outline-on-dark'),
];
}