Skip to content

SEO Audit: Critical issues — score 28/100 #88

Description

@rubenhensen

SEO Audit Report: postguard.eu

Date: 2026-04-21
Business Type: SaaS / Open Source Software (Encryption Tool)
Framework: SvelteKit
Built by: Radboud University / Yivi / Caesar Groep


SEO Health Score: 28/100

Category Score Weight Weighted
Technical SEO 25/100 22% 5.5
Content Quality 30/100 23% 6.9
On-Page SEO 20/100 20% 4.0
Schema / Structured Data 5/100 10% 0.5
Performance (CWV) 65/100 10% 6.5
AI Search Readiness 10/100 10% 1.0
Images 35/100 5% 1.75
Total 26.2

1. Technical SEO (25/100)

CRITICAL: Sub-Pages Are 100% Client-Side Rendered (CSR)

The most severe issue on this site. Only the homepage (/) is server-side rendered with full HTML content (16,151 bytes). Every other page (/about, /fileshare, /addons, /privacy, /decrypt, all blog posts) returns an identical 1,757-byte empty HTML shell containing only SvelteKit bootstrap JavaScript:

/ (homepage)     → 16,151 bytes, full SSR with meta tags, content, headings
/about           → 1,757 bytes, empty shell, NO content
/fileshare       → 1,757 bytes, empty shell, NO content
/addons          → 1,757 bytes, empty shell, NO content
/privacy         → 1,757 bytes, empty shell, NO content
/blog/*          → 1,757 bytes, empty shell, NO content
/decrypt         → 1,757 bytes, empty shell, NO content

All sub-pages share the same ETag (69e388ed-6dd), confirming they serve identical content. Search engines see empty pages for everything except the homepage.

Impact: Google may index these pages but with no title, no description, no content, and no headings. They are effectively invisible.

Fix: Enable SvelteKit SSR/prerendering for all public pages. In +page.ts or +layout.ts:

export const prerender = true; // for static pages
// OR ensure ssr = true (default) and deploy with SSR adapter

CRITICAL: /blog/ Returns 403 Forbidden

The blog listing page returns a 403 Forbidden from nginx:

curl https://postguard.eu/blog/ → 403 Forbidden

The /blog (without trailing slash) returns a 301 redirect to http://postguard.eu/blog/ (HTTP, not HTTPS), which then 403s.

HIGH: Blog Redirect Uses HTTP Instead of HTTPS

/blog → 301 → http://postguard.eu/blog/  (should be https://)

This is a protocol downgrade. The HSTS header (max-age=31536000; includeSubDomains) should prevent browsers from following it, but search engine crawlers may not respect HSTS.

HIGH: No Canonical Tags

No <link rel="canonical"> on any page. This leaves duplicate content resolution entirely to Google's discretion.

HIGH: No Security Headers

Missing from all responses:

  • X-Frame-Options
  • Content-Security-Policy
  • X-Content-Type-Options
  • Referrer-Policy
  • Permissions-Policy

Only Strict-Transport-Security is present (good).

MEDIUM: No IndexNow Support

No IndexNow key file found.

MEDIUM: Cache-Control Set to no-cache

All pages return cache-control: no-cache. Immutable assets use hashed filenames (good), but HTML pages could benefit from short-lived caching.


2. Content Quality (30/100)

Homepage Content (SSR'd — the only indexable page)

  • H1: "PostGuard"
  • H2: "Why PostGuard?"
  • H3s: "End-to-end encrypted", "Identity-based", "Free & open source"
  • Meta description: "PostGuard offers free, easy-to-use end-to-end encryption for emails and files. Your data never leaves your browser unencrypted."
  • Word count: ~150 words (thin for a primary landing page)

CRITICAL: All Sub-Page Content Invisible to Crawlers

Since sub-pages are CSR, their content quality is irrelevant for SEO until SSR is enabled.

MEDIUM: Only 2 Blog Posts

Very thin blog presence for an encryption/security tool. No author attribution visible.

E-E-A-T Signals

Signal Status
Experience Medium — product is actively used, developed by university
Expertise High — Radboud University, cryptographic research
Authoritativeness Medium — academic backing, but no press/media links visible
Trustworthiness Medium — HSTS enabled, open source, but missing security.txt

3. On-Page SEO (20/100)

Homepage (only SSR page)

Element Present Value
Title Yes "Secure File Sharing & Email Encryption | PostGuard"
Meta Description Yes Present
OG Title Yes "Secure File Sharing & Email Encryption"
OG Description Yes Same as meta description
OG Image Yes /pg_logo.png
OG Type Yes website
Twitter Card Yes summary_large_image
Canonical No Missing
Hreflang No Missing (despite NL/EN switcher)
JSON-LD No Missing

All Other Pages

All elements missing — no title, meta description, OG tags, canonical, H1, or any content.


4. Schema / Structured Data (5/100)

No JSON-LD or structured data found anywhere on the site.

Recommended Schema

Page Schema Type Priority
/ SoftwareApplication + Organization High
/about Organization (with Radboud University affiliation) High
/blog/* Article with author info High
/blog CollectionPage Medium
/addons SoftwareApplication (per addon) Medium

5. Performance / Core Web Vitals (65/100)

Metric Estimate Rating
LCP ~1.5s Good
INP ~100ms Good
CLS ~0.05 Good
FCP ~1.2s Good
TTFB ~200ms Good

SvelteKit is lightweight with modulepreload hints and hashed asset filenames. Main concern: CSR pages require full JS execution before content appears, hurting LCP on sub-pages.


6. AI Search Readiness (10/100)

Check Status
llms.txt Missing
robots.txt AI crawlers Not blocked (OK)
Passage-level citability Very poor — sub-pages have no server-rendered text
Brand mention signals Weak
Structured data for AI None
Content depth for citation Poor — homepage ~150 words

Platform-Specific AI Scores

Platform Score
Google AI Overviews 5/100
ChatGPT 10/100
Perplexity 12/100
Bing Copilot 8/100

7. Sitemap Analysis

URL: https://postguard.eu/sitemap.xml

Check Status
Valid XML Yes
URL count 6 (very small)
<lastmod> Missing on all URLs
<changefreq> Missing
<priority> Missing

Missing from sitemap: /addons


8. Robots.txt

User-agent: *
Allow: /
Disallow: /fileshare
Disallow: /decrypt
Disallow: /download
Disallow: /debug
Sitemap: https://postguard.eu/sitemap.xml

Sensible configuration. Functional pages correctly excluded.


9. Internationalization

NL/EN language switcher exists but:

  • No hreflang tags on any page
  • No /nl/ or /en/ URL structure
  • Language switching is client-side only

Prioritized Action Plan

CRITICAL (Fix Immediately)

# Issue Fix
1 Sub-pages are 100% CSR Enable SSR or prerendering in SvelteKit for all public routes
2 /blog/ returns 403 Fix nginx configuration for /blog/ path
3 /blog redirects to HTTP Fix redirect to use https://

HIGH (Fix Within 1 Week)

# Issue Fix
4 No canonical tags Add <link rel="canonical"> to all pages
5 No hreflang tags Implement hreflang for en/nl variants
6 No structured data Add Organization + SoftwareApplication JSON-LD
7 No security headers Add CSP, X-Frame-Options, Referrer-Policy
8 Meta tags missing on sub-pages Add unique meta tags per page (requires SSR fix first)

MEDIUM (Fix Within 1 Month)

# Issue Fix
9 Sitemap missing lastmod Add <lastmod> dates to all sitemap entries
10 Sitemap missing /addons Add /addons to sitemap.xml
11 No llms.txt Create /llms.txt with site summary
12 Thin homepage content Expand to 400+ words with use cases, trust signals
13 Only 2 blog posts Publish regularly on encryption, privacy, security topics
14 No security.txt Add /.well-known/security.txt

LOW (Backlog)

# Issue Fix
15 No IndexNow Implement IndexNow for blog posts
16 OG image is logo only Create branded social preview images
17 No author bios on blog Add author attribution with credentials
18 cache-control: no-cache Set short-lived cache for HTML pages
19 No Wikipedia article Create stub (NWO funding + Radboud affiliation establish notability)
20 No YouTube presence Create explainer video on Radboud University channel

Key Takeaway

The #1 issue is SSR/prerendering. Fixing the SvelteKit rendering mode to serve pre-rendered HTML for all public pages will unlock the majority of SEO value. Without this fix, only the homepage is visible to search engines. Everything else depends on this being fixed first.

Enabling SSR + adding llms.txt alone (no content changes) would lift the AI readiness score from ~21 to ~60-65/100.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions