Remove placeholders and finalize contact details for launch
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled

- Replace all `[PLACEHOLDER]` entries across legal pages with actual values
- Update privacy policy with ICO registration status and service provider details (Ionos, Vonage, OneSignal)
- Finalize contact email as `hello@fuel-alert.co.uk` throughout legal pages and footer
- Update legal layout to use full landing nav with auth/guest actions
- Add Umami analytics script to main app layout
- Remove "Fleet" nav link from landing navigation
- Add feature test to enforce no placeholders and correct contact domain remain in legal pages
This commit is contained in:
Ovidiu U
2026-06-10 10:07:02 +01:00
parent ecd45588e9
commit 7a8bd5c86a
11 changed files with 522 additions and 460 deletions

860
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,10 +11,11 @@
"@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue": "^6.0.5",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"axios": "^1.15.0", "axios": "^1.15.0",
"concurrently": "^9.0.1", "concurrently": "^10.0.3",
"iconify-icon": "^3.0.2", "iconify-icon": "^3.0.2",
"laravel-vite-plugin": "^3.0.0", "laravel-vite-plugin": "^3.0.0",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"shell-quote": "^1.8.4",
"tailwindcss": "^4.0.7", "tailwindcss": "^4.0.7",
"vite": "^8.0.0", "vite": "^8.0.0",
"vue": "^3.5.32", "vue": "^3.5.32",

View File

@@ -12,7 +12,6 @@
<a class="hover:text-accent transition-colors" href="#how-it-works">How it works</a> <a class="hover:text-accent transition-colors" href="#how-it-works">How it works</a>
<a class="hover:text-accent transition-colors" href="#features">Why it works</a> <a class="hover:text-accent transition-colors" href="#features">Why it works</a>
<a class="hover:text-accent transition-colors" href="#pricing">Pricing</a> <a class="hover:text-accent transition-colors" href="#pricing">Pricing</a>
<a class="hover:text-accent transition-colors" href="#fleet">Fleet</a>
</div> </div>
<div class="flex items-center gap-3 md:gap-5"> <div class="flex items-center gap-3 md:gap-5">

View File

@@ -372,6 +372,9 @@
<p class="text-sm text-zinc-500 leading-relaxed"> <p class="text-sm text-zinc-500 leading-relaxed">
Helping UK drivers save money at the pump. Real-time data, smarter choices. Helping UK drivers save money at the pump. Real-time data, smarter choices.
</p> </p>
<p class="text-sm text-zinc-500">
Questions? <a class="text-accent hover:underline" href="mailto:hello@fuel-alert.co.uk">hello@fuel-alert.co.uk</a>
</p>
<div class="flex gap-4"> <div class="flex gap-4">
<iconify-icon class="text-2xl text-zinc-500 hover:text-accent cursor-pointer transition-colors" icon="mdi:twitter"></iconify-icon> <iconify-icon class="text-2xl text-zinc-500 hover:text-accent cursor-pointer transition-colors" icon="mdi:twitter"></iconify-icon>
<iconify-icon class="text-2xl text-zinc-500 hover:text-accent cursor-pointer transition-colors" icon="mdi:facebook"></iconify-icon> <iconify-icon class="text-2xl text-zinc-500 hover:text-accent cursor-pointer transition-colors" icon="mdi:facebook"></iconify-icon>

View File

@@ -6,6 +6,12 @@
<meta name="csrf-token" content="{{ csrf_token() }}"> <meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ __('Welcome') }} - {{ config('app.name', 'Laravel') }}</title> <title>{{ __('Welcome') }} - {{ config('app.name', 'Laravel') }}</title>
<meta name="description" content="Live UK fuel prices across 11,000+ stations. See whether to fill up today or wait, based on local trends."> <meta name="description" content="Live UK fuel prices across 11,000+ stations. See whether to fill up today or wait, based on local trends.">
<script
defer src="https://umami.local.uovidiu.com/script.js"
data-website-id="26b2df00-e3fc-4c8c-97d1-75d99daa4545"
data-do-not-track="true"
data-domains="fuel-alert.co.uk,www.fuel-alert.co.uk"
></script>
<script> <script>
window['FUEL_TYPES'] = @json( window['FUEL_TYPES'] = @json(
collect(App\Enums\FuelType::cases()) collect(App\Enums\FuelType::cases())

View File

@@ -1,25 +1,60 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head> <head>
@include('partials.head', ['title' => $title ?? null]) <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ ($title ?? $heading ?? 'Legal').' - '.config('app.name') }}</title>
@isset($metaDescription) @isset($metaDescription)
<meta name="description" content="{{ $metaDescription }}"> <meta name="description" content="{{ $metaDescription }}">
@endisset @endisset
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=inter:400,500,600&family=manrope:600,700,800,900&display=swap" rel="stylesheet" />
{{-- CSS only no @fluxAppearance: it applies Flux's `.dark` class from the OS
preference, which overrides --color-accent to white. Legal pages render no
Flux components, so they stay light like the rest of the public site. --}}
@vite(['resources/css/app.css'])
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js" defer></script>
</head> </head>
<body class="min-h-screen bg-[#f5ede5] text-zinc-900 antialiased"> <body class="min-h-screen bg-[#f5ede5] text-zinc-900 antialiased">
<header class="border-b border-zinc-300 bg-white/70 backdrop-blur"> <nav class="fixed top-0 w-full z-50 bg-zinc-50/90 backdrop-blur-sm border-b border-zinc-300 px-6 py-4 md:px-12">
<div class="mx-auto flex max-w-3xl items-center justify-between px-6 py-4"> <div class="max-w-7xl mx-auto flex items-center justify-between gap-6">
<a href="/" class="flex items-center gap-2"> <a class="flex items-center gap-3 shrink-0" href="/">
<span class="flex h-8 w-8 items-center justify-center rounded bg-accent text-white"> <div class="w-9 h-9 md:w-10 md:h-10 rounded-lg bg-accent flex items-center justify-center shadow-md">
<iconify-icon icon="lucide:fuel"></iconify-icon> <iconify-icon class="text-white text-xl" icon="lucide:fuel"></iconify-icon>
</span> </div>
<span class="font-display text-xl font-black tracking-tighter text-accent">FuelAlert</span> <span class="text-xl md:text-2xl font-black font-display tracking-tighter text-accent">FuelAlert</span>
</a> </a>
<a href="/" class="text-sm text-zinc-600 hover:text-accent">&larr; Back to site</a>
</div>
</header>
<main class="mx-auto max-w-3xl px-6 py-12"> <div class="hidden lg:flex items-center gap-8 font-mono text-[11px] uppercase tracking-widest text-zinc-600">
<a class="hover:text-accent transition-colors" href="/#how-it-works">How it works</a>
<a class="hover:text-accent transition-colors" href="/#features">Why it works</a>
<a class="hover:text-accent transition-colors" href="/#pricing">Pricing</a>
</div>
<div class="flex items-center gap-3 md:gap-5">
@auth
<a class="bg-accent text-white px-5 py-2 rounded-full text-sm font-bold shadow-md hover:bg-primary-dark transition-all" href="/dashboard">
Dashboard
</a>
@else
<a class="text-sm font-semibold text-zinc-600 hover:text-zinc-900 transition-colors" href="/login">Login</a>
<a class="hidden sm:inline-flex bg-accent text-white px-5 py-2 rounded-full text-sm font-bold shadow-md hover:bg-primary-dark transition-all" href="/register">
Get started
</a>
@endauth
</div>
</div>
</nav>
<main class="mx-auto max-w-3xl px-6 pt-28 pb-12 md:pt-32">
<article class="space-y-6 leading-relaxed text-zinc-800"> <article class="space-y-6 leading-relaxed text-zinc-800">
<header class="space-y-3 border-b border-zinc-300 pb-6"> <header class="space-y-3 border-b border-zinc-300 pb-6">
<h1 class="font-display text-3xl font-black tracking-tight text-zinc-900 md:text-4xl"> <h1 class="font-display text-3xl font-black tracking-tight text-zinc-900 md:text-4xl">
@@ -47,7 +82,5 @@
</p> </p>
</div> </div>
</footer> </footer>
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js" defer></script>
</body> </body>
</html> </html>

View File

