From d21ac00ea0d56723cf88112c1de0c0d8c2a3b0d2 Mon Sep 17 00:00:00 2001 From: wksantiago Date: Fri, 26 Dec 2025 09:31:57 -0400 Subject: [PATCH 1/8] Extract form endpoint to config --- assets/js/main.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/js/main.js b/assets/js/main.js index fdc8dff..38ce529 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,6 +1,10 @@ (function() { 'use strict'; + const CONFIG = { + FORM_ENDPOINT: 'https://formspree.io/f/mwkwqwkl' + }; + const DATA = { services: [ { icon: "pe-7s-rocket", title: "Custom Software Development", desc: "Full-cycle software development from ideation to production. Since 2018, we've been building custom enterprise solutions tailored to your unique business needs.", features: ["End-to-End Development", "Agile Methodology", "Cloud-Native Architecture", "Continuous Integration/Deployment"], expandedContent: "With years of experience since 2018, we've delivered custom software solutions for various companies across industries.", useCases: ["Enterprise application development", "SaaS platform creation", "Mobile and web application development", "Legacy system modernization"] }, @@ -318,7 +322,7 @@ formData.append('Referral', sanitize(form.referral.value.trim())); formData.append('comments', sanitize(form.comments.value.trim())); try { - const response = await fetch('https://formspree.io/f/mwkwqwkl', { method: 'POST', body: formData, headers: { 'Accept': 'application/json' } }); + const response = await fetch(CONFIG.FORM_ENDPOINT, { method: 'POST', body: formData, headers: { 'Accept': 'application/json' } }); if (response.ok) { status.innerHTML = '
Thank you! Your message has been sent.
'; status.style.display = 'block'; form.reset(); setTimeout(() => status.style.display = 'none', 5000); } else throw new Error('Network error'); } catch { status.innerHTML = '
Sorry, there was an error. Please try again.
'; status.style.display = 'block'; } From db9cccf52f3dcaa77b258a801593fddc26bf2c96 Mon Sep 17 00:00:00 2001 From: wksantiago Date: Fri, 26 Dec 2025 10:44:22 -0400 Subject: [PATCH 2/8] Freeze CONFIG object --- assets/js/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/main.js b/assets/js/main.js index 38ce529..d047dbd 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,9 +1,9 @@ (function() { 'use strict'; - const CONFIG = { + const CONFIG = Object.freeze({ FORM_ENDPOINT: 'https://formspree.io/f/mwkwqwkl' - }; + }); const DATA = { services: [ From ef8b2d5444dae3b788af6f5d7fc7e694305f5fba Mon Sep 17 00:00:00 2001 From: wksantiago Date: Fri, 26 Dec 2025 11:42:43 -0400 Subject: [PATCH 3/8] Remove .well-known directory --- .well-known/lnurlp/william | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .well-known/lnurlp/william diff --git a/.well-known/lnurlp/william b/.well-known/lnurlp/william deleted file mode 100644 index bfe841f..0000000 --- a/.well-known/lnurlp/william +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","tag":"payRequest","commentAllowed":255,"callback":"https://getalby.com/lnurlp/williamsantiago/callback","metadata":"[[\"text/identifier\",\"williamsantiago@getalby.com\"],[\"text/plain\",\"Sats for williamsantiago\"]]","minSendable":1000,"maxSendable":11000000000,"payerData":{"name":{"mandatory":false},"email":{"mandatory":false}},"nostrPubkey":"79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432","allowsNostr":true} \ No newline at end of file From a2a7792ed880c09ba055458b1faa1a23d3a3e541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kyle=20=F0=9F=90=86?= Date: Fri, 26 Dec 2025 11:23:57 -0500 Subject: [PATCH 4/8] Fix social icons in footer, add LICENSE and SECURITY.md --- LICENSE | 21 ++++++ SECURITY.md | 7 ++ assets/css/colors/green.css | 24 +----- assets/css/essential-only.css | 41 +--------- assets/css/mobile-responsive-fixes.css | 100 +++++++++++++++---------- assets/css/plain-html.css | 3 +- index.html | 2 +- 7 files changed, 93 insertions(+), 105 deletions(-) create mode 100644 LICENSE create mode 100644 SECURITY.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..acefb8a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 PrivKey LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..98c98b7 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +## Reporting a Vulnerability + +If you discover a security vulnerability, please report it to **security@privkey.io**. + +Do not open a public issue. diff --git a/assets/css/colors/green.css b/assets/css/colors/green.css index 5c9b1c5..0063df9 100644 --- a/assets/css/colors/green.css +++ b/assets/css/colors/green.css @@ -4,7 +4,6 @@ File Description: Main CSS file of the template */ - .text-primary,.read-btn, .navbar-custom.navbar-white .navbar-nav li.active a, .navbar-custom.navbar-white .navbar-nav li a:hover, @@ -14,14 +13,11 @@ color: #27ae60 !important; } - .section-title-border, .services-box:hover i,.bg-primary,.btn-primary,.features-item-list li:before,.process-left-icon-1 i, .process-left-icon-2 i, .account-card .form-check-input:checked { background-color: #27ae60 !important; } - - .btn-primary,.play-btn,.account-card .form-check-input:checked { border-color:#27ae60 !important; } @@ -31,25 +27,7 @@ .btn-primary:active, .btn-primary.active, .btn-primary.focus, -.btn-primary:active, -.btn-primary:focus, -.btn-primary:hover, -.open > .dropdown-toggle.btn-primary{ +.open > .dropdown-toggle.btn-primary { background-color: #27ae60; -} - - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.btn-primary.focus, -.btn-primary:active, -.btn-primary:focus, -.btn-primary:hover, -.open > .dropdown-toggle.btn-primary{ border-color: #27ae60 !important; } - - - diff --git a/assets/css/essential-only.css b/assets/css/essential-only.css index d0a98ac..48cd2c2 100644 --- a/assets/css/essential-only.css +++ b/assets/css/essential-only.css @@ -89,25 +89,6 @@ section[id] { } } -/* Hero section particle animation */ -@keyframes float { - 0%, 100% { - transform: translateY(0px) translateX(0px); - opacity: 0.7; - } - 25% { - transform: translateY(-10px) translateX(5px); - opacity: 1; - } - 50% { - transform: translateY(-5px) translateX(-5px); - opacity: 0.8; - } - 75% { - transform: translateY(-15px) translateX(3px); - opacity: 0.9; - } -} /* =========================================== MINIMAL TEAM PHOTO HOVER EFFECTS @@ -353,13 +334,7 @@ section[id] { filter: blur(0); } -/* Accessibility Improvements */ -/* Focus Indicators */ -*:focus { - outline: 2px solid #27ae60 !important; - outline-offset: 2px !important; -} - +/* Focus Indicators for buttons and links (higher specificity than generic *:focus) */ button:focus, a:focus { outline: 2px solid #27ae60 !important; @@ -367,20 +342,6 @@ a:focus { box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.3) !important; } -/* Skip Link Focus */ -.skip-nav:focus { - position: fixed !important; - top: 20px !important; - left: 20px !important; - z-index: 10000 !important; - padding: 12px 20px !important; - background: #27ae60 !important; - color: white !important; - text-decoration: none !important; - border-radius: 4px !important; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important; -} - /* Screen Reader Only Text */ .sr-only { position: absolute !important; diff --git a/assets/css/mobile-responsive-fixes.css b/assets/css/mobile-responsive-fixes.css index c393599..fa94a7b 100644 --- a/assets/css/mobile-responsive-fixes.css +++ b/assets/css/mobile-responsive-fixes.css @@ -346,14 +346,23 @@ /* Additional mobile improvements */ @media (max-width: 768px) { - /* Hero section text container */ .hero-text-container { padding: 12px 18px !important; margin: 0 1rem !important; max-width: calc(100% - 2rem) !important; - min-height: 80px !important; + min-height: 100px !important; + height: 100px !important; + line-height: 1.6 !important; + white-space: normal !important; + word-wrap: break-word !important; + overflow-wrap: break-word !important; + transition: none !important; + overflow: hidden !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; } - + .hero-text-container > div { font-size: 1.1rem !important; white-space: normal !important; @@ -361,21 +370,23 @@ overflow-wrap: break-word !important; hyphens: auto !important; } - - /* Hero title */ + + .custom-typing-wrapper { + min-height: 3em !important; + display: block !important; + } + .home-title { font-size: 1.75rem !important; line-height: 1.3 !important; margin-bottom: 1rem !important; } - - /* Container padding */ + .container { padding-left: 15px !important; padding-right: 15px !important; } - - /* Section padding */ + .section { padding-top: 60px !important; padding-bottom: 60px !important; @@ -439,29 +450,6 @@ z-index: 1; } -/* Mobile text container adjustments */ -@media (max-width: 768px) { - /* Fixed height container to prevent layout shift */ - .hero-text-container { - min-height: 100px !important; - height: 100px !important; - line-height: 1.6 !important; - white-space: normal !important; - word-wrap: break-word !important; - overflow-wrap: break-word !important; - transition: none !important; - overflow: hidden !important; - display: flex !important; - align-items: center !important; - justify-content: center !important; - } - - /* Prevent layout shift during typing animation */ - .custom-typing-wrapper { - min-height: 3em !important; - display: block !important; - } -} /* Fix for very small screens */ @media (max-width: 375px) { @@ -647,6 +635,44 @@ display: none !important; } } +/* Fix: Social icons in footer Follow Us box */ +.social-icons-list { + display: flex; + justify-content: center; + align-items: center; + gap: 0.15rem; + list-style: none; + padding: 0; + margin: 0 0 1rem 0; +} + +.social-icons-list .list-inline-item { + margin: 0; +} + +.social-icons-list .social-icon { + width: 32px; + height: 32px; + background: none !important; + border: none !important; +} + +.social-icons-list .social-icon:hover { + background: none !important; + border: none !important; +} + +.social-icons-list .social-icon svg { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; +} + +.social-icons-list .social-icon i { + font-size: 20px; +} + /* Ensure smooth scrolling behavior */ html { scroll-behavior: smooth; @@ -678,19 +704,15 @@ html { @media (max-width: 768px) { .team-bio-overlay.team-bio-mobile { display: flex !important; + padding: 1rem 1.25rem !important; + align-items: center !important; + justify-content: center !important; } .team-bio-overlay.team-bio-desktop { display: none !important; } - .team-bio-overlay.team-bio-mobile { - padding: 1rem 1.25rem !important; - display: flex !important; - align-items: center !important; - justify-content: center !important; - } - .team-bio-content { width: 100% !important; display: flex !important; diff --git a/assets/css/plain-html.css b/assets/css/plain-html.css index 73ddfa7..142c4f9 100644 --- a/assets/css/plain-html.css +++ b/assets/css/plain-html.css @@ -1,5 +1,4 @@ .skip-nav{position:absolute;left:-9999px;z-index:999;padding:8px 16px;background:#28a745;color:#fff;text-decoration:none;border-radius:4px} -.skip-nav:focus{left:20px;top:20px} .hero-particles,.footer-particles{position:absolute;top:0;left:0;right:0;bottom:0;background:radial-gradient(2px 2px at 20% 30%,rgba(39,174,96,.3),transparent),radial-gradient(1px 1px at 60% 70%,rgba(39,174,96,.2),transparent),radial-gradient(1px 1px at 90% 40%,rgba(39,174,96,.1),transparent),radial-gradient(2px 2px at 10% 80%,rgba(39,174,96,.2),transparent);animation:float 6s ease-in-out infinite;pointer-events:none;z-index:1} @keyframes float{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}} .hero-stats{display:flex;justify-content:center;gap:2rem;flex-wrap:nowrap;margin-top:2rem;margin-bottom:3rem;align-items:center;padding:1rem 0} @@ -13,7 +12,7 @@ .stats-bar{display:flex;justify-content:center;gap:4rem;padding:3rem 0;flex-wrap:nowrap} .stats-bar .stat-item{text-align:center;min-width:120px;white-space:nowrap} .footer-card{background-color:rgba(0,0,0,.6);padding:1.25rem;border-radius:12px;border:1px solid rgba(39,174,96,.3);backdrop-filter:blur(15px);width:100%;min-height:120px;display:flex;flex-direction:column;justify-content:flex-start} -.social-icon{color:#fff!important;font-size:24px!important;transition:all .3s ease;display:inline-flex!important;align-items:center!important;justify-content:center!important;width:44px!important;height:44px!important;border-radius:50%!important;background:rgba(255,255,255,.1)!important;border:1px solid rgba(255,255,255,.2)!important;padding:0!important} +.social-icon{color:#fff!important;font-size:24px!important;transition:all .3s ease;display:inline-flex!important;align-items:center!important;justify-content:center!important;width:44px;height:44px;border-radius:50%!important;background:rgba(255,255,255,.1)!important;border:1px solid rgba(255,255,255,.2)!important;padding:0!important} .social-icon:hover{color:#27ae60!important;transform:translateY(-3px) scale(1.1);background:rgba(39,174,96,.2)!important;border-color:rgba(39,174,96,.4)!important} .social-icon svg{display:block!important;flex-shrink:0!important;width:24px!important;height:24px!important;min-width:24px!important;min-height:24px!important} .mail-cellphone{display:inline-flex;align-items:center;justify-content:flex-start;color:#fff;font-size:1.1rem;text-decoration:none;transition:color .3s ease} diff --git a/index.html b/index.html index f26df90..4861227 100644 --- a/index.html +++ b/index.html @@ -381,7 +381,7 @@

Our Technology

Open Source Contributions

- We value open source development and contribute back to the Bitcoin, Lightning Network, and Nostr communities. + Contributing to Bitcoin, Lightning Network, and Nostr communities.

-
-
2+
Active Projects
-
100%
Open Source
-
MIT/LGPL
Licensed
-
@@ -231,9 +219,6 @@

Community Contributions

Meet Our Team

-
- We lead the industry through continuous R&D, backed by a team of top cybersecurity experts and advisors. -
@@ -274,7 +259,7 @@

Stay Updated with PrivKey's Blog

Get In Touch

- Schedule a confidential consultation to discuss your enterprise cybersecurity and blockchain infrastructure requirements. + Schedule a consultation to discuss your security requirements.
@@ -311,16 +296,13 @@

Get In Touch

Schedule a Demo
-

Book a 30-minute consultation with our security experts

-
- - Book Now - - Available Monday-Friday, 9AM-4PM EST -
+ + Book Now +
+
@@ -405,7 +387,7 @@
`).join(''); } - function renderTechModules() { - document.getElementById('tech-modules-grid').innerHTML = DATA.techModules.map(m => ` -
-
- ${m.alt} -
-

${m.title}

-

${m.desc}

-
    ${m.features.map(f => `
  • ${f}
  • `).join('')}
-
`).join(''); - } - - function renderOpenSourceProjects() { - document.getElementById('opensource-projects').innerHTML = ` + function renderProducts() { + document.getElementById('products-grid').innerHTML = `
- ${DATA.openSourceProjects.map(p => ` + ${DATA.products.map(p => `
${p.name} @@ -228,9 +205,10 @@ } function renderResources() { - document.getElementById('resources-grid').innerHTML = DATA.resources.map(r => ` + const grid = document.getElementById('resources-grid'); + grid.innerHTML = DATA.resources.map((r, i) => `
-
+
${r.readTime}
${r.title}
@@ -238,6 +216,7 @@
`).join(''); + grid.querySelectorAll('.resource-card').forEach(card => card.addEventListener('click', () => window.open(DATA.resources[card.dataset.resource].link, '_blank', 'noopener,noreferrer'))); } function initNavbar() { @@ -292,23 +271,6 @@ function closeMobileMenu() { state.mobileMenuOpen = false; document.getElementById('navbarCollapse').classList.remove('show'); document.querySelector('.navbar-toggler').setAttribute('aria-expanded', 'false'); } - function initTypingEffect() { - const typedEl = document.querySelector('.typed-text'); - const cursor = document.querySelector('.cursor'); - const texts = DATA.typingTexts; - let textIndex = 0, charIndex = 0, isDeleting = false; - function type() { - const current = texts[textIndex]; - typedEl.textContent = current.substring(0, isDeleting ? --charIndex : ++charIndex); - let delay = isDeleting ? 30 : 50; - if (!isDeleting && charIndex === current.length) { delay = 3000; isDeleting = true; } - else if (isDeleting && charIndex === 0) { isDeleting = false; textIndex = (textIndex + 1) % texts.length; delay = 500; } - setTimeout(type, delay); - } - setInterval(() => cursor.style.opacity = cursor.style.opacity === '0' ? '1' : '0', 500); - setTimeout(type, 1000); - } - function initCounters() { const observer = new IntersectionObserver(entries => { entries.forEach(entry => { diff --git a/index.html b/index.html index 3f21f3b..2981f43 100644 --- a/index.html +++ b/index.html @@ -4,15 +4,15 @@ - + - PrivKey - Enterprise Cybersecurity & Blockchain Solutions - - + PrivKey - Self-Sovereign Bitcoin & Nostr Infrastructure + + - - + + @@ -20,8 +20,8 @@ - - + + @@ -36,16 +36,16 @@ "@context": "https://schema.org", "@type": "Organization", "name": "PrivKey LLC", - "description": "Leading cybersecurity and blockchain consulting firm with 30+ years experience.", + "description": "Self-sovereign Bitcoin and Nostr infrastructure. Your keys, your stack.", "url": "https://privkey.io", "logo": "https://privkey.io/assets/images/LOGO_Green_new_transparent.png", - "foundingDate": "2020", + "foundingDate": "2018", "founder": [ {"@type": "Person", "name": "William Santiago"}, {"@type": "Person", "name": "Kyle Santiago"} ], "address": {"@type": "PostalAddress", "addressCountry": "US"}, - "sameAs": ["https://linkedin.com/company/privkey", "https://github.com/privkey"] + "sameAs": ["https://linkedin.com/company/privkeyllc", "https://github.com/privkeyio", "https://x.com/privkey_io"] } @@ -104,7 +104,7 @@
-
+
@@ -113,30 +113,10 @@
@@ -175,7 +155,7 @@

Our Services

Who We Are

- Founded by cybersecurity veterans with 30+ years of combined experience, PrivKey specializes in enterprise-grade security solutions for digital assets, Bitcoin, Lightning Network, and blockchain infrastructure. + Founded by cybersecurity veterans with 30+ years of combined experience. We build self-sovereign Bitcoin and Nostr infrastructure—your keys, your stack.

@@ -183,27 +163,17 @@

Who We Are

-
-
-
-

Our Technology

-

PrivKey's Enterprise Security Platform for Bitcoin & Lightning Network

-
-
-
-
- -
+
-

Open Source Contributions

+

Open Source

- Contributing to Bitcoin, Lightning Network, and Nostr communities. + Bitcoin, Lightning, and Nostr infrastructure.

-
+

Community Contributions

@@ -244,7 +214,7 @@

Resources & Insights

@@ -356,7 +326,7 @@
Schedule
-

Leading the way in cybersecurity and Lightning Network innovation

+

Your keys, your stack

@@ -388,7 +358,7 @@

- From 07c79c4268b83ef767d2d7b73b4123b68c930451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kyle=20=F0=9F=90=86?= Date: Fri, 26 Dec 2025 13:20:23 -0500 Subject: [PATCH 8/8] text updates --- assets/css/mobile-responsive-fixes.css | 25 +++++++++++- assets/js/main.js | 55 +++++++++++++++++++------- index.html | 44 ++++++++++----------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/assets/css/mobile-responsive-fixes.css b/assets/css/mobile-responsive-fixes.css index d4d926c..7bae31f 100644 --- a/assets/css/mobile-responsive-fixes.css +++ b/assets/css/mobile-responsive-fixes.css @@ -76,6 +76,18 @@ .mobile-menu-close-btn { flex: 0 0 auto !important; margin-left: auto !important; + width: 44px !important; + height: 44px !important; + border-radius: 50% !important; + border: 2px solid rgba(255, 255, 255, 0.3) !important; + background: rgba(255, 255, 255, 0.1) !important; + color: #fff !important; + font-size: 1.5rem !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + cursor: pointer !important; + transition: all 0.2s ease !important; } .mobile-menu-close-btn:hover { @@ -322,8 +334,19 @@ } } -/* Fix 3: Hero buttons spacing on mobile */ @media (max-width: 768px) { + .display-table { + min-height: 50vh !important; + } + + #home .btn-primary { + padding: 12px 24px !important; + font-size: 1rem !important; + max-width: 220px !important; + display: block !important; + margin: 0 auto !important; + } + .mt-5[role="group"] { display: flex !important; flex-wrap: wrap !important; diff --git a/assets/js/main.js b/assets/js/main.js index fe63480..a51e4f1 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -7,22 +7,22 @@ MAX_SUBMISSIONS: 3 }); - const formState = { submissions: [], blocked: false }; + const formState = { submissions: [], blocked: false, rateLimited: false, retryAfter: null }; const DATA = { services: [ - { icon: "pe-7s-rocket", title: "Software Development", desc: "Full-cycle development from ideation to production. We build secure, scalable applications for enterprises—web, mobile, and infrastructure.", features: ["Full-Stack Development", "Security-First Architecture", "Open Source Contributions", "API & Protocol Implementation"], expandedContent: "Since 2018, we've delivered custom software for enterprises across industries—from high-throughput systems to user-facing applications.", useCases: ["Enterprise applications", "Bitcoin & Lightning tooling", "Web & mobile development", "Custom integrations"] }, + { icon: "pe-7s-rocket", title: "Software Development", desc: "Full-cycle development from ideation to production. We build secure, scalable applications for enterprises: web, mobile, and infrastructure.", features: ["Full-Stack Development", "Security-First Architecture", "Open Source Contributions", "API & Protocol Implementation"], expandedContent: "Since 2018, we've delivered custom software for enterprises across industries, from high-throughput systems to user-facing applications.", useCases: ["Enterprise applications", "Bitcoin & Lightning tooling", "Web & mobile development", "Custom integrations"] }, { icon: "pe-7s-lock", title: "Key Management & Custody", desc: "Self-sovereign key infrastructure with FROST threshold signing, TEE enclave protection, and hidden volumes for plausible deniability.", features: ["FROST Threshold Signatures", "TEE Enclave Security", "Hidden Volumes", "NIP-46 Remote Signing"], expandedContent: "Our Keep signing stack is the only open-source solution combining FROST + Enclave + Nostr + Hidden Volumes.", useCases: ["Enterprise self-custody setup", "Multi-party signing infrastructure", "AI agent key constraints", "Institutional wallet architecture"] }, - { icon: "pe-7s-gleam", title: "Lightning Infrastructure", desc: "Enterprise Lightning Network deployment, node security, channel management, and payment routing optimization.", features: ["Node Deployment & Hardening", "Channel Security", "Liquidity Management", "Payment Routing"], expandedContent: "We help enterprises run Lightning infrastructure that scales—securely and reliably.", useCases: ["Institutional Lightning nodes", "Payment processing infrastructure", "Cross-border settlement", "Liquidity provisioning"] }, - { icon: "pe-7s-note2", title: "Security Auditing", desc: "Comprehensive audits for Bitcoin infrastructure, key management systems, Lightning nodes, and custody operations.", features: ["Key Management Audits", "Node Security Assessment", "Penetration Testing", "Compliance Review"], expandedContent: "We audit what matters—keys, signing infrastructure, and custody operations. 30+ years combined experience.", useCases: ["Custody infrastructure audits", "Lightning node security review", "Key management assessment", "Pre-deployment security review"] }, + { icon: "pe-7s-gleam", title: "Lightning Infrastructure", desc: "Enterprise Lightning Network deployment, node security, channel management, and payment routing optimization.", features: ["Node Deployment & Hardening", "Channel Security", "Liquidity Management", "Payment Routing"], expandedContent: "We help enterprises run Lightning infrastructure that scales, securely and reliably.", useCases: ["Institutional Lightning nodes", "Payment processing infrastructure", "Cross-border settlement", "Liquidity provisioning"] }, + { icon: "pe-7s-note2", title: "Security Auditing", desc: "Comprehensive audits for Bitcoin infrastructure, key management systems, Lightning nodes, and custody operations.", features: ["Key Management Audits", "Node Security Assessment", "Penetration Testing", "Compliance Review"], expandedContent: "We audit what matters: keys, signing infrastructure, and custody operations. 30+ years combined experience.", useCases: ["Custody infrastructure audits", "Lightning node security review", "Key management assessment", "Pre-deployment security review"] }, { icon: "pe-7s-plugin", title: "Nostr Infrastructure", desc: "High-performance relay deployment, NIP implementations, and decentralized identity solutions built on Nostr.", features: ["Relay Deployment (Wisp)", "NIP Implementation", "Blossom Media Storage", "Decentralized Identity"], expandedContent: "Wisp is 4x faster than competitors. We build and deploy Nostr infrastructure that scales.", useCases: ["Enterprise relay deployment", "Private communication infrastructure", "Decentralized identity systems", "Lightning-integrated Nostr apps"] }, - { icon: "pe-7s-safe", title: "Consulting", desc: "Strategic guidance for Bitcoin adoption, self-custody implementation, and sovereign infrastructure planning.", features: ["Self-Custody Strategy", "Infrastructure Architecture", "Regulatory Guidance", "Technology Selection"], expandedContent: "We help enterprises own their infrastructure—from treasury strategy to full-stack deployment.", useCases: ["Bitcoin treasury planning", "Self-custody roadmap", "Infrastructure architecture", "Vendor-free sovereignty"] } + { icon: "pe-7s-safe", title: "Consulting", desc: "Strategic guidance for Bitcoin adoption, self-custody implementation, and sovereign infrastructure planning.", features: ["Self-Custody Strategy", "Infrastructure Architecture", "Regulatory Guidance", "Technology Selection"], expandedContent: "We help enterprises own their infrastructure, from treasury strategy to full-stack deployment.", useCases: ["Bitcoin treasury planning", "Self-custody roadmap", "Infrastructure architecture", "Vendor-free sovereignty"] } ], highlights: [ - { icon: "pe-7s-medal", title: "30+ Years Experience", description: "Decades of expertise in networking, cybersecurity, and Bitcoin infrastructure" }, - { icon: "pe-7s-lock", title: "Self-Sovereign Security", description: "FROST threshold signing with TEE enclave protection" }, - { icon: "pe-7s-network", title: "Full Stack", description: "Relay → Signing → Policy → Payments → Oracles" }, - { icon: "pe-7s-rocket", title: "Zig + Rust", description: "Zig for speed (4x throughput), Rust for security (memory-safe crypto)" } + { icon: "pe-7s-medal", title: "30+ Years Experience", description: "Decades of expertise in networking, cybersecurity, and Bitcoin infrastructure." }, + { icon: "pe-7s-lock", title: "Open Source First", description: "Trust through transparency. Core infrastructure you can audit and self-host." }, + { icon: "pe-7s-science", title: "Performance + Security", description: "Zig for speed, Rust for security. We don't compromise on either." }, + { icon: "pe-7s-rocket", title: "Self-Sovereign", description: "Own your data, identity, and money without third-party custody." } ], products: [ { name: "Keep", description: "Self-custodial key management for Nostr and Bitcoin.", language: "Rust", url: "https://github.com/privkeyio/keep" }, @@ -200,6 +200,20 @@

`).join(''); } + function escapeHtml(str) { + const div = document.createElement('div'); + div.textContent = str; + return div.innerHTML; + } + + function sanitizeUrl(url) { + try { + const parsed = new URL(url); + if (parsed.protocol === 'https:' || parsed.protocol === 'http:') return parsed.href; + } catch {} + return '#'; + } + async function renderResources() { const grid = document.getElementById('resources-grid'); grid.innerHTML = '

Loading articles...

'; @@ -210,14 +224,17 @@ const articles = data.items.slice(0, 6); grid.innerHTML = articles.map((r, i) => { const date = new Date(r.pubDate).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); - const desc = r.description.replace(/<[^>]*>/g, '').substring(0, 120) + '...'; + const rawDesc = r.description.replace(/<[^>]*>/g, '').substring(0, 120) + '...'; + const safeTitle = escapeHtml(r.title); + const safeDesc = escapeHtml(rawDesc); + const safeUrl = sanitizeUrl(r.link); return `
-
+
${date}
-
${r.title}
-

${desc}

+
${safeTitle}
+

${safeDesc}

`; @@ -334,9 +351,19 @@ try { const response = await fetch(CONFIG.FORM_ENDPOINT, { method: 'POST', body: formData, headers: { 'Accept': 'application/json' } }); if (response.ok) { status.innerHTML = '
Thank you! Your message has been sent.
'; status.style.display = 'block'; form.reset(); setTimeout(() => status.style.display = 'none', 5000); } + else if (response.status === 429) { + formState.rateLimited = true; + const retryAfter = parseInt(response.headers.get('Retry-After'), 10) || 60; + formState.retryAfter = Date.now() + retryAfter * 1000; + submitBtn.disabled = true; + status.innerHTML = `
Server rate limit reached. Please wait ${retryAfter} seconds.
`; + status.style.display = 'block'; + setTimeout(() => { formState.rateLimited = false; formState.retryAfter = null; submitBtn.disabled = false; submitBtn.innerHTML = 'Send Message'; }, retryAfter * 1000); + return; + } else throw new Error('Network error'); } catch { status.innerHTML = '
Sorry, there was an error. Please try again.
'; status.style.display = 'block'; } - finally { submitBtn.disabled = false; submitBtn.innerHTML = 'Send Message'; } + finally { if (!formState.rateLimited) { submitBtn.disabled = false; submitBtn.innerHTML = 'Send Message'; } } }); } diff --git a/index.html b/index.html index 01547ae..fb225bc 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ PrivKey - Self-Sovereign Bitcoin & Nostr Infrastructure - + @@ -76,6 +76,7 @@ + @@ -85,16 +86,18 @@ - +
@@ -104,11 +107,10 @@
-
+
-
-
+
@@ -123,7 +125,6 @@

-
@@ -132,10 +133,10 @@

-

Our Services

+

Our Services

- Software development, key management, auditing, and infrastructure—since 2018. + Software development, key management, auditing, and infrastructure since 2018.
@@ -149,11 +150,11 @@

Our Services

-
+

Who We Are

-
-

- Founded by cybersecurity veterans with 30+ years of combined experience. We build privacy-first Bitcoin, Lightning, and Nostr infrastructure—so you never have to trust a third party with your keys. +

+

+ Founded by cybersecurity veterans with 30+ years of combined experience. We build privacy-first, high-performance infrastructure for Bitcoin, Lightning, and Nostr. Open source. Self-hostable. No vendor lock-in.

@@ -165,10 +166,8 @@

Who We Are

-

Open Source

-

- Bitcoin, Lightning, and Nostr infrastructure. -

+

Our Products

+
@@ -185,7 +184,7 @@

Community Contributions

-

Meet Our Team

+

Meet Our Team

@@ -198,8 +197,9 @@

Meet Our Team

-

Resources & Insights

-

+

Resources & Insights

+
+

Stay ahead with our latest research, white papers, and industry insights.

@@ -224,7 +224,7 @@

Stay Updated with PrivKey's Blog

-

Get In Touch

+

Get In Touch

Schedule a consultation to discuss your security requirements.