Анализ сайта virtalabs.com
Основное Готовность: 100%
Домен
virtalabs.com
Состояние доменного имени
?
Проверяем корректность доменного имени и наличие технических проблем на уровне домена.
Домен второго уровня идеален для продвижения.
Отличный запоминающийся домен.
Ответ сервера
200 Успешный ответ
HTTP-код ответа и цепочка редиректов
?
Код 200 — страница доступна. Коды 3xx — редиректы (цепочки замедляют загрузку и размывают ссылочный вес). Коды 4xx/5xx — ошибки, поисковик не сможет проиндексировать страницу.
Сервер настроен корректно.
Цепочка редиректов:
http://virtalabs.com
301 MovedPermanently
https://virtalabs.com/
200 OK
Безопасность
Сайт безопасен
Использование HTTPS и SSL-сертификат
?
HTTPS — обязательный стандарт. Google и Яндекс отдают предпочтение защищённым сайтам. Отсутствие SSL или просроченный сертификат ведут к предупреждениям в браузере и снижению позиций.
На сайте работает защищенный протокол ssl и сайт открывается по https.
Ssl-сертификат действителен до 28.10.2026 23:43:40.
Сервер поддерживает HTTP/3 (QUIC) — новейший протокол.
Включён HSTS (Strict-Transport-Security) — защита от подмены на http.
HTTP автоматически перенаправляется на HTTPS.
Поздравляем! Сайт не содержится в реестре РКН.
Кодировка
UTF-8
Кодировка символов страницы
?
Стандарт — UTF-8. Неправильная кодировка вызывает нечитаемые символы и мешает поисковику корректно распознать текст страницы.
Указана кодировка на странице UTF-8.
Язык
en
Атрибут lang в HTML-теге
?
Атрибут lang (<html lang="ru">) сообщает поисковикам и браузерам, на каком языке написана страница. Помогает при ранжировании в региональном поиске.
Язык документа указан явно: en.
Скорость загрузки
~0,56сек
Время отклика сервера (TTFB)
?
Time To First Byte — время до получения первого байта от сервера. Норма до 200 мс. Медленный отклик ухудшает пользовательский опыт и ранжирование: Яндекс и Google учитывают скорость страниц.
Скорость загрузки сайта 0,56сек оптимальна.
Объем документа
70Кб
Размер HTML-кода страницы
?
Слишком большой HTML замедляет парсинг браузером и сканирование поисковым роботом. Рекомендуется не более 200 Кб.
Объем html-документа 70Кб оптимален.
Структура html-документа корректна.
Ресурсы
Ресурсы: 1
Внешние ресурсы страницы (CSS, JS, изображения)
?
Количество и тип подключённых ресурсов влияют на скорость загрузки. Большое число запросов увеличивает время рендеринга страницы.
Кол-во файлов ресурсов 1 достаточно.
Показать полный список ресурсов
| Тип | Название | Значение |
|---|---|---|
| stylesheet | https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=IBM+Plex+Mono:ital,wght@0,400;0,500;1,400&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap |
Серверные заголовки
Кол-во: 11
HTTP-заголовки ответа сервера
?
Заголовки сервера передают браузеру и поисковику служебную информацию: кеширование, безопасность (CSP, HSTS), сжатие (gzip). Правильная настройка ускоряет загрузку и повышает защищённость.
Найдены серверные заголовки 11шт. Подробнее про серверные заголовки.
Показать полный список серверных заголовков
| Ключ | Значение |
|---|---|
| Accept-Ranges | bytes |
| Cache-Control | max-age=0, private |
| Date | Sun, 23 Aug 2026 19:47:55 GMT |
| ETag | W/"11ad7-19d06e7c5d0" |
| Server | |
| Set-Cookie | GAESA=Cp4BMDBhNDFlOGMxZDU1NzBmZWQ4Mzc1M2QyMWEwM2U2NjY5YTcyNGI2ZDk3OTcxZmQ0MmFlNDY3ZmZhNmJjYmY1NDE4ZGZlZTQyZWY5YjM1ODIxYTA0OTkyMThkMGNlNmVkZGFmNGE0ZDRhODc1ZTkyMzQzZGMzOTU2NGQxZjkzNmU3YTVlNmVlNGYxMDRlM2UyNDk5OTg2ZjAwODhhOTAQq6apgYM0; expires=Tue, 22-Sep-2026 19:47:55 GMT; path=/ |
| Strict-Transport-Security | max-age=63072000; includeSubDomains |
| x-cloud-trace-context | 41e7cfdb537d402c99ab19ceae84a634;o=1 |
| X-Powered-By | Express |
| Via | 1.1 google |
| Alt-Svc | h3=":443"; ma=2592000 |
CMS
Не определена
Система управления сайтом (движок)
?
CMS — это движок, на котором работает сайт (WordPress, 1C-Bitrix, Tilda и др.). Знание CMS помогает понять возможности SEO-оптимизации и подобрать подходящие инструменты. «Не определена» — вероятно, самописный сайт или нестандартная сборка.
CMS не определена. Вероятно, сайт самописный либо движок надёжно скрыт. Это не ошибка.
Веб-сервер
Программное обеспечение сервера
?
Веб-сервер — это ПО, которое отдаёт страницы посетителям (nginx, Apache, IIS, LiteSpeed и др.). Определяется по серверным заголовкам ответа (Server, X-Powered-By и т.п.). «Не определён» — сервер намеренно скрывает эти заголовки, это нормальная практика безопасности.
Сайт работает на веб-сервере Node.js.
Мета-теги Готовность: 52%
Title
Virta Labs — Open Security for Connected Care
Заголовок страницы в браузере и поисковой выдаче
?
Title — главный SEO-заголовок страницы. Влияет на CTR в поиске и ранжирование. Оптимальная длина: 50–70 символов. Ключевые слова — ближе к началу.
Дублей словоформ в title не найдено.
Число символов в title 45 оптимально (норма: от 40 до 45).
Description
API-first security platform for connected care. Open-core asset management, SBOM generation, and AI risk orchestration for healthcare infrastructure.
Описание страницы в поисковой выдаче (сниппет)
?
Meta Description — текст под заголовком в выдаче. Напрямую на позиции не влияет, но влияет на CTR. Оптимальная длина: 120–160 символов.
Необходимо уменьшить число символов в description (текущее значение: 149, оптимально: от 120 до 130)
Keywords
Список ключевых слов страницы (устаревший тег)
?
Meta Keywords не учитывается Яндексом и Google для ранжирования с 2009–2012 годов. Заполнение не обязательно, но не вредит. Конкурент может использовать содержимое для анализа.
Установите мета-тег keywords!
Канонический Url
Указывает поисковику основную версию страницы
?
Canonical (rel=canonical) предотвращает проблему дублей страниц. Должен точно совпадать с URL проверяемой страницы. Неправильный canonical может передать ссылочный вес на другую страницу.
Рекомендуем прописать канонический Url.
Robots
Ошибок нет
Директивы для поисковых роботов на уровне страницы
?
Meta Robots управляет индексацией конкретной страницы: index/noindex — индексировать ли, follow/nofollow — следовать ли по ссылкам. Noindex полностью исключает страницу из поиска.
Meta-тег robots не указан. Страница свободна для индексации.
Адаптивность
width=device-width, initial-scale=1.0
Настройка масштабирования на мобильных устройствах
?
Тег viewport (<meta name="viewport">) сообщает браузеру, как масштабировать страницу на мобильных. Стандарт: width=device-width, initial-scale=1. Отсутствие — признак отсутствия мобильной версии.
Meta-тег viewport со значением-константой width=device-width задаёт ширину страницы в соответствии с размером экрана.
Meta-тег viewport со значением initial-scale=1.0 определяет масштаб 1:1, т.е. «не масштабировать».
Разметка OpenGraph
Не найдено
Мета-теги для красивых превью в соцсетях
?
OpenGraph (og:title, og:description, og:image) управляет тем, как страница выглядит при репосте в социальных сетях и мессенджерах. Отсутствие OG-тегов — невзрачный превью при шеринге.
Разметка OpenGraph не задана. Страница не оптимизирована под социальные сети. Мета-теги с разметкой Og помогают социальным роботам лучше структурировать Ваш сайт.
Все мета-теги
Кол-во: 2
Полный список мета-тегов страницы
?
Таблица всех meta-тегов, включая нестандартные. Позволяет найти опечатки, дубли и лишние теги.
Найдены мета-теги 2шт. Мета-теги не видимы для человека и предназначены для обмена информацией между веб-страницей и поисковыми системами, браузерами и другими веб-службами. С ними роботы 🤖 и устройства ведут себя более ожидаемо.
Показать полный список мета-тегов
| Тип | Название | Значение |
|---|---|---|
| name | viewport | width=device-width, initial-scale=1.0 |
| name | description | API-first security platform for connected care. Open-core asset management, SBOM generation, and AI risk orchestration for healthcare infrastructure. |
Оптимизация Готовность: 90%
Структура
Ошибок нет
Семантические HTML-элементы страницы
?
Проверяет наличие основных структурных элементов: nav, header, footer, main. Корректная семантическая структура помогает поисковику понять архитектуру страницы.
Структура документа корректна (теги <html> и <body> присутствуют в одном экземпляре).
Контент
Ошибок нет
Объём и качество текстового содержимого
?
Анализирует объём полезного текста на странице. Слишком мало — страница может считаться малополезной. Слишком много — ухудшается читаемость и восприятие.
Слова из title 8 встречаются в тексте достаточно.
Абзацев с текстом 29 достаточно.
Среднее число слов в абзаце 24 достаточно.
Кол-во знаков контента 12205 на странице оптимально.
Кол-во слов 1681 на странице оптимально.
Заголовки
Ошибок нет
Иерархия заголовков H1–H6
?
H1 должен быть один и содержать ключевой запрос. H2–H6 описывают подразделы. Пропуск уровней (H1 → H3) и несколько H1 — типичные ошибки, снижающие понятность страницы для поисковика.
На странице присутствуют заголовки <h1> 1. Это прекрасно.
На странице присутствуют заголовки <h2> 8. Это хорошо.
Тошнота
3,74
Насколько одно слово доминирует в тексте
?
Классическая тошнота = √(частота самого повторяющегося слова). Норма до 7–8: текст воспринимается естественно. Выше — поисковик может счесть страницу переспамленной.
Тошнота страницы в пределах нормы 3,74.
Академич. тошнота
26,83%
Насколько текст перенасыщен ключевыми словами
?
Академическая тошнота = (частота слова / общее количество слов) × 100%. Показывает долю конкретного слова в тексте. Норма 5–15%.
Академическая тошнота превышает норму 5-15%. Измените текст страницы!
Семантическое ядро
20
Наиболее часто встречающиеся слова на странице
?
Топ слов по частоте использования. Показывает, какие слова доминируют в тексте с точки зрения поисковика.
Контент страницы содержит осмысленный текст и слова.
Показать список слов
| Слово | Кол-во | Частота |
|---|---|---|
| security | 14 | 0,83% |
| connector | 12 | 0,71% |
| access | 11 | 0,65% |
| vulnerability | 11 | 0,65% |
| platform | 10 | 0,59% |
| github | 10 | 0,59% |
| device | 10 | 0,59% |
| discovery | 10 | 0,59% |
| medical | 9 | 0,54% |
| research | 8 | 0,48% |
| blueflow | 8 | 0,48% |
| celery | 8 | 0,48% |
| docker | 8 | 0,48% |
| devices | 8 | 0,48% |
| management | 7 | 0,42% |
| tapirx | 7 | 0,42% |
| deploy | 7 | 0,42% |
| compose | 7 | 0,42% |
| request | 6 | 0,36% |
| source | 6 | 0,36% |
Индексация Готовность: 30%
Индексирование
Ошибок нет
Разрешено ли индексирование страницы
?
Проверяет, не закрыта ли страница от индексации через robots.txt, meta robots или X-Robots-Tag. Страница, закрытая от индексации, не появится в поисковой выдаче.
Анкоров на странице 35 оптимально. Поисковые роботы обязательно проиндексируют сайт.
Robots.txt
Найден корректный robots.txt
Файл управления сканированием сайта роботами
?
Robots.txt указывает поисковым роботам, какие страницы сканировать, а какие — нет. Ошибки в файле могут случайно закрыть важные разделы от индексации.
Robots.txt настроен корректно. Размер файла: 72230 байт. Загружен за: 1сек.
Проверяемая страница не запрещена в robots.txt.
Robots.txt доступен по постоянному адресу
Цепочка редиректов для файла robots.txt:
http://virtalabs.com/robots.txt
301 MovedPermanently
https://virtalabs.com/robots.txt
200 OK
Показать содержимое robots.txt
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="API-first security platform for connected care. Open-core asset management, SBOM generation, and AI risk orchestration for healthcare infrastructure.">
<title>Virta Labs — Open Security for Connected Care</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=IBM+Plex+Mono:ital,wght@0,400;0,500;1,400&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--bg:#070910;--bg2:#0b0e18;--surface:#101420;--surface2:#161d2c;
--border:rgba(255,255,255,0.07);--border2:rgba(255,255,255,0.13);
--accent:#00c8f0;--accent-dim:rgba(0,200,240,0.08);
--green:#00d98c;--purple:#a78bfa;--coral:#ff5a6e;--amber:#f0a030;
--text:#d0dcea;--muted:#5c7080;--dim:#2a3848;
--sans:'IBM Plex Sans',-apple-system,sans-serif;
--mono:'IBM Plex Mono','Fira Code',monospace;
--serif:'DM Serif Display',Georgia,serif;
--max:1140px;--r:8px;--r2:12px;
}
html{scroll-behavior:smooth}
body{font-family:var(--sans);background:var(--bg);color:var(--text);line-height:1.6;overflow-x:hidden;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
img,svg{display:block}
/* layout */
.wrap{max-width:var(--max);margin:0 auto;padding:0 24px}
/* buttons */
.btn{display:inline-flex;align-items:center;gap:8px;padding:10px 22px;border-radius:var(--r);font-family:var(--sans);font-size:14px;font-weight:500;cursor:pointer;transition:all .18s ease;border:none;white-space:nowrap}
.btn-primary{background:var(--accent);color:#070910}
.btn-primary:hover{background:#20d8ff;transform:translateY(-1px);box-shadow:0 8px 24px rgba(0,200,240,.28)}
.btn-ghost{background:transparent;color:var(--text);border:1px solid var(--border2)}
.btn-ghost:hover{border-color:rgba(255,255,255,.28);background:rgba(255,255,255,.04)}
.btn-lg{padding:13px 28px;font-size:15px}
/* nav */
nav{position:fixed;top:0;left:0;right:0;z-index:100;height:60px;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);background:rgba(7,9,16,.75);border-bottom:1px solid var(--border);transition:background .3s}
nav.scrolled{background:rgba(7,9,16,.96)}
.nav-inner{max-width:var(--max);margin:0 auto;padding:0 24px;height:100%;display:flex;align-items:center;justify-content:space-between}
.nav-logo{display:flex;flex-direction:column;line-height:1}
.nav-logo-name{font-family:var(--mono);font-size:13px;font-weight:500;color:var(--text);letter-spacing:.06em}
.nav-logo-sub{font-family:var(--mono);font-size:10px;color:var(--accent);letter-spacing:.1em;margin-top:2px}
.nav-links{display:flex;align-items:center;gap:32px;list-style:none}
.nav-links a{font-size:13.5px;color:var(--muted);transition:color .15s}
.nav-links a:hover{color:var(--text)}
.nav-cta{display:flex;align-items:center;gap:10px}
.nav-gh{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--muted);padding:6px 12px;border:1px solid var(--border2);border-radius:var(--r);transition:all .15s}
.nav-gh:hover{color:var(--text);border-color:rgba(255,255,255,.24)}
/* hero */
.hero{position:relative;min-height:100vh;display:flex;align-items:center;padding:100px 0 80px;overflow:hidden}
.hero::before{content:'';position:absolute;inset:0;background-image:radial-gradient(rgba(255,255,255,.032) 1px,transparent 1px);background-size:24px 24px;-webkit-mask-image:radial-gradient(ellipse 90% 90% at 50% 50%,black 20%,transparent 80%);mask-image:radial-gradient(ellipse 90% 90% at 50% 50%,black 20%,transparent 80%);pointer-events:none}
.hero::after{content:'';position:absolute;top:0;left:0;right:0;height:55%;background:radial-gradient(ellipse 70% 60% at 60% 0%,rgba(0,200,240,.05) 0%,transparent 70%);pointer-events:none}
.hero-inner{position:relative;z-index:1;display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:center;max-width:var(--max);margin:0 auto;padding:0 24px}
.hero-badge{display:inline-flex;align-items:center;gap:8px;padding:5px 12px;border:1px solid rgba(0,200,240,.25);border-radius:100px;font-family:var(--mono);font-size:11px;color:var(--accent);letter-spacing:.06em;margin-bottom:24px;background:rgba(0,200,240,.05)}
.hero-badge::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--accent);animation:pulse 2s ease infinite;flex-shrink:0}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.75)}}
.hero-headline{font-family:var(--serif);font-style:italic;font-size:clamp(40px,5.5vw,70px);line-height:1.08;color:#edf2fa;margin-bottom:20px;letter-spacing:-.01em}
.hero-headline em{color:var(--accent);font-style:italic}
.hero-sub{font-size:16px;color:var(--muted);line-height:1.72;max-width:460px;margin-bottom:36px;font-weight:300}
.hero-sub strong{color:var(--text);font-weight:500}
.hero-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.hero-meta{margin-top:44px;padding-top:24px;border-top:1px solid var(--border);display:flex;align-items:center;gap:24px;flex-wrap:wrap}
.hero-meta-item{font-family:var(--mono);font-size:11px;color:var(--muted);display:flex;align-items:center;gap:6px}
.hero-meta-item::before{content:'';width:4px;height:4px;border-radius:50%;background:var(--accent);flex-shrink:0}
/* terminal */
.terminal{border-radius:var(--r2);overflow:hidden;background:#09090f;border:1px solid rgba(255,255,255,.1);box-shadow:0 40px 80px rgba(0,0,0,.7),0 0 0 1px rgba(255,255,255,.04)}
.term-header{background:#0d1018;border-bottom:1px solid rgba(255,255,255,.07);padding:11px 16px;display:flex;align-items:center;gap:7px}
.term-dot{width:11px;height:11px;border-radius:50%}
.term-dot:nth-child(1){background:#ff5f57}
.term-dot:nth-child(2){background:#febc2e}
.term-dot:nth-child(3){background:#28c840}
.term-title{font-family:var(--mono);font-size:11.5px;color:var(--muted);margin-left:6px}
.term-body{padding:18px 20px;min-height:360px;font-family:var(--mono);font-size:12.5px;line-height:1.85;overflow:hidden}
.term-line{display:block}
.term-prompt{color:var(--accent)}
.term-cmd{color:#d8e8f4}
.term-comment{color:#344a5e}
.term-flag{color:#4a6a80}
.term-ok{color:var(--green)}
.term-key{color:var(--purple)}
.term-str{color:var(--green)}
.term-num{color:var(--amber)}
.term-punct{color:var(--muted)}
.term-nested{color:#3d5a70}
.term-cursor{display:inline-block;width:7px;height:14px;background:var(--accent);animation:blink 1.1s step-end infinite;vertical-align:middle;border-radius:1px;margin-left:2px}
@keyframes blink{0%,100%{opacity:1}50%{opacity:0}}
/* section base */
section{padding:96px 0}
.section-label{font-family:var(--mono);font-size:11px;color:var(--accent);letter-spacing:.12em;text-transform:uppercase;margin-bottom:12px}
.section-title{font-family:var(--serif);font-style:italic;font-size:clamp(28px,3.5vw,46px);color:#edf2fa;line-height:1.15;margin-bottom:16px}
.section-body{font-size:16px;color:var(--muted);line-height:1.7;max-width:580px;font-weight:300}
.section-header{margin-bottom:52px}
/* stack strip */
.stack-strip{padding:18px 0;border-top:1px solid var(--border);border-bottom:1px solid var(--border);background:rgba(255,255,255,.015)}
.stack-inner{max-width:var(--max);margin:0 auto;padding:0 24px;display:flex;align-items:center;gap:0;overflow-x:auto}
.stack-label{font-family:var(--mono);font-size:10px;color:var(--dim);letter-spacing:.1em;text-transform:uppercase;margin-right:20px;white-space:nowrap}
.stack-items{display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.stack-item{font-family:var(--mono);font-size:11px;color:var(--muted);padding:4px 10px;border:1px solid var(--border);border-radius:4px;background:rgba(255,255,255,.02);white-space:nowrap}
/* products */
.products{background:var(--bg2)}
.products-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.product-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r2);padding:28px;display:flex;flex-direction:column;gap:18px;transition:border-color .2s,transform .2s;position:relative;overflow:hidden}
.product-card::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;opacity:0;transition:opacity .3s}
.product-card:hover{transform:translateY(-2px)}
.card-blueflow:hover{border-color:rgba(0,200,240,.3)}
.card-blueflow::before{background:linear-gradient(90deg,transparent,var(--accent),transparent)}
.card-tapirx:hover{border-color:rgba(0,217,140,.3)}
.card-tapirx::before{background:linear-gradient(90deg,transparent,var(--green),transparent)}
.card-vulnfwrd:hover{border-color:rgba(167,139,250,.3)}
.card-vulnfwrd::before{background:linear-gradient(90deg,transparent,var(--purple),transparent)}
.card-gurney:hover{border-color:rgba(240,160,48,.3)}
.card-gurney::before{background:linear-gradient(90deg,transparent,var(--amber),transparent)}
.product-card:hover::before{opacity:1}
.product-head{display:flex;align-items:flex-start;justify-content:space-between}
.product-name{font-family:var(--mono);font-size:17px;font-weight:500;color:var(--text);margin-bottom:3px}
.product-desc-short{font-family:var(--mono);font-size:11px;color:var(--muted)}
.product-badges{display:flex;flex-direction:column;align-items:flex-end;gap:4px}
.badge{font-family:var(--mono);font-size:10px;font-weight:500;letter-spacing:.04em;padding:3px 8px;border-radius:4px;white-space:nowrap}
.badge-mit{background:rgba(0,200,240,.1);color:var(--accent);border:1px solid rgba(0,200,240,.2)}
.badge-gpl{background:rgba(0,217,140,.1);color:var(--green);border:1px solid rgba(0,217,140,.2)}
.badge-pro{background:rgba(167,139,250,.1);color:var(--purple);border:1px solid rgba(167,139,250,.2)}
.badge-oss{background:rgba(255,255,255,.05);color:var(--muted);border:1px solid var(--border)}
.product-desc{font-size:14px;color:var(--muted);line-height:1.65;font-weight:300}
.product-features{display:flex;flex-direction:column;gap:7px}
.product-feature{font-size:13px;color:var(--muted);display:flex;align-items:flex-start;gap:8px;line-height:1.5}
.product-feature::before{content:'—';color:var(--dim);flex-shrink:0;font-family:var(--mono);margin-top:1px}
.product-endpoints{background:#070910;border-radius:var(--r);padding:14px;font-family:var(--mono);font-size:11.5px;line-height:2;border:1px solid rgba(255,255,255,.06)}
.ep-method{font-weight:500;margin-right:6px}
.ep-get{color:var(--green)}
.ep-post{color:var(--amber)}
.ep-path{color:#7a9ab5}
.ep-comment{color:var(--dim)}
.product-link{font-family:var(--mono);font-size:12px;color:var(--muted);display:inline-flex;align-items:center;gap:5px;transition:color .15s}
.product-link:hover{color:var(--text)}
/* api */
.api-section{background:var(--surface)}
.api-layout{display:grid;grid-template-columns:1fr 1.7fr;gap:60px;align-items:flex-start}
.api-tabs{display:flex;flex-direction:column;gap:4px;margin-top:28px}
.api-tab{padding:10px 14px;border-radius:var(--r);cursor:pointer;transition:all .15s;border:1px solid transparent}
.api-tab-name{font-family:var(--mono);font-size:13px;color:var(--muted);transition:color .15s;margin-bottom:2px}
.api-tab-desc{font-size:12px;color:var(--dim)}
.api-tab:hover .api-tab-name{color:var(--text)}
.api-tab.active{background:var(--surface2);border-color:var(--border)}
.api-tab.active .api-tab-name{color:var(--accent)}
.api-tab.active .api-tab-desc{color:var(--muted)}
.api-code-panel{background:#07090e;border:1px solid rgba(255,255,255,.08);border-radius:var(--r2);overflow:hidden}
.api-code-header{background:#0b0e17;border-bottom:1px solid rgba(255,255,255,.06);padding:10px 16px;display:flex;align-items:center;justify-content:space-between}
.api-code-path{font-family:var(--mono);font-size:11.5px;color:var(--muted)}
.api-code-lang{font-family:var(--mono);font-size:10px;color:var(--dim);text-transform:uppercase;letter-spacing:.08em}
.api-code-body{padding:20px;font-family:var(--mono);font-size:12.5px;line-height:1.85;min-height:300px}
.code-panel{display:none}
.code-panel.active{display:block}
/* connectors */
.connectors{background:var(--bg)}
.connector-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.connector-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r2);padding:22px;transition:border-color .2s,transform .2s}
.connector-card:hover{border-color:var(--border2);transform:translateY(-1px)}
.connector-icon{width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;margin-bottom:13px}
.ci-discovery{background:rgba(0,200,240,.1)}
.ci-vuln{background:rgba(255,90,110,.1)}
.ci-cmms{background:rgba(240,160,48,.1)}
.ci-siem{background:rgba(167,139,250,.1)}
.ci-threat{background:rgba(0,217,140,.1)}
.ci-webhook{background:rgba(255,90,110,.08)}
.connector-type{font-family:var(--mono);font-size:10px;color:var(--accent);letter-spacing:.1em;text-transform:uppercase;margin-bottom:5px}
.connector-name{font-size:15px;font-weight:500;color:var(--text);margin-bottom:6px}
.connector-desc{font-size:13px;color:var(--muted);line-height:1.55;font-weight:300}
.connector-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:12px}
.connector-tag{font-family:var(--mono);font-size:10px;color:var(--dim);padding:2px 7px;border:1px solid var(--border);border-radius:3px}
/* deploy */
.deploy{background:var(--bg2)}
.deploy-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:28px}
.deploy-step{padding:28px;background:var(--surface);border:1px solid var(--border);border-radius:var(--r2)}
.step-num{font-family:var(--serif);font-style:italic;font-size:64px;color:var(--dim);line-height:1;margin-bottom:14px;display:block}
.step-title{font-size:17px;font-weight:500;color:var(--text);margin-bottom:8px}
.step-desc{font-size:14px;color:var(--muted);line-height:1.65;font-weight:300;margin-bottom:16px}
.step-code{background:#07090e;border:1px solid rgba(255,255,255,.07);border-radius:var(--r);padding:14px;font-family:var(--mono);font-size:12px;line-height:1.75}
.step-prompt{color:var(--accent)}
.step-cmd{color:#bfd4e8}
.step-out{color:var(--green)}
.step-cmt{color:var(--dim)}
/* rbac */
.rbac{background:var(--surface)}
.rbac-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.role-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--r2);padding:22px;transition:border-color .2s}
.role-card:hover{border-color:var(--border2)}
.role-icon{width:40px;height:40px;border-radius:10px;margin-bottom:14px;display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:12px;font-weight:500}
.ri-viewer{background:rgba(100,130,160,.12);color:#7a9ab5}
.ri-editor{background:rgba(0,200,240,.1);color:var(--accent)}
.ri-biomed{background:rgba(0,217,140,.1);color:var(--green)}
.ri-admin{background:rgba(255,90,110,.1);color:var(--coral)}
.role-name{font-family:var(--mono);font-size:13px;font-weight:500;color:var(--text);margin-bottom:6px}
.role-desc{font-size:13px;color:var(--muted);line-height:1.6;font-weight:300;margin-bottom:13px}
.role-perms{display:flex;flex-direction:column;gap:5px}
.role-perm{font-family:var(--mono);font-size:10.5px;color:var(--dim);display:flex;align-items:center;gap:6px}
.role-perm::before{content:'✓';color:var(--green);font-size:10px}
/* research */
.research{background:var(--bg);border-top:1px solid var(--border);border-bottom:1px solid var(--border)}
.research-inner{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center}
.research-kicker{font-family:var(--mono);font-size:10px;color:var(--amber);letter-spacing:.12em;text-transform:uppercase;margin-bottom:10px;display:flex;align-items:center;gap:8px}
.research-kicker::before{content:'';display:inline-block;width:18px;height:1px;background:var(--amber)}
.research-title{font-family:var(--serif);font-style:italic;font-size:clamp(24px,2.8vw,36px);color:#edf2fa;line-height:1.2;margin-bottom:16px}
.research-body{font-size:15px;color:var(--muted);line-height:1.72;font-weight:300;margin-bottom:28px}
.research-stat{padding:16px 20px;background:var(--surface);border:1px solid var(--border);border-left:2px solid var(--amber);border-radius:var(--r);margin-bottom:10px}
.research-stat-label{font-family:var(--mono);font-size:10px;color:var(--amber);letter-spacing:.08em;text-transform:uppercase;margin-bottom:4px}
.research-stat-value{font-size:13.5px;color:var(--text);font-weight:300;line-height:1.55}
/* pioneers */
.pioneers{background:var(--bg);padding:80px 0}
.pioneers-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:40px}
.pioneer-item{padding:22px;background:var(--surface);border:1px solid var(--border);border-radius:var(--r2)}
.pioneer-label{font-family:var(--mono);font-size:10px;color:var(--accent);letter-spacing:.1em;text-transform:uppercase;margin-bottom:8px}
.pioneer-text{font-size:13.5px;color:var(--muted);line-height:1.65;font-weight:300}
/* access */
.access{background:var(--surface)}
.access-inner{display:grid;grid-template-columns:1.1fr 1fr;gap:80px;align-items:flex-start}
.access-form-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--r2);padding:32px}
.form-title{font-size:17px;font-weight:500;color:var(--text);margin-bottom:5px}
.form-sub{font-size:14px;color:var(--muted);margin-bottom:24px;font-weight:300;line-height:1.6}
.form-group{margin-bottom:14px}
.form-label{display:block;font-family:var(--mono);font-size:10.5px;color:var(--muted);letter-spacing:.06em;margin-bottom:6px}
.form-input,.form-select{width:100%;background:var(--surface2);border:1px solid var(--border2);border-radius:var(--r);padding:10px 14px;font-family:var(--sans);font-size:14px;color:var(--text);transition:border-color .15s;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}
.form-input:focus,.form-select:focus{border-color:rgba(0,200,240,.4)}
.form-input::-moz-placeholder{color:var(--dim)}
.form-input::placeholder{color:var(--dim)}
.form-select{cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%235c7080' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center}
.form-select option{background:#101420}
.form-submit{width:100%;margin-top:6px;padding:12px;font-size:15px}
#form-success{display:none;text-align:center;padding:24px 0}
/* footer */
footer{background:var(--bg);border-top:1px solid var(--border);padding:48px 0 32px}
.footer-inner{max-width:var(--max);margin:0 auto;padding:0 24px}
.footer-top{display:grid;grid-template-columns:1.5fr repeat(3,1fr);gap:48px;margin-bottom:40px}
.footer-brand p{font-size:13px;color:var(--muted);line-height:1.65;margin-top:12px;font-weight:300;max-width:260px}
.footer-col-title{font-family:var(--mono);font-size:11px;color:var(--text);letter-spacing:.06em;margin-bottom:14px}
.footer-links{list-style:none;display:flex;flex-direction:column;gap:9px}
.footer-links a{font-size:13px;color:var(--muted);transition:color .15s}
.footer-links a:hover{color:var(--text)}
.footer-bottom{border-top:1px solid var(--border);padding-top:24px;display:flex;align-items:center;justify-content:space-between}
.footer-copy{font-family:var(--mono);font-size:11px;color:var(--dim)}
.footer-legal{display:flex;gap:20px}
.footer-legal a{font-family:var(--mono);font-size:11px;color:var(--dim);transition:color .15s}
.footer-legal a:hover{color:var(--muted)}
/* reveal */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .6s ease,transform .6s ease}
.reveal.visible{opacity:1;transform:none}
.reveal-delay-1{transition-delay:.1s}
.reveal-delay-2{transition-delay:.2s}
.reveal-delay-3{transition-delay:.3s}
/* access feature list */
.access-features{display:flex;flex-direction:column;gap:10px;margin-top:28px}
/* responsive */
@media(max-width:1000px){
.hero-inner{grid-template-columns:1fr;gap:40px}
.products-grid{grid-template-columns:1fr}
.api-layout{grid-template-columns:1fr}
.connector-grid{grid-template-columns:repeat(2,1fr)}
.deploy-steps{grid-template-columns:1fr}
.rbac-grid{grid-template-columns:repeat(2,1fr)}
.research-inner{grid-template-columns:1fr}
.access-inner{grid-template-columns:1fr}
.pioneers-grid{grid-template-columns:1fr}
.footer-top{grid-template-columns:1fr 1fr}
.nav-links{display:none}
}
@media(max-width:600px){
.rbac-grid{grid-template-columns:1fr}
.connector-grid{grid-template-columns:1fr}
.footer-top{grid-template-columns:1fr}
.hero-meta{gap:12px}
}
</style>
</head>
<body>
<!-- NAV -->
<nav id="nav">
<div class="nav-inner">
<a href="#home" class="nav-logo">
<span class="nav-logo-name">VIRTA LABS™</span>
<span class="nav-logo-sub">OpenSecOps</span>
</a>
<ul class="nav-links">
<li><a href="#platform">Platform</a></li>
<li><a href="#api">API</a></li>
<li><a href="#connectors">Connectors</a></li>
<li><a href="#research">Research</a></li>
<li><a href="#access">Access</a></li>
</ul>
<div class="nav-cta">
<a href="https://github.com/virtalabs/blueflow" target="_blank" class="nav-gh">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
GitHub
</a>
<a href="#access" class="btn btn-primary" style="padding:8px 18px;font-size:13px">Request Access</a>
</div>
</div>
</nav>
<!-- HERO -->
<section class="hero" id="home">
<div class="hero-inner">
<div>
<div class="hero-badge reveal">ARPA-H Funded · NSF SBIR · Open Source</div>
<h1 class="hero-headline reveal reveal-delay-1">
Open Security<br>for <em>Connected</em><br>Care.
</h1>
<p class="hero-sub reveal reveal-delay-2">
API-first security platform for healthcare infrastructure.
<strong>BlueFlow</strong> asset management, <strong>Tapirx</strong> passive device discovery,
and <strong>VulnFWRD™</strong> AI risk orchestration —
MIT-licensed open core you can inspect, extend, and deploy on your own terms.
</p>
<div class="hero-actions reveal reveal-delay-2">
<a href="#access" class="btn btn-primary btn-lg">Request Access →</a>
<a href="#platform" class="btn btn-ghost btn-lg">Explore Platform</a>
</div>
<div class="hero-meta reveal reveal-delay-3">
<div class="hero-meta-item">MIT Open Core</div>
<div class="hero-meta-item">FDA SBOM Ready</div>
<div class="hero-meta-item">NIST CSF Aligned</div>
<div class="hero-meta-item">Self-hosted option</div>
</div>
</div>
<div class="reveal reveal-delay-2">
<div class="terminal">
<div class="term-header">
<div class="term-dot"></div>
<div class="term-dot"></div>
<div class="term-dot"></div>
<span class="term-title">blueflow — api explorer</span>
</div>
<div class="term-body" id="terminal-body"></div>
</div>
</div>
</div>
</section>
<!-- STACK STRIP -->
<div class="stack-strip">
<div class="stack-inner">
<span class="stack-label">Stack</span>
<div class="stack-items">
<span class="stack-item">Python 3.12+</span>
<span class="stack-item">Django · DRF</span>
<span class="stack-item">PostgreSQL 16</span>
<span class="stack-item">Celery · Redis</span>
<span class="stack-item">OpenAPI 3 · drf-spectacular</span>
<span class="stack-item">Docker Compose</span>
<span class="stack-item">uv</span>
<span class="stack-item">HL7 · DICOM</span>
<span class="stack-item">Go (Tapirx)</span>
<span class="stack-item">GitHub Actions CI</span>
</div>
</div>
</div>
<!-- PLATFORM / PRODUCTS -->
<section class="products" id="platform">
<div class="wrap">
<div class="section-header">
<div class="section-label reveal">Platform</div>
<h2 class="section-title reveal reveal-delay-1">Four tools. One platform.</h2>
<p class="section-body reveal reveal-delay-2">Use independently or together. Each component exposes a versioned REST API and connects via the pluggable connector framework — designed for maximum flexibility with no vendor lock-in.</p>
</div>
<div class="products-grid">
<!-- BLUEFLOW -->
<div class="product-card card-blueflow reveal">
<div class="product-head">
<div>
<div class="product-name">BlueFlow™</div>
<div class="product-desc-short">Open-core asset platform</div>
</div>
<div class="product-badges">
<span class="badge" style="background:rgba(0,217,140,.12);color:var(--green);border:1px solid rgba(0,217,140,.25)">Open Source</span>
<span class="badge badge-mit">MIT</span>
<span class="badge badge-oss">Python / Django</span>
</div>
</div>
<p class="product-desc">Now free and open source. Django REST API for healthcare IT asset management. Versioned API at <code style="font-family:var(--mono);font-size:12px;color:var(--accent)">/api/v1/</code> with full OpenAPI 3 schema, pluggable connector framework, SBOM generation, and role-based access control. Deploy with Docker Compose or install as a Python package.</p>
<div class="product-features">
<div class="product-feature">Connector plugin framework — discovery, vuln, CMMS, SIEM, webhooks</div>
<div class="product-feature">SBOM generation in SPDX and CycloneDX formats for FDA compliance</div>
<div class="product-feature">Built-in RBAC: viewer, editor, biomed, security admin</div>
<div class="product-feature">Full Docker Compose stack — web, worker, beat, Postgres, Redis</div>
<div class="product-feature">Audit trail via django-simple-history on every model</div>
</div>
<div class="product-endpoints">
<div><span class="ep-method ep-get">GET</span><span class="ep-path">/api/v1/assets/</span></div>
<div><span class="ep-method ep-post">POST</span><span class="ep-path">/api/v1/assets/<id>/sbom/</span></div>
<div><span class="ep-method ep-post">POST</span><span class="ep-path">/api/v1/webhooks/</span></div>
<div><span class="ep-method ep-post">POST</span><span class="ep-path">/api/v1/connectors/<id>/sync/</span></div>
<div><span class="ep-method ep-get">GET</span><span class="ep-path">/api/v1/schema/</span><span class="ep-comment"> → OpenAPI 3</span></div>
</div>
<a href="https://github.com/virtalabs/blueflow" target="_blank" class="product-link">View on GitHub →</a>
</div>
<!-- TAPIRX -->
<div class="product-card card-tapirx reveal reveal-delay-1">
<div class="product-head">
<div>
<div class="product-name">Tapirx™</div>
<div class="product-desc-short">Passive device discovery</div>
</div>
<div class="product-badges">
<span class="badge badge-gpl">GPL-3.0</span>
<span class="badge badge-oss">Go</span>
</div>
</div>
<p class="product-desc">Free, open-source medical device discovery written in Go. Passively identifies devices from HL7 and DICOM network traffic via SPAN port, live interface, or pcap file — with zero impact on clinical operations. Plugs into BlueFlow as a discovery-type connector.</p>
<div class="product-features">
<div class="product-feature">Protocols: HL7 ADT/PRT (UDI extraction) and DICOM</div>
<div class="product-feature">Runs on Linux, macOS, Windows — no network disruption</div>
<div class="product-feature">SPAN port, live capture, or pcap file input with BPF filtering</div>
<div class="product-feature">MAC-keyed asset upsert with provenance and last-seen timestamps</div>
<div class="product-feature">CSV output or direct POST to BlueFlow discovery connector</div>
</div>
<div class="product-endpoints">
<div style="font-family:var(--mono);font-size:11.5px;color:#4a6a80;">$ tapirx -iface eth0 \</div>
<div style="font-family:var(--mono);font-size:11.5px;color:#4a6a80;padding-left:12px;">-apiurl http://bf:8000/api/v1/assets/</div>
<div style="margin-top:6px;font-family:var(--mono);font-size:11.5px;"><span style="color:var(--green);">→</span> <span style="color:#5c7080;">Infuse-O-Matic Peach B+</span></div>
<div style="font-family:var(--mono);font-size:11.5px;"><span style="color:var(--green);">→</span> <span style="color:#5c7080;">POST /api/v1/assets/ 201 Created</span></div>
</div>
<a href="https://github.com/virtalabs/tapirx" target="_blank" class="product-link">View on GitHub →</a>
</div>
<!-- GURNEY -->
<div class="product-card card-gurney reveal">
<div class="product-head">
<div>
<div class="product-name">Gurney</div>
<div class="product-desc-short">Clinical testbed scanner</div>
</div>
<div class="product-badges">
<span class="badge" style="background:rgba(0,217,140,.12);color:var(--green);border:1px solid rgba(0,217,140,.25)">Open Source</span>
<span class="badge badge-oss">Python</span>
</div>
</div>
<p class="product-desc">Reproducible, self-contained test environment that exercises BlueFlow's passive (pcap/protocol observation) and active (Nessus/Tenable-backed) scanning pipelines — topology- and scenario-driven, runs via Docker Compose.</p>
<div class="product-features">
<div class="product-feature">Topology-based environments: networks, nodes, healthchecks, dependencies</div>
<div class="product-feature">Scenario-driven runs — one topology can back many test scenarios</div>
<div class="product-feature">Exercises both passive pcap/protocol observation and active scanning</div>
<div class="product-feature">NDJSON machine-readable output for CI integration</div>
<div class="product-feature">Requires Python ≥ 3.11, Docker Engine, and uv</div>
</div>
<div class="product-endpoints">
<div style="font-family:var(--mono);font-size:11.5px;color:#4a6a80;"><span style="color:var(--accent)">$</span> gurney list</div>
<div style="font-family:var(--mono);font-size:11.5px;color:#4a6a80;margin-top:4px;"><span style="color:var(--accent)">$</span> gurney run blueflow-local/smoke-docker</div>
<div style="margin-top:6px;font-family:var(--mono);font-size:11.5px;"><span style="color:var(--amber);">→</span> <span style="color:#5c7080;">{"event":"completed","command":"run"}</span></div>
</div>
<a href="https://github.com/virtalabs/gurney" target="_blank" class="product-link">View on GitHub →</a>
</div>
<!-- VULNFWRD -->
<div class="product-card card-vulnfwrd reveal reveal-delay-2">
<div class="product-head">
<div>
<div class="product-name">VulnFWRD™</div>
<div class="product-desc-short">AI risk orchestration</div>
</div>
<div class="product-badges">
<span class="badge badge-pro">Proprietary</span>
</div>
</div>
<p class="product-desc">AI-powered risk orchestration with bidirectional BlueFlow integration. BlueFlow emits structured risk events when vulnerabilities map to assets or Pulse feed items match tracked devices. VulnFWRD returns scored remediation intents — the full closed-loop for healthcare vulnerability management.</p>
<div class="product-features">
<div class="product-feature">Bidirectional integration via connector plugin framework</div>
<div class="product-feature">AI risk scoring with NVD, EPSS, CISA KEV, and asset criticality</div>
<div class="product-feature">Remediation intents returned as actionable BlueFlow alerts</div>
<div class="product-feature">Custom stakeholder dashboards per role</div>
<div class="product-feature">Policy engine and workflow automation via webhooks</div>
</div>
<div class="product-endpoints">
<div><span class="ep-method" style="color:var(--purple);font-weight:500;margin-right:6px;">POST</span><span class="ep-path">/api/v1/intents/</span><span class="ep-comment"> ← risk event in</span></div>
<div><span class="ep-method ep-get">GET</span><span class="ep-path">/api/v1/pulse/</span><span class="ep-comment"> ← threat feed</span></div>
<div style="margin-top:8px;font-family:var(--mono);font-size:11px;color:var(--dim);line-height:1.75;">
{ "event_type": "vulnerability_mapped",<br>
"cve_id": "CVE-2024-1234",<br>
"epss_score": 0.87 }
</div>
</div>
<a href="#access" class="product-link">Request Access →</a>
</div>
</div>
</div>
</section>
<!-- API -->
<section class="api-section" id="api">
<div class="wrap">
<div class="api-layout">
<div>
<div class="section-label reveal">API Reference</div>
<h2 class="section-title reveal reveal-delay-1">Versioned.<br>Documented.<br>Complete.</h2>
<p class="section-body reveal reveal-delay-2">Every endpoint lives at <code style="font-family:var(--mono);font-size:13px;color:var(--accent)">/api/v1/</code> with full OpenAPI 3 schema auto-generated by drf-spectacular. Swagger UI served at <code style="font-family:var(--mono);font-size:13px;color:var(--accent)">/api/v1/schema/ui/</code>.</p>
<div class="api-tabs reveal reveal-delay-3">
<div class="api-tab active" data-tab="assets">
<div class="api-tab-name">Assets & SBOM</div>
<div class="api-tab-desc">Inventory, MAC-keyed upsert, FDA SBOM generation</div>
</div>
<div class="api-tab" data-tab="risk">
<div class="api-tab-name">Risk & Vulnerabilities</div>
<div class="api-tab-desc">CVE tracking, Pulse feed, VulnFWRD intents</div>
</div>
<div class="api-tab" data-tab="connectors">
<div class="api-tab-name">Connectors & Webhooks</div>
<div class="api-tab-desc">Plugin sync, generalized webhook jobs</div>
</div>
<div class="api-tab" data-tab="schema">
<div class="api-tab-name">Schema & Discovery</div>
<div class="api-tab-desc">OpenAPI 3, Swagger UI, autocomplete</div>
</div>
</div>
</div>
<div class="reveal reveal-delay-2">
<div class="api-code-panel">
<div class="api-code-header">
<span class="api-code-path" id="api-code-path">GET /api/v1/assets/ · POST /api/v1/assets/<id>/sbom/</span>
<span class="api-code-lang">HTTP · JSON</span>
</div>
<div class="api-code-body">
<div class="code-panel active" id="panel-assets">
<span style="color:var(--green);font-weight:500">GET</span> <span style="color:#b8cfe4">/api/v1/assets/?network=ICU-Floor-3</span>
<span style="color:var(--dim)">Authorization: Token sk-bf-••••••••</span>
<span style="color:var(--green)">200 OK</span>
<span style="color:var(--purple)">{</span>
<span style="color:var(--purple)">"count"</span><span style="color:var(--muted)">:</span> <span style="color:var(--amber)">1847</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"results"</span><span style="color:var(--muted)">: [{</span>
<span style="color:var(--purple)">"name"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"Infuse-O-Matic Peach B+"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"mac_address"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"00:03:b1:b5:b6:48"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"last_seen"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"2026-03-18T09:14:22Z"</span>
<span style="color:var(--muted)">}]</span>
<span style="color:var(--purple)">}</span>
<span style="color:var(--amber);font-weight:500">POST</span> <span style="color:#b8cfe4">/api/v1/assets/a3f1b2c4/sbom/</span>
<span style="color:var(--muted)">{ "format": "cyclonedx" }</span>
<span style="color:var(--green)">201 Created</span>
<span style="color:var(--purple)">{</span> <span style="color:var(--purple)">"format"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"cyclonedx"</span><span style="color:var(--muted)">,</span> <span style="color:var(--purple)">"components"</span><span style="color:var(--muted)">:</span> <span style="color:var(--amber)">47</span> <span style="color:var(--purple)">}</span>
</div>
<div class="code-panel" id="panel-risk">
<span style="color:var(--green);font-weight:500">GET</span> <span style="color:#b8cfe4">/api/v1/vulnerabilities/?asset=a3f1b2c4</span>
<span style="color:var(--green)">200 OK</span>
<span style="color:var(--muted)">[{</span>
<span style="color:var(--purple)">"cve_id"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"CVE-2024-1234"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"epss_score"</span><span style="color:var(--muted)">:</span> <span style="color:var(--amber)">0.87</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"cvss"</span><span style="color:var(--muted)">:</span> <span style="color:var(--amber)">9.1</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"kev"</span><span style="color:var(--muted)">:</span> <span style="color:var(--amber)">true</span>
<span style="color:var(--muted)">}]</span>
<span style="color:var(--amber);font-weight:500">POST</span> <span style="color:#b8cfe4">/api/v1/intents/</span>
<span style="color:var(--dim)">// Risk event → VulnFWRD™</span>
<span style="color:var(--purple)">{</span>
<span style="color:var(--purple)">"event_type"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"vulnerability_mapped"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"cve_id"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"CVE-2024-1234"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"network_segment"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"ICU-Floor-3"</span>
<span style="color:var(--purple)">}</span>
</div>
<div class="code-panel" id="panel-connectors">
<span style="color:var(--amber);font-weight:500">POST</span> <span style="color:#b8cfe4">/api/v1/connectors/nessus-prod/sync/</span>
<span style="color:var(--green)">202 Accepted</span>
<span style="color:var(--purple)">{</span> <span style="color:var(--purple)">"task_id"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"8f3a2c1d-..."</span> <span style="color:var(--purple)">}</span>
<span style="color:var(--amber);font-weight:500">POST</span> <span style="color:#b8cfe4">/api/v1/webhooks/</span>
<span style="color:var(--purple)">{</span>
<span style="color:var(--purple)">"connector_id"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"viper-prod"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"callback"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"https://viper.example/cb"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"since"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"2026-03-01T00:00:00Z"</span>
<span style="color:var(--purple)">}</span>
<span style="color:var(--green)">202 Accepted</span>
<span style="color:var(--purple)">{</span> <span style="color:var(--purple)">"request_id"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"7d8e9f0a-..."</span> <span style="color:var(--purple)">}</span>
</div>
<div class="code-panel" id="panel-schema">
<span style="color:var(--green);font-weight:500">GET</span> <span style="color:#b8cfe4">/api/v1/schema/</span>
<span style="color:var(--dim)">Accept: application/vnd.oai.openapi+json</span>
<span style="color:var(--green)">200 OK</span> <span style="color:var(--dim)">openapi: 3.1.0</span>
<span style="color:var(--purple)">{</span>
<span style="color:var(--purple)">"openapi"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"3.1.0"</span><span style="color:var(--muted)">,</span>
<span style="color:var(--purple)">"info"</span><span style="color:var(--muted)">: {</span> <span style="color:var(--purple)">"title"</span><span style="color:var(--muted)">:</span> <span style="color:var(--green)">"BlueFlow API"</span><span style="color:var(--muted)">, "version":</span> <span style="color:var(--green)">"1"</span> <span style="color:var(--muted)">},</span>
<span style="color:var(--purple)">"paths"</span><span style="color:var(--muted)">: { ... }</span>
<span style="color:var(--purple)">}</span>
<span style="color:var(--dim)">// Swagger UI available at:</span>
<span style="color:var(--green);font-weight:500">GET</span> <span style="color:var(--accent)">/api/v1/schema/ui/</span>
<span style="color:var(--dim)">// Generate with management command:</span>
<span style="color:var(--dim)">$ python manage.py spectacular --validate</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- CONNECTORS -->
<section class="connectors" id="connectors">
<div class="wrap">
<div class="section-header">
<div class="section-label reveal">Connector Plugin Framework</div>
<h2 class="section-title reveal reveal-delay-1">Every integration, one interface.</h2>
<p class="section-body reveal reveal-delay-2">Each connector implements <code style="font-family:var(--mono);font-size:14px;color:var(--accent)">ConnectorBase</code> — standard <code style="font-family:var(--mono);font-size:13px;color:var(--accent)">pull()</code>, <code style="font-family:var(--mono);font-size:13px;color:var(--accent)">push()</code>, and <code style="font-family:var(--mono);font-size:13px;color:var(--accent)">validate_credentials()</code> methods with Celery task binding. Trigger any connector on-demand via <code style="font-family:var(--mono);font-size:13px;color:var(--accent)">POST /api/v1/connectors/<id>/sync/</code> or schedule with Celery Beat.</p>
</div>
<div class="connector-grid">
<div class="connector-card reveal">
<div class="connector-icon ci-discovery">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
</div>
<div class="connector-type">Discovery</div>
<div class="connector-name">Passive Network Discovery</div>
<p class="connector-desc">Identifies medical devices from HL7 and DICOM traffic without active scanning or any network disruption. SPAN port or pcap input.</p>
<div class="connector-tags">
<span class="connector-tag">Tapirx</span><span class="connector-tag">SPAN port</span><span class="connector-tag">HL7</span><span class="connector-tag">DICOM</span><span class="connector-tag">pcap</span>
</div>
</div>
<div class="connector-card reveal reveal-delay-1">
<div class="connector-icon ci-vuln">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--coral)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<div class="connector-type">Vulnerability Scanner</div>
<div class="connector-name">Safe Vulnerability Scanning</div>
<p class="connector-desc">Safe scanning workflows that guard active medical devices. CVE cross-reference against NVD with EPSS and CISA KEV enrichment.</p>
<div class="connector-tags">
<span class="connector-tag">Nessus</span><span class="connector-tag">Qualys</span><span class="connector-tag">Nexpose</span><span class="connector-tag">nessrest</span>
</div>
</div>
<div class="connector-card reveal reveal-delay-2">
<div class="connector-icon ci-cmms">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--amber)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>
</div>
<div class="connector-type">CMMS</div>
<div class="connector-name">Maintenance System Sync</div>
<p class="connector-desc">Bidirectional sync with computerized maintenance management systems. Import existing device inventory; export scan scheduling and utilization data.</p>
<div class="connector-tags">
<span class="connector-tag">ServiceNow</span><span class="connector-tag">TMS</span><span class="connector-tag">REST import</span>
</div>
</div>
<div class="connector-card reveal">
<div class="connector-icon ci-siem">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--purple)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
</div>
<div class="connector-type">SIEM</div>
<div class="connector-name">Security Event Integration</div>
<p class="connector-desc">Push asset context and vulnerability events to SIEM platforms. Enrich alerts with device criticality, ePHI status, and network segment data.</p>
<div class="connector-tags">
<span class="connector-tag">Splunk</span><span class="connector-tag">QRadar</span><span class="connector-tag">Sentinel</span><span class="connector-tag">syslog</span>
</div>
</div>
<div class="connector-card reveal reveal-delay-1">
<div class="connector-icon ci-threat">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--green)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg>
</div>
<div class="connector-type">Threat Feed</div>
<div class="connector-name">Pulse™ Vulnerability Feed</div>
<p class="connector-desc">Virta Labs proprietary threat intelligence matched to your specific device inventory. NVD, CISA KEV, and EPSS enrichment for tracked assets.</p>
<div class="connector-tags">
<span class="connector-tag">Pulse™</span><span class="connector-tag">NVD</span><span class="connector-tag">CISA KEV</span><span class="connector-tag">EPSS</span>
</div>
</div>
<div class="connector-card reveal reveal-delay-2">
<div class="connector-icon ci-webhook">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--coral)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
</div>
<div class="connector-type">Webhook</div>
<div class="connector-name">Generalized Webhook Jobs</div>
<p class="connector-desc">Async paginated push to any subscriber. UUID job tracking, configurable page size, and full auditing. Powers the <a href="https://github.com/PATCH-UPGRADE/viper" target="_blank" style="color:var(--coral);text-decoration:none;border-bottom:1px solid rgba(255,90,110,.3)">VIPER VMP</a> vulnerability intelligence bridge.</p>
<div class="connector-tags">
<span class="connector-tag"><a href="https://github.com/PATCH-UPGRADE/viper" target="_blank" style="color:inherit;text-decoration:none">VIPER VMP</a></span><span class="connector-tag">Celery</span><span class="connector-tag">UUID jobs</span><span class="connector-tag">paginated</span>
</div>
</div>
</div>
</div>
</section>
<!-- DEPLOY -->
<section class="deploy" id="deploy">
<div class="wrap">
<div class="section-header">
<div class="section-label reveal">Deploy</div>
<h2 class="section-title reveal reveal-delay-1">From zero to secure in three steps.</h2>
</div>
<div class="deploy-steps">
<div class="deploy-step reveal">
<span class="step-num">01</span>
<div class="step-title">Deploy the platform</div>
<p class="step-desc">Full Docker Compose stack — web, Celery worker, Celery Beat, PostgreSQL, Redis. Auto-migration on container boot. Running in minutes.</p>
<div class="step-code">
<div><span class="step-cmt"># Clone and start the full stack</span></div>
<div><span class="step-prompt">$</span> <span class="step-cmd">git clone github.com/virtalabs/blueflow</span></div>
<div><span class="step-prompt">$</span> <span class="step-cmd">cp .env.example .env</span></div>
<div><span class="step-prompt">$</span> <span class="step-cmd">docker compose up -d</span></div>
<div> </div>
<div><span class="step-out">✓ postgres healthy</span></div>
<div><span class="step-out">✓ redis healthy</span></div>
<div><span class="step-out">✓ migrations applied</span></div>
<div><span class="step-out">✓ celery worker ready</span></div>
<div><span class="step-out">✓ web → localhost:8000</span></div>
</div>
</div>
<div class="deploy-step reveal reveal-delay-1">
<span class="step-num">02</span>
<div class="step-title">Discover your devices</div>
<p class="step-desc">Register connectors, deploy Tapirx on a SPAN port, trigger syncs via API. The safe-scanning guard protects active medical devices automatically.</p>
<div class="step-code">
<div><span class="step-cmt"># Start passive discovery</span></div>
<div><span class="step-prompt">$</span> <span class="step-cmd">tapirx -iface eth0 \</span></div>
<div style="padding-left:14px"><span class="step-cmd">-apiurl http://bf:8000/api/v1/assets/</span></div>
<div> </div>
<div><span class="step-out">→ Infuse-O-Matic Peach B+</span></div>
<div><span class="step-out">→ GE Dash 4000 Monitor</span></div>
<div><span class="step-out">→ Philips IntelliVue MP70</span></div>
<div><span class="step-out">→ 47 new assets · 12 updated</span></div>
</div>
</div>
<div class="deploy-step reveal reveal-delay-2">
<span class="step-num">03</span>
<div class="step-title">Orchestrate your defenses</div>
<p class="step-desc">Connect vulnerability scanners, configure the VulnFWRD bridge, enable webhook subscribers. Celery Beat runs scheduled connector syncs.</p>
<div class="step-code">
<div><span class="step-cmt"># Trigger Nessus connector sync</span></div>
<div><span class="step-prompt">$</span> <span class="step-cmd">curl -X POST \</span></div>
<div style="padding-left:14px"><span class="step-cmd">/api/v1/connectors/nessus/sync/</span></div>
<div><span class="step-out">202 { "task_id": "8f3a2c1d" }</span></div>
<div> </div>
<div><span class="step-cmt"># Generate FDA SBOM (CycloneDX)</span></div>
<div><span class="step-prompt">$</span> <span class="step-cmd">curl -X POST /api/v1/assets/</span></div>
<div style="padding-left:14px"><span class="step-cmd">a3f1/sbom/ -d '{"format":"spdx"}'</span></div>
<div><span class="step-out">201 { "components": 47 }</span></div>
</div>
</div>
</div>
</div>
</section>
<!-- RBAC -->
<section class="rbac" id="rbac">
<div class="wrap">
<div class="section-header" style="text-align:center">
<div class="section-label reveal" style="text-align:center">Access Control</div>
<h2 class="section-title reveal reveal-delay-1" style="margin:0 auto">Every role. Every team.</h2>
<p class="section-body reveal reveal-delay-2" style="margin:0 auto;text-align:center">Built-in RBAC with scoped API tokens. Permissions enforced at the ViewSet level on every endpoint. From read-only leadership dashboards to full security admin control.</p>
</div>
<div class="rbac-grid">
<div class="role-card reveal">
<div class="role-icon ri-viewer">RO</div>
<div class="role-name">Viewer</div>
<p class="role-desc">Read-only access for leadership and auditors. Export reports in JSON, CSV, SPDX, and CycloneDX formats.</p>
<div class="role-perms">
<div class="role-perm">GET all resources</div>
<div class="role-perm">Export CSV & SBOM</div>
<div class="role-perm">NIST CSF coverage view</div>
</div>
</div>
<div class="role-card reveal reveal-delay-1">
<div class="role-icon ri-editor">ED</div>
<div class="role-name">Editor</div>
<p class="role-desc">Create and update assets, groups, and tags. For IT teams managing day-to-day device inventory.</p>
<div class="role-perms">
<div class="role-perm">All Viewer permissions</div>
<div class="role-perm">POST/PATCH assets</div>
<div class="role-perm">Manage groups & tags</div>
</div>
</div>
<div class="role-card reveal reveal-delay-2">
<div class="role-icon ri-biomed">BM</div>
<div class="role-name">Biomed</div>
<p class="role-desc">Clinical engineering access. Scan management, SBOM generation, ePHI tracking, and maintenance scheduling.</p>
<div class="role-perms">
<div class="role-perm">All Editor permissions</div>
<div class="role-perm">Manage scans & alerts</div>
<div class="role-perm">Generate FDA SBOMs</div>
</div>
</div>
<div class="role-card reveal reveal-delay-3">
<div class="role-icon ri-admin">SA</div>
<div class="role-name">Security Admin</div>
<p class="role-desc">Full platform control. Connector management, webhook configuration, scoped API token issuance, and RBAC administration.</p>
<div class="role-perms">
<div class="role-perm">All Biomed permissions</div>
<div class="role-perm">Manage connectors</div>
<div class="role-perm">Issue scoped API tokens</div>
</div>
</div>
</div>
</div>
</section>
<!-- RESEARCH -->
<section class="research" id="research">
<div class="wrap">
<div class="research-inner">
<div>
<div class="research-kicker reveal">Active Research</div>
<h2 class="research-title reveal reveal-delay-1">Built on a decade of pioneering security research.</h2>
<p class="research-body reveal reveal-delay-2">Virta Labs cofounders co-authored the world's first research on cardiac implant cybersecurity in 2008. They shaped FDA medical device security guidance, led industry standards bodies, and introduced <strong style="color:var(--text)">PowerGuard™</strong> in 2015 — the NSF-funded malware detection system that identifies infected medical devices by analyzing power consumption patterns, requiring no software installation and causing zero disruption to patient care. Now funded by ARPA-H's UPGRADE program to build hospital-scale digital twins for autonomous vulnerability remediation.</p>
<div style="display:flex;gap:10px;flex-wrap:wrap;margin-top:20px" class="reveal reveal-delay-2">
<a href="https://www.secure-medicine.org/patch" target="_blank" rel="noopener noreferrer" class="btn btn-ghost" style="font-size:13px">PATCH Project →</a>
<a href="https://www.nsf.gov/impacts/cybersecurity" target="_blank" rel="noopener noreferrer" class="btn btn-ghost" style="font-size:13px">NSF PowerGuard →</a>
<a href="https://www.healthcareitnews.com/news/arpa-h-funds-digital-twin-tech-healthcare-cybersecurity" target="_blank" rel="noopener noreferrer" class="btn btn-ghost" style="font-size:13px">HealthcareIT News →</a>
</div>
</div>
<div class="reveal reveal-delay-1">
<div class="research-stat">
<div class="research-stat-label">ARPA-H UPGRADE Program</div>
<div class="research-stat-value">PATCH Project — up to $19M — hospital-scale digital twins for autonomous vulnerability discovery and remediation across thousands of medical devices while ensuring uninterrupted patient care.</div>
</div>
<div class="research-stat" style="border-left-color:var(--accent)">
<div class="research-stat-label" style="color:var(--accent)">Clinical Partners</div>
<div class="research-stat-value">Michigan Medicine · Massachusetts General Hospital · Beth Israel Deaconess Medical Center</div>
</div>
<div class="research-stat" style="border-left-color:var(--green)">
<div class="research-stat-label" style="color:var(--green)">Industry Partners</div>
<div class="research-stat-value">Medcrypt · ForAllSecure — open-source commercialization and vulnerability mitigation platform deployment across healthcare systems.</div>
</div>
</div>
</div>
</div>
</section>
<!-- PIONEERS -->
<section class="pioneers">
<div class="wrap">
<div class="section-label reveal">Built by the Pioneers</div>
<h2 class="section-title reveal reveal-delay-1" style="max-width:520px">The team that shaped the industry.</h2>
<div class="pioneers-grid">
<div class="pioneer-item reveal">
<div class="pioneer-label">Federal Advisory Experience</div>
<p class="pioneer-text">Former federal advisors who shaped national medical device security policies, standards, and regulatory frameworks at FDA, NIST, and HHS. Founded the category through pioneering research.</p>
</div>
<div class="pioneer-item reveal reveal-delay-1">
<div class="pioneer-label">Industry-Changing Research</div>
<p class="pioneer-text">Co-authored the first peer-reviewed research on cardiac implant cybersecurity. Exposed critical vulnerabilities and drove industry-wide security improvements across major device manufacturers.</p>
</div>
<div class="pioneer-item reveal reveal-delay-2">
<div class="pioneer-label">Federal-Validated Technology</div>
<p class="pioneer-text">Production-grade technology proven through NSF SBIR grants, ARPA-H funding, and enterprise deployments at major health systems across the United States.</p>
</div>
</div>
</div>
</section>
<!-- ACCESS -->
<section class="access" id="access">
<div class="wrap">
<div class="access-inner">
<div>
<div class="section-label reveal">Get Access</div>
<h2 class="section-title reveal reveal-delay-1">Take control of your security stack.</h2>
<p class="section-body reveal reveal-delay-2">Deploy locally. Own your data. Export anytime. We'll align VulnFWRD™ capabilities to your environment and share documentation.</p>
<div class="access-features reveal reveal-delay-2">
<div class="hero-meta-item">MIT-licensed open core — inspect, extend, deploy</div>
<div class="hero-meta-item">Full Docker Compose stack — production-ready in hours</div>
<div class="hero-meta-item">100% self-hosted option available</div>
<div class="hero-meta-item">No vendor lock-in — export all data at any time</div>
<div class="hero-meta-item">FDA SBOM generation — SPDX and CycloneDX</div>
<div class="hero-meta-item">NIST CSF coverage tracking built-in</div>
</div>
</div>
<div class="reveal reveal-delay-1">
<div class="access-form-card">
<div class="form-title">Request Access to VulnFWRD™</div>
<p class="form-sub">We'll align capabilities to your environment and share API documentation.</p>
<form id="access-form" onsubmit="handleSubmit(event)">
<div class="form-group">
<label class="form-label" for="email">Email Address</label>
<input type="email" id="email" class="form-input" placeholder="you@hospital.org" required>
</div>
<div class="form-group">
<label class="form-label" for="org">Organization</label>
<input type="text" id="org" class="form-input" placeholder="Health System Name">
</div>
<div class="form-group">
<label class="form-label" for="env">Environment Type</label>
<select id="env" class="form-select">
<option value="">Select your environment</option>
<option>Hospital / Health System</option>
<option>Independent HDO</option>
<option>Medical Device Manufacturer</option>
<option>Security Consultant</option>
<option>Research Institution</option>
<option>Federal / Government</option>
</select>
</div>
<div class="form-group">
<label class="form-label" for="usecase">Primary Use Case</label>
<select id="usecase" class="form-select">
<option value="">Select primary use case</option>
<option>Medical device inventory management</option>
<option>FDA SBOM compliance</option>
<option>Vulnerability management</option>
<option>Network segmentation</option>
<option>Incident response</option>
<option>Research / evaluation</option>
</select>
</div>
<button type="submit" class="btn btn-primary form-submit">Request Access →</button>
</form>
<div id="form-success">
<div style="font-size:32px;margin-bottom:12px;color:var(--green)">✓</div>
<div style="font-size:16px;color:var(--text);font-weight:500;margin-bottom:6px">Request received.</div>
<div style="font-size:14px;color:var(--muted)">We'll be in touch to align capabilities to your environment.</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- FOOTER -->
<footer>
<div class="footer-inner">
<div class="footer-top">
<div class="footer-brand">
<div class="nav-logo">
<span class="nav-logo-name">VIRTA LABS™</span>
<span class="nav-logo-sub">OpenSecOps</span>
</div>
<p>Open cyber-physical security built for builders. API-first vulnerability orchestration for connected care and critical infrastructure.</p>
</div>
<div>
<div class="footer-col-title">Platform</div>
<ul class="footer-links">
<li><a href="#platform">VulnFWRD™</a></li>
<li><a href="#platform">BlueFlow™</a></li>
<li><a href="https://github.com/virtalabs/tapirx" target="_blank">Tapirx™</a></li>
<li><a href="#api">API Documentation</a></li>
</ul>
</div>
<div>
<div class="footer-col-title">Resources</div>
<ul class="footer-links">
<li><a href="#deploy">How It Works</a></li>
<li><a href="https://github.com/virtalabs/blueflow" target="_blank">Open Source</a></li>
<li><a href="#research">Security Research</a></li>
<li><a href="#access">Contact Us</a></li>
</ul>
</div>
<div>
<div class="footer-col-title">Open Source</div>
<ul class="footer-links">
<li><a href="https://github.com/virtalabs/blueflow" target="_blank">BlueFlow on GitHub</a></li>
<li><a href="https://github.com/virtalabs/tapirx" target="_blank">Tapirx on GitHub</a></li>
<li><a href="https://github.com/virtalabs/gurney" target="_blank">Gurney on GitHub</a></li>
<li><a href="https://github.com/PATCH-UPGRADE/viper" target="_blank">VIPER VMP on GitHub</a></li>
<li><a href="https://github.com/virtalabs" target="_blank">Virta Labs Org</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<div class="footer-copy">© 2026 Virta Laboratories, Inc. All rights reserved.</div>
<div class="footer-legal">
<a href="#">Privacy Policy</a>
<a href="#">Terms of Service</a>
<a href="#">Security</a>
</div>
</div>
</div>
</footer>
<script>
// nav scroll
const navEl = document.getElementById('nav');
window.addEventListener('scroll', () => {
navEl.classList.toggle('scrolled', window.scrollY > 40);
}, { passive: true });
// scroll reveal
const observer = new IntersectionObserver(entries => {
entries.forEach(e => {
if (e.isIntersecting) {
e.target.classList.add('visible');
observer.unobserve(e.target);
}
});
}, { threshold: 0.08, rootMargin: '0px 0px -32px 0px' });
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
// terminal
const tb = document.getElementById('terminal-body');
const sequences = [
{ comment: 'list assets in ICU network', cmds: [
{ type:'cmd', text:'curl -s /api/v1/assets/ \\', delay:32 },
{ type:'flag', text:' -H "Authorization: Token sk-bf-••••" \\' },
{ type:'flag', text:' -G -d "network=ICU-Floor-3"' },
{ type:'blank' },
{ type:'ok', text:'HTTP/1.1 200 OK' },
{ type:'json', text:'{' },
{ type:'kv', key:'"count"', val:'1847', vt:'num' },
{ type:'kv', key:'"results"', val:'[{', vt:'punct' },
{ type:'nested', text:' "name": "Infuse-O-Matic Peach B+",' },
{ type:'nested', text:' "mac": "00:03:b1:b5:b6:48",' },
{ type:'nested', text:' "last_seen": "2026-03-18T09:14Z"' },
{ type:'json', text:'}]' }
]},
{ comment: 'generate FDA SBOM', cmds: [
{ type:'cmd', text:'curl -X POST /api/v1/assets/a3f1/sbom/ \\', delay:28 },
{ type:'flag', text:' -d \'{"format":"cyclonedx"}\'' },
{ type:'blank' },
{ type:'ok', text:'HTTP/1.1 201 Created' },
{ type:'json', text:'{' },
{ type:'kv', key:'"format"', val:'"cyclonedx"', vt:'str' },
{ type:'kv', key:'"components"', val:'47', vt:'num' },
{ type:'kv', key:'"status"', val:'"FDA_compliant"', vt:'str' },
{ type:'json', text:'}' }
]},
{ comment: 'trigger async webhook job', cmds: [
{ type:'cmd', text:'curl -X POST /api/v1/webhooks/ \\', delay:30 },
{ type:'flag', text:' -d \'{"connector_id":"viper-prod",' },
{ type:'flag', text:' "callback":"https://viper/cb"}\'' },
{ type:'blank' },
{ type:'ok', text:'HTTP/1.1 202 Accepted' },
{ type:'json', text:'{' },
{ type:'kv', key:'"request_id"', val:'"8f3a2c1d-..."', vt:'str' },
{ type:'kv', key:'"status"', val:'"queued"', vt:'str' },
{ type:'json', text:'}' }
]}
];
let si = 0, li = 0, ci = 0, curEl = null;
function mkLine(c) {
const s = document.createElement('span');
s.className = 'term-line';
if (c.type === 'blank') { s.innerHTML = ' '; return s; }
if (c.type === 'cmd') {
s.innerHTML = `<span class="term-prompt">$</span> <span class="term-cmd"></span>`;
return s;
}
if (c.type === 'flag') { s.innerHTML = `<span class="term-flag">${c.text}</span>`; return s; }
if (c.type === 'ok') { s.innerHTML = `<span class="term-ok">${c.text}</span>`; return s; }
if (c.type === 'json') { s.innerHTML = `<span class="term-punct">${c.text}</span>`; return s; }
if (c.type === 'kv') {
let v = c.vt === 'str' ? `<span class="term-str">${c.val}</span>` :
c.vt === 'num' ? `<span class="term-num">${c.val}</span>` :
`<span class="term-punct">${c.val}</span>`;
s.innerHTML = ` <span class="term-key">${c.key}</span><span class="term-punct">: </span>${v}<span class="term-punct">,</span>`;
return s;
}
if (c.type === 'nested') { s.innerHTML = ` <span class="term-nested">${c.text}</span>`; return s; }
return s;
}
function tick() {
const seq = sequences[si];
if (li >= seq.cmds.length) {
setTimeout(() => { tb.innerHTML = ''; li = 0; ci = 0; curEl = null; si = (si + 1) % sequences.length; addComment(); setTimeout(tick, 400); }, 3000);
return;
}
const cmd = seq.cmds[li];
if (cmd.type === 'cmd') {
if (!curEl) { curEl = mkLine(cmd); tb.appendChild(curEl); ci = 0; }
const el = curEl.querySelector('.term-cmd');
if (el && ci < cmd.text.length) {
el.textContent = cmd.text.substring(0, ci + 1);
ci++;
setTimeout(tick, (cmd.delay || 30) + Math.random() * 16);
} else {
curEl = null; ci = 0; li++;
setTimeout(tick, 100);
}
} else {
tb.appendChild(mkLine(cmd));
li++;
setTimeout(tick, cmd.type === 'blank' ? 40 : cmd.type === 'ok' ? 180 : 55);
}
}
function addComment() {
const c = document.createElement('span');
c.className = 'term-line';
c.innerHTML = `<span class="term-comment"> # ${sequences[si].comment}</span>`;
tb.appendChild(c);
const b = document.createElement('span');
b.className = 'term-line';
b.innerHTML = ' ';
tb.appendChild(b);
}
addComment();
setTimeout(tick, 900);
// api tabs
const tabPathMap = {
assets: 'GET /api/v1/assets/ · POST /api/v1/assets/<id>/sbom/',
risk: 'GET /api/v1/vulnerabilities/ · POST /api/v1/intents/',
connectors: 'POST /api/v1/connectors/<id>/sync/ · POST /api/v1/webhooks/',
schema: 'GET /api/v1/schema/ · GET /api/v1/schema/ui/'
};
document.querySelectorAll('.api-tab').forEach(tab => {
tab.addEventListener('click', () => {
const t = tab.dataset.tab;
document.querySelectorAll('.api-tab').forEach(x => x.classList.remove('active'));
document.querySelectorAll('.code-panel').forEach(x => x.classList.remove('active'));
tab.classList.add('active');
document.getElementById('panel-' + t).classList.add('active');
const cp = document.getElementById('api-code-path');
if (cp) cp.textContent = tabPathMap[t] || '';
});
});
// form
async function handleSubmit(e) {
e.preventDefault();
const btn = document.querySelector('#access-form button[type="submit"]');
btn.disabled = true;
btn.textContent = 'Submitting…';
const body = {
email: document.getElementById('email').value,
organization: document.getElementById('org').value,
environment: document.getElementById('env').value,
useCase: document.getElementById('usecase').value,
};
try {
const res = await fetch('/api/access-requests', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error('Server error');
document.getElementById('access-form').style.display = 'none';
document.getElementById('form-success').style.display = 'block';
} catch (err) {
btn.disabled = false;
btn.textContent = 'Request Access →';
alert('Something went wrong. Please try again.');
}
}
</script>
</body>
</html>
Sitemap
Кол-во: 0
XML-карта сайта для поисковиков
?
Sitemap.xml помогает поисковику быстрее находить и индексировать страницы. Особенно важен для крупных сайтов и новых страниц, на которые ещё нет входящих ссылок.
Robots.txt не содержит ссылку на карту сайта. Рекомендуется добавить карту сайта и указать ссылку на нее в robots.txt.
Внутренние ссылки
Не найдено
Ссылки на другие страницы своего сайта
?
Внутренние ссылки распределяют ссылочный вес между страницами и помогают поисковику обходить сайт. Пустые анкоры и ссылки на запрещённые robots.txt страницы — типичные ошибки.
Внутренних ссылок на странице 0 оптимально.
Внешние ссылки
Кол-во: 16
Ссылки на сторонние сайты
?
Исходящие внешние ссылки передают часть ссылочного веса на чужие сайты. Ссылки на авторитетные ресурсы безопасны; ссылки на мусорные сайты могут навредить репутации страницы.
Внешних ссылок на странице 16 слишком много. Спрячьте лишние ссылки в тег noindex или атрибут rel='nofollow'!
Показать внешние ссылки
| Url | Анкор | Анализировать |
|---|---|---|
| github.com |
<svg width="14" height="14" viewbox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg>
GitHub
|
Анализировать url |
| github.com |
View on GitHub →
|
Анализировать url |
| github.com |
View on GitHub →
|
Анализировать url |
| github.com |
View on GitHub →
|
Анализировать url |
| github.com |
VIPER VMP
|
Анализировать url |
| github.com |
VIPER VMP
|
Анализировать url |
| secure-medicine.org |
PATCH Project →
|
Анализировать url |
| nsf.gov |
NSF PowerGuard →
|
Анализировать url |
| healthcareitnews.com |
HealthcareIT News →
|
Анализировать url |
| github.com |
Tapirx™
|
Анализировать url |
| github.com |
Open Source
|
Анализировать url |
| github.com |
BlueFlow on GitHub
|
Анализировать url |
| github.com |
Tapirx on GitHub
|
Анализировать url |
| github.com |
Gurney on GitHub
|
Анализировать url |
| github.com |
VIPER VMP on GitHub
|
Анализировать url |
| github.com |
Virta Labs Org
|
Анализировать url |
Конкуренты Готовность: 0%
Конкуренты в Яндексе
Кол-во: 0
Топ сайтов-конкурентов в Яндексе
?
Сайты, чаще всего появляющиеся в ТОПе Яндекса по запросам из семантического ядра этой страницы.
Мы не нашли у вас конкурентов в Яндексе. Сайт или очень молодой или плохо продвигается.
Конкурентов в ТОП-10 Яндекса не нашлось.
Конкуренты в Google
Кол-во: 0
Топ сайтов-конкурентов в Google
?
Сайты, чаще всего появляющиеся в ТОПе Google по запросам из семантического ядра этой страницы.
Конкуренты в Google тоже не найдены. Займитесь продвижением сайта!
Конкурентов в ТОП-10 Google не нашлось.
ЗоЗПП: права потребителей Готовность: 100%
Нарушения
Не выявлены
Признаков дистанционной продажи товаров (интернет-магазина) не обнаружено — требования ЗоЗПП о раскрытии информации продавца к сайту не применяются. Нарушений нет.
ФЗ-149: рекомендательные технологии Готовность: 100%
Нарушения
Не выявлены
Рекомендательные блоки («с этим покупают», «похожие товары» и т.п.) на сайте не обнаружены — требования ст. 10.7 ФЗ-149 к сайту не применяются. Нарушений нет.
ФЗ-38: реклама Готовность: 100%
Нарушения
Не выявлены
Рекламных тематик с обязательными оговорками (медицина, БАД, кредиты и займы, новостройки) на сайте не обнаружено. Нарушений нет.
ФЗ-436: защита детей Готовность: 100%
Нарушения
Не выявлены
Признаков информационной продукции (новости, видео, книги, игры, курсы) не обнаружено — обязательная возрастная маркировка по ФЗ-436 сайту не требуется. Нарушений нет.
Вердикт
Выполнен подробный анализ сайта virtalabs.com: готовность на 68%. Чтобы выполнить все условия и попасть на первую страницу выдачи поисковых систем требуется:
Исправьте ошибки в мета-тегах.
Исправьте ошибки индексации.
Поделитесь с друзьями: