314 lines
14 KiB
Cheetah
314 lines
14 KiB
Cheetah
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{{.Title}}</title>
|
|
{{if .Desc}}<meta name="description" content="{{.Desc}}">{{end}}
|
|
<meta property="og:site_name" content="clavitor">
|
|
<meta property="og:title" content="{{.Title}}">
|
|
{{if .Desc}}<meta property="og:description" content="{{.Desc}}">{{end}}
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:url" content="https://clavitor.ai{{if ne .Page "index"}}/{{.Page}}{{end}}">
|
|
<meta name="twitter:card" content="summary">
|
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
|
<link rel="preload" href="/fonts/ibm-plex-sans-latin.woff2" as="font" type="font/woff2" crossorigin>
|
|
<link rel="preload" href="/fonts/jetbrains-mono-latin.woff2" as="font" type="font/woff2" crossorigin>
|
|
<link rel="stylesheet" href="/clavitor.css">
|
|
{{if eq .Page "install"}}{{template "install-head"}}{{end}}
|
|
{{if eq .Page "styleguide"}}{{template "styleguide-head"}}{{end}}
|
|
{{if eq .Page "index"}}
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "WebSite",
|
|
"name": "clavitor",
|
|
"url": "https://clavitor.ai",
|
|
"description": "AI-native password manager with field-level encryption. Your AI gets what it needs. Your secrets stay yours.",
|
|
"potentialAction": {
|
|
"@type": "SearchAction",
|
|
"target": "https://clavitor.ai?q={search_term_string}",
|
|
"query-input": "required name=search_term_string"
|
|
}
|
|
}
|
|
</script>
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "Organization",
|
|
"name": "clavitor",
|
|
"url": "https://clavitor.ai",
|
|
"logo": "https://clavitor.ai/favicon.svg",
|
|
"sameAs": []
|
|
}
|
|
</script>
|
|
{{end}}
|
|
{{if or (eq .Page "hosted") (eq .Page "pricing")}}
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "SoftwareApplication",
|
|
"name": "clavitor",
|
|
"applicationCategory": "SecurityApplication",
|
|
"operatingSystem": "Any",
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "12",
|
|
"priceCurrency": "USD",
|
|
"priceValidUntil": "2026-12-31",
|
|
"description": "$12/year hosted (launch price)"
|
|
},
|
|
"aggregateRating": {
|
|
"@type": "AggregateRating",
|
|
"ratingValue": "4.8",
|
|
"ratingCount": "1"
|
|
},
|
|
"featureList": "Field-level encryption, WebAuthn PRF, Scoped agent tokens, AI-powered 2FA, LLM field mapping"
|
|
}
|
|
</script>
|
|
{{end}}
|
|
</head>
|
|
<body>
|
|
<nav class="nav">
|
|
<div class="container nav-inner">
|
|
<a href="/" class="nav-logo"><span class="logo-lockup logo-lockup-nav"><span class="logo-lockup-square"></span><span class="logo-lockup-text"><span class="logo-lockup-wordmark">CLAVITOR</span><span class="logo-lockup-tagline">Black-box credential issuance</span></span></span></a>
|
|
<button class="nav-hamburger" onclick="document.querySelector('.nav-links').classList.toggle('open')"><span></span><span></span><span></span></button>
|
|
<div class="nav-links">
|
|
<a href="/hosted" class="nav-link{{if eq .ActiveNav "hosted"}} active{{end}}">Hosted</a>
|
|
<div class="nav-dropdown">
|
|
<span class="nav-link nav-dropdown-trigger{{if or (eq .ActiveNav "install") (eq .ActiveNav "integrations") (eq .ActiveNav "upgrade") (eq .ActiveNav "developers")}} active{{end}}">Product</span>
|
|
<div class="nav-dropdown-menu">
|
|
<a href="/upgrade" class="nav-dropdown-item">Upgrade</a>
|
|
<a href="/developers" class="nav-dropdown-item">Developers</a>
|
|
<a href="/install" class="nav-dropdown-item">Self-host</a>
|
|
<a href="/integrations/claude-code" class="nav-dropdown-item">Claude Code</a>
|
|
<a href="/integrations/codex" class="nav-dropdown-item">Codex</a>
|
|
<a href="/integrations/openclaw" class="nav-dropdown-item">OpenClaw</a>
|
|
</div>
|
|
</div>
|
|
<div class="nav-dropdown">
|
|
<span class="nav-link nav-dropdown-trigger{{if or (eq .ActiveNav "status") (eq .ActiveNav "glass")}} active{{end}}">Network</span>
|
|
<div class="nav-dropdown-menu">
|
|
<a href="/status" class="nav-dropdown-item">Status</a>
|
|
<a href="/glass" class="nav-dropdown-item">Looking Glass</a>
|
|
</div>
|
|
</div>
|
|
<div class="nav-dropdown">
|
|
<span class="nav-link nav-dropdown-trigger{{if or (eq .ActiveNav "for-consumer") (eq .ActiveNav "for-smb") (eq .ActiveNav "for-mme") (eq .ActiveNav "for-enterprise") (eq .ActiveNav "for-msp")}} active{{end}}">Solutions</span>
|
|
<div class="nav-dropdown-menu">
|
|
<a href="/for/consumer" class="nav-dropdown-item">Consumer</a>
|
|
<a href="/for/smb" class="nav-dropdown-item">SMB</a>
|
|
<a href="/for/enterprise" class="nav-dropdown-item">Enterprise</a>
|
|
<a href="/for/msp" class="nav-dropdown-item">MSP</a>
|
|
</div>
|
|
</div>
|
|
<a href="/pricing" class="nav-link{{if eq .ActiveNav "pricing"}} active{{end}}">Pricing</a>
|
|
<div class="nav-dropdown nav-dropdown--language">
|
|
<span class="nav-link nav-dropdown-trigger" id="languageTrigger">🇺🇸 EN</span>
|
|
<div class="nav-dropdown-menu nav-dropdown-menu--right">
|
|
<a href="/" class="nav-dropdown-item active" data-lang="en">🇺🇸 English</a>
|
|
<a href="/de" class="nav-dropdown-item" data-lang="de">🇩🇪 Deutsch</a>
|
|
<a href="/fr" class="nav-dropdown-item" data-lang="fr">🇫🇷 Français</a>
|
|
</div>
|
|
</div>
|
|
<div class="nav-dropdown nav-dropdown--currency">
|
|
<span class="nav-link nav-dropdown-trigger" id="currencyTrigger">$ USD</span>
|
|
<div class="nav-dropdown-menu nav-dropdown-menu--right" id="currencyMenu">
|
|
<!-- Currency options loaded dynamically from /api/currencies -->
|
|
<a href="#" class="nav-dropdown-item active" data-currency="USD">$ USD</a>
|
|
<a href="#" class="nav-dropdown-item" data-currency="EUR">€ EUR</a>
|
|
</div>
|
|
</div>
|
|
<a href="#" class="nav-link btn btn-ghost">Sign in</a>
|
|
<a href="/hosted" class="btn btn-primary">Get hosted — $12/yr</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
{{if eq .Page "index"}}{{template "index" .}}
|
|
{{else if eq .Page "hosted"}}{{template "hosted" .}}
|
|
{{else if eq .Page "install"}}{{template "install" .}}
|
|
{{else if eq .Page "pricing"}}{{template "pricing" .}}
|
|
{{else if eq .Page "privacy"}}{{template "privacy" .}}
|
|
{{else if eq .Page "terms"}}{{template "terms" .}}
|
|
{{else if eq .Page "cookies"}}{{template "cookies" .}}
|
|
{{else if eq .Page "sources"}}{{template "sources" .}}
|
|
{{else if eq .Page "upgrade"}}{{template "upgrade" .}}
|
|
{{else if eq .Page "developers"}}{{template "developers" .}}
|
|
{{else if eq .Page "styleguide"}}{{template "styleguide" .}}
|
|
{{else if eq .Page "glass"}}{{template "glass" .}}
|
|
{{else if eq .Page "noc"}}{{template "noc" .}}
|
|
{{else if eq .Page "status"}}{{template "status" .}}
|
|
{{else if eq .Page "signup"}}{{template "signup" .}}
|
|
{{else if eq .Page "claude-code"}}{{template "claude-code" .}}
|
|
{{else if eq .Page "codex"}}{{template "codex" .}}
|
|
{{else if eq .Page "openclaw"}}{{template "openclaw" .}}
|
|
{{else if eq .Page "openclaw-cn"}}{{template "openclaw-cn" .}}
|
|
{{else if eq .Page "install-new"}}{{template "install-new" .}}
|
|
{{else if eq .Page "for-consumer"}}{{template "for-consumer" .}}
|
|
{{else if eq .Page "for-smb"}}{{template "for-smb" .}}
|
|
{{else if eq .Page "for-mme"}}{{template "for-mme" .}}
|
|
{{else if eq .Page "for-enterprise"}}{{template "for-enterprise" .}}
|
|
{{else if eq .Page "for-msp"}}{{template "for-msp" .}}
|
|
{{else if eq .Page "onboarding-profile"}}{{template "onboarding-profile" .}}
|
|
{{else if eq .Page "onboarding-plan"}}{{template "onboarding-plan" .}}
|
|
{{else if eq .Page "onboarding-done"}}{{template "onboarding-done" .}}
|
|
{{else if eq .Page "onboarding-login"}}{{template "onboarding-login" .}}
|
|
{{else if eq .Page "onboarding-details"}}{{template "onboarding-details" .}}
|
|
{{else if eq .Page "onboarding-product"}}{{template "onboarding-product" .}}
|
|
{{else if eq .Page "onboarding-terms"}}{{template "onboarding-terms" .}}
|
|
{{else if eq .Page "onboarding-checkout"}}{{template "onboarding-checkout" .}}
|
|
{{end}}
|
|
{{if ne .Page "styleguide"}}{{template "footer"}}{{end}}
|
|
{{if eq .Page "hosted" "glass"}}{{template "ping-script"}}{{end}}
|
|
{{if eq .Page "index"}}{{template "index-script"}}
|
|
{{else if eq .Page "hosted"}}{{template "hosted-script" .}}
|
|
{{else if eq .Page "glass"}}{{template "glass-script"}}
|
|
{{else if eq .Page "noc"}}{{template "noc-script"}}
|
|
{{else if eq .Page "status"}}{{template "status-script"}}
|
|
{{else if eq .Page "signup"}}{{template "signup-script"}}
|
|
{{else if eq .Page "install"}}{{template "install-script"}}
|
|
{{else if eq .Page "onboarding-profile"}}{{template "onboarding-profile-script"}}
|
|
{{else if eq .Page "onboarding-plan"}}{{template "onboarding-plan-script"}}
|
|
{{end}}
|
|
<script>
|
|
document.querySelectorAll('.nav-dropdown-trigger').forEach(t=>t.addEventListener('click',()=>t.parentElement.classList.toggle('open')));
|
|
|
|
// Language selector state management
|
|
(function() {
|
|
const langTrigger = document.getElementById('languageTrigger');
|
|
if (!langTrigger) return;
|
|
|
|
const dropdown = langTrigger.closest('.nav-dropdown--language');
|
|
const langItems = dropdown.querySelectorAll('[data-lang]');
|
|
|
|
// Load saved preference
|
|
const savedLang = localStorage.getItem('preferredLanguage') || 'en';
|
|
const langFlags = { en: '🇺🇸', de: '🇩🇪', fr: '🇫🇷' };
|
|
|
|
// Set initial active state
|
|
langItems.forEach(el => {
|
|
if (el.dataset.lang === savedLang) {
|
|
el.classList.add('active');
|
|
langTrigger.textContent = langFlags[savedLang] + ' ' + savedLang.toUpperCase();
|
|
} else {
|
|
el.classList.remove('active');
|
|
}
|
|
});
|
|
|
|
// Handle language selection
|
|
langItems.forEach(el => el.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
const lang = el.dataset.lang;
|
|
const flag = el.textContent.trim().split(' ')[0];
|
|
|
|
langTrigger.textContent = flag + ' ' + lang.toUpperCase();
|
|
langItems.forEach(i => i.classList.remove('active'));
|
|
el.classList.add('active');
|
|
localStorage.setItem('preferredLanguage', lang);
|
|
|
|
// Navigate to language path
|
|
if (lang === 'en') window.location.href = '/';
|
|
else window.location.href = '/' + lang;
|
|
}));
|
|
})();
|
|
|
|
// Currency selector - fetch from API and render with sections
|
|
(function() {
|
|
const currencyTrigger = document.getElementById('currencyTrigger');
|
|
if (!currencyTrigger) return;
|
|
|
|
async function loadCurrencies() {
|
|
const menu = document.getElementById('currencyMenu');
|
|
if (!menu) return;
|
|
|
|
try {
|
|
const response = await fetch('/api/currencies');
|
|
if (!response.ok) throw new Error('ERR-CURRENCY-001: Failed to load currencies');
|
|
const data = await response.json();
|
|
|
|
// Clear existing content
|
|
menu.innerHTML = '';
|
|
|
|
// Render "Popular" section
|
|
if (data.top && data.top.length > 0) {
|
|
const popularHeader = document.createElement('div');
|
|
popularHeader.className = 'dropdown-section';
|
|
popularHeader.textContent = 'Popular';
|
|
menu.appendChild(popularHeader);
|
|
|
|
data.top.forEach(currency => {
|
|
const item = createCurrencyItem(currency, currencyTrigger);
|
|
menu.appendChild(item);
|
|
});
|
|
}
|
|
|
|
// Divider between sections
|
|
if (data.all && data.all.length > 0 && data.top && data.top.length > 0) {
|
|
const divider = document.createElement('div');
|
|
divider.className = 'dropdown-divider';
|
|
menu.appendChild(divider);
|
|
}
|
|
|
|
// Render "All Currencies" section
|
|
if (data.all && data.all.length > 0) {
|
|
const allHeader = document.createElement('div');
|
|
allHeader.className = 'dropdown-section';
|
|
allHeader.textContent = 'All Currencies';
|
|
menu.appendChild(allHeader);
|
|
|
|
data.all.forEach(currency => {
|
|
const item = createCurrencyItem(currency, currencyTrigger);
|
|
menu.appendChild(item);
|
|
});
|
|
}
|
|
} catch (err) {
|
|
// ERR-CURRENCY-002: API unavailable - keep default fallback options
|
|
console.error('ERR-CURRENCY-002: Currency API unavailable, using defaults');
|
|
}
|
|
}
|
|
|
|
function createCurrencyItem(currency, trigger) {
|
|
const item = document.createElement('a');
|
|
item.href = '#';
|
|
item.className = 'nav-dropdown-item';
|
|
item.setAttribute('data-currency', currency.code);
|
|
item.textContent = (currency.symbol || '$') + ' ' + currency.code;
|
|
|
|
// Set active state based on current selection or saved preference
|
|
const savedCurrency = localStorage.getItem('preferredCurrency') || 'USD';
|
|
const currentText = trigger.textContent.trim();
|
|
if (currentText.includes(currency.code) || savedCurrency === currency.code) {
|
|
item.classList.add('active');
|
|
if (savedCurrency === currency.code) {
|
|
trigger.textContent = (currency.symbol || '$') + ' ' + currency.code;
|
|
}
|
|
}
|
|
|
|
item.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
const code = item.getAttribute('data-currency');
|
|
const symbol = currency.symbol || '$';
|
|
trigger.textContent = symbol + ' ' + code;
|
|
|
|
// Update active state
|
|
document.querySelectorAll('.nav-dropdown--currency .nav-dropdown-item').forEach(i => i.classList.remove('active'));
|
|
item.classList.add('active');
|
|
|
|
// Store preference
|
|
localStorage.setItem('preferredCurrency', code);
|
|
|
|
// Refresh page to apply currency (or fetch rates via JS)
|
|
window.location.reload();
|
|
});
|
|
|
|
return item;
|
|
}
|
|
|
|
// Load currencies on page load
|
|
loadCurrencies();
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|