@@ -70,9 +70,8 @@
</div> </div>
<p class="text-sm text-zinc-600"> <p class="text-sm text-zinc-600">
<strong>[PLACEHOLDER:</strong> Update the table above if any cookie names change. If a If we add a marketing or advertising tool in future, a Marketing row will be added to the
marketing tool is added in future, a Marketing row will be added here and consent will table above and your consent will be requested before it loads.
be requested before it loads.<strong>]</strong>
</p> </p>
</section> </section>
@@ -106,7 +105,7 @@
<h2 class="font-display text-2xl font-bold text-zinc-900">5. Contact</h2> <h2 class="font-display text-2xl font-bold text-zinc-900">5. Contact</h2>
<p> <p>
Questions about cookies? Email Questions about cookies? Email
<a href="mailto:[PLACEHOLDER: hello@fuelalert.co.uk]" class="text-accent underline">[PLACEHOLDER: hello@fuelalert.co.uk]</a>. <a href="mailto:hello@fuel-alert.co.uk" class="text-accent underline">hello@fuel-alert.co.uk</a>.
</p> </p>
</section> </section>
</x-layouts.legal> </x-layouts.legal>

View File

@@ -13,12 +13,12 @@
is the <strong>data controller</strong> for personal data collected through this service. is the <strong>data controller</strong> for personal data collected through this service.
</p> </p>
<p> <p>
We are registered with the UK Information Commissioner's Office (ICO). As the data controller, Ovidiu Ungureanu is registering with the UK Information
Our registration number is <strong>[PLACEHOLDER: ICO registration number ZAxxxxxxx]</strong>. Commissioner's Office (ICO). Our registration number will be published here once issued.
</p> </p>
<p> <p>
If you have any questions about this policy or how we handle your personal data, contact us at If you have any questions about this policy or how we handle your personal data, contact us at
<a href="mailto:[PLACEHOLDER: hello@fuelalert.co.uk]" class="text-accent underline">[PLACEHOLDER: hello@fuelalert.co.uk]</a>. <a href="mailto:hello@fuel-alert.co.uk" class="text-accent underline">hello@fuel-alert.co.uk</a>.
</p> </p>
</section> </section>
@@ -92,15 +92,15 @@
and subscription events flow to Stripe. See and subscription events flow to Stripe. See
<a class="text-accent underline" href="https://stripe.com/privacy" target="_blank" rel="noopener">Stripe's privacy policy</a>. <a class="text-accent underline" href="https://stripe.com/privacy" target="_blank" rel="noopener">Stripe's privacy policy</a>.
</li> </li>
<li><strong>[PLACEHOLDER: Hosting provider]</strong> &mdash; infrastructure where our application and database run.</li> <li><strong>Ionos</strong> &mdash; infrastructure where our application and database run, and the mail servers (SMTP) that send account, billing and alert emails on our behalf.</li>
<li><strong>[PLACEHOLDER: Transactional email provider]</strong> &mdash; sends account, billing and alert emails on our behalf.</li>
<li> <li>
<strong>Umami Analytics</strong> &mdash; we run our own self-hosted Umami instance to <strong>Umami Analytics</strong> &mdash; we run our own self-hosted Umami instance to
collect aggregated, cookieless usage metrics (pages viewed, referrer, country, device collect aggregated, cookieless usage metrics (pages viewed, referrer, country, device
type). No personal data is collected and no analytics data is shared with third type). No personal data is collected and no analytics data is shared with third
parties. parties.
</li> </li>
<li><strong>[PLACEHOLDER: Notification providers]</strong> &mdash; if you opt in to push, WhatsApp, or SMS alerts, the chosen provider will be named here.</li> <li><strong>Vonage</strong> &mdash; delivers WhatsApp and SMS alerts if you opt in to those channels. Your phone number is shared only to send messages you have requested.</li>
<li><strong>OneSignal</strong> &mdash; delivers web push notifications if you opt in to push alerts.</li>
</ul> </ul>
</section> </section>
@@ -139,7 +139,7 @@
</ul> </ul>
<p> <p>
To exercise any of these rights, email To exercise any of these rights, email
<a href="mailto:[PLACEHOLDER: hello@fuelalert.co.uk]" class="text-accent underline">[PLACEHOLDER: hello@fuelalert.co.uk]</a>. <a href="mailto:hello@fuel-alert.co.uk" class="text-accent underline">hello@fuel-alert.co.uk</a>.
We will respond within one month. We will respond within one month.
</p> </p>
</section> </section>
@@ -199,7 +199,7 @@
<h2 class="font-display text-2xl font-bold text-zinc-900">14. Contact</h2> <h2 class="font-display text-2xl font-bold text-zinc-900">14. Contact</h2>
<p> <p>
For any privacy queries, email For any privacy queries, email
<a href="mailto:[PLACEHOLDER: hello@fuelalert.co.uk]" class="text-accent underline">[PLACEHOLDER: hello@fuelalert.co.uk]</a>. <a href="mailto:hello@fuel-alert.co.uk" class="text-accent underline">hello@fuel-alert.co.uk</a>.
</p> </p>
</section> </section>
</x-layouts.legal> </x-layouts.legal>

View File

@@ -52,7 +52,7 @@
<p>You can cancel a subscription in either of these ways:</p> <p>You can cancel a subscription in either of these ways:</p>
<ul class="list-disc space-y-1 pl-6"> <ul class="list-disc space-y-1 pl-6">
<li>From your account: <strong>Settings &rarr; Subscription &rarr; Cancel</strong>.</li> <li>From your account: <strong>Settings &rarr; Subscription &rarr; Cancel</strong>.</li>
<li>By emailing <a href="mailto:[PLACEHOLDER: hello@fuelalert.co.uk]" class="text-accent underline">[PLACEHOLDER: hello@fuelalert.co.uk]</a> from the address on your account.</li> <li>By emailing <a href="mailto:hello@fuel-alert.co.uk" class="text-accent underline">hello@fuel-alert.co.uk</a> from the address on your account.</li>
</ul> </ul>
<p> <p>
Unless you are exercising the 14-day right above, cancellation takes effect at the end Unless you are exercising the 14-day right above, cancellation takes effect at the end
@@ -104,7 +104,7 @@
<h2 class="font-display text-2xl font-bold text-zinc-900">8. Contact</h2> <h2 class="font-display text-2xl font-bold text-zinc-900">8. Contact</h2>
<p> <p>
For refund or cancellation queries, email For refund or cancellation queries, email
<a href="mailto:[PLACEHOLDER: hello@fuelalert.co.uk]" class="text-accent underline">[PLACEHOLDER: hello@fuelalert.co.uk]</a>. <a href="mailto:hello@fuel-alert.co.uk" class="text-accent underline">hello@fuel-alert.co.uk</a>.
</p> </p>
</section> </section>
</x-layouts.legal> </x-layouts.legal>

View File

@@ -69,8 +69,9 @@
You may cancel before the change takes effect. You may cancel before the change takes effect.
</p> </p>
<p> <p>
<strong>VAT.</strong> Prices include UK VAT where applicable. <strong>VAT.</strong> FuelAlert is currently below the UK VAT registration threshold and is
<strong>[PLACEHOLDER: verify before launch &mdash; FuelAlert is currently below the UK VAT registration threshold and therefore does not charge VAT.]</strong> not VAT-registered, so no VAT is charged on your subscription. The price shown is the total
amount you pay.
</p> </p>
</section> </section>
@@ -215,7 +216,7 @@
<h2 class="font-display text-2xl font-bold text-zinc-900">15. Contact</h2> <h2 class="font-display text-2xl font-bold text-zinc-900">15. Contact</h2>
<p> <p>
For questions about these terms, email For questions about these terms, email
<a href="mailto:[PLACEHOLDER: hello@fuelalert.co.uk]" class="text-accent underline">[PLACEHOLDER: hello@fuelalert.co.uk]</a>. <a href="mailto:hello@fuel-alert.co.uk" class="text-accent underline">hello@fuel-alert.co.uk</a>.
</p> </p>
</section> </section>
</x-layouts.legal> </x-layouts.legal>

View File

@@ -52,3 +52,17 @@ it('cross-links between legal pages', function (): void {
$this->get('/legal/privacy')->assertSee(route('legal.cookies'), false); $this->get('/legal/privacy')->assertSee(route('legal.cookies'), false);
$this->get('/legal/terms')->assertSee(route('legal.refund'), false); $this->get('/legal/terms')->assertSee(route('legal.refund'), false);
}); });
it('is launch-ready: no placeholders and the correct contact domain', function (string $path): void {
$response = $this->get($path);
$response->assertStatus(200);
$response->assertDontSee('[PLACEHOLDER', false);
$response->assertDontSee('hello@fuelalert.co.uk', false);
$response->assertSee('hello@fuel-alert.co.uk', false);
})->with([
'/legal/privacy',
'/legal/terms',
'/legal/refund',
'/legal/cookies',
]);