uniform_resource (table) Content
01JR7CRJTTV2K95SKKRFM8X07P | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/content-assembler/index.html | a09821bd95b821e11fd26412ee661d6ade810c92 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Content Assembler | surveilr","url":"https://www.surveilr.com/pattern/content-assembler/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/content-assembler/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/content-assembler/"><meta property="og:type" content="website"><meta property="og:title" content="Content Assembler | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/pattern/content-assembler/"><meta name="twitter:title" content="Content Assembler | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Content Assembler | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="23bfc20b-c08b-4a89-8fb6-9f9336216117" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="23bfc20b-c08b-4a89-8fb6-9f9336216117"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../pattern.html" class="c-breadcrumbs__link" aria-current="false"> Pattern </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Content Assembler </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/pattern/","name":"Pattern"}},{"@type":"ListItem","position":3,"item":{"@id":"/pattern/content-assembler/","name":"Content Assembler"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"></div> <section class="mx-auto flex max-w-[85rem] flex-col px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div> <p id="fadeText" class="mb-8 max-w-prose text-pretty font-light text-neutral-700 dark:text-neutral-300 sm:text-xl"> The Content Assembler Pattern is a comprehensive content curation, assembly, and distribution platform designed for marketing, SEO, and content automation. </p> </div> <div class="flex flex-col items-center justify-between space-y-4 sm:flex-row sm:space-y-0"> <div id="fadeInUp"> <h1 class="block text-4xl font-bold tracking-tighter text-neutral-800 dark:text-neutral-200 sm:text-5xl md:text-6xl lg:text-7xl"> Content Assembler </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> Content curation, assembly, and distribution platform </p> </div> <div> <img src="../../_astro/content-assembler-pattern.BdjZyCUW_Z1VVjrm.avif" id="fadeInMoveRight" alt="Content Assembler Pattern Workflow" loading="eager" width="6325" height="4781" decoding="async" class="w-[600px]"> </div> </div> </section> <div class="mx-auto max-w-[85rem] px-4 pt-10 sm:px-6 lg:px-8 lg:pt-14"> <nav class="mx-auto grid max-w-6xl gap-y-px sm:flex sm:gap-x-4 sm:gap-y-0" aria-label="Tabs" role="tablist"> <!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 active bg-neutral-100 hover:border-transparent dark:bg-white/[.05]" id="tabs-with-card-item-1" data-target="#tabs-with-card-1" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-orange-400 dark:text-orange-300"> Description </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-2" data-target="#tabs-with-card-2" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Capabilities </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-3" data-target="#tabs-with-card-3" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Screenshots </span> </button> </nav> <div class="mt-12 md:mt-16"> <div id="tabs-with-card-1" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid gap-12 md:grid-cols-2"> <div class="lg:w-3/4"> <h2 class="text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:leading-tight lg:text-4xl"> Content Assembler Pattern </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> Content Assembler Pattern provides a powerful, flexible framework for aggregating, curating, and distributing content across multiple platforms, with advanced SEO optimization and marketing automation integration. Suitable for businesses of any size looking to scale their content marketing efforts while maximizing audience engagement and traffic. It provides powerful tools to gather, organize, and distribute content across multiple platforms, while maximizing SEO benefits and audience engagement. </p> <p class="mt-5"> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="https://www.surveilr.com/pattern/content-assembler/package.sql"> Use the SQL <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 ml-1 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../../eg.surveilr.com/lib/pattern/content-assembler.html" target="_blank"> Live Demo <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> </p> </div> <div class="space-y-6 lg:space-y-10"> <div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Content Assembly & Curation </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Automatic content assembly from multiple sources and media types </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> RSS Feed Management </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Sourcing from RSS and social media feeds such as X / Twitter </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Automated Email Newsletter Ingestion </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Email Newsletter import from designated mailboxes </p> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-2" class="hidden" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid w-full grid-cols-1 gap-x-16 md:grid-cols-2"> <div class="max-w-md space-y-6"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div> </div> <div class="mt-6 space-y-6 md:ml-auto md:mt-0"> <div class="flex flex-col"> <div class="-m-1.5 overflow-x-auto"> <div class="inline-block min-w-full p-1.5 align-middle"> <div class="overflow-hidden"> <table class="min-w-full divide-y divide-neutral-300 dark:divide-neutral-700"> <thead> <tr> <th scope="col" class="px-6 py-3 text-start text-xs font-medium uppercase text-neutral-500 dark:text-neutral-500"> Capability </th><th scope="col" class="px-6 py-3 text-start text-xs font-medium uppercase text-neutral-500 dark:text-neutral-500"> Explanation </th> </tr> </thead> <tbody class="divide-y divide-neutral-300 dark:divide-neutral-700"> <tr> <td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Something </td><td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Description of something </td> </tr><tr> <td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Something </td><td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Description of something </td> </tr><tr> <td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Something </td><td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Description of something </td> </tr><tr> <td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Something </td><td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Description of something </td> </tr><tr> <td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Something </td><td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400"> Description of something </td> </tr> </tbody> </table> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"> <img src="../../_astro/blueprint-1.C3as_WJM_Z3Mdge.avif" alt="Blueprint Illustration" width="1920" height="1080" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <img src="../../_astro/blueprint-2.DSItIwt1_1sl0AH.avif" alt="Blueprint Illustration" width="1920" height="1080" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> </div> </div> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../../blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> <script type="module">document.addEventListener("DOMContentLoaded",function(){function d(t,e){if(t!==e){t.classList.remove("active","bg-neutral-100","hover:border-transparent","dark:bg-white/[.05]");const a=t.getAttribute("data-target");if(a){const n=document.querySelector(a);n&&n.classList.add("hidden")}o(t,["text-neutral-800","dark:text-neutral-200"],["text-orange-400","dark:text-orange-300"])}}function c(t){t.classList.add("active","bg-neutral-100",",hover:border-transparent","dark:bg-white/[.05]");const e=t.getAttribute("data-target");if(e){const a=document.querySelector(e);a&&a.classList.remove("hidden")}o(t,["text-orange-400","dark:text-orange-300"],["text-neutral-800","dark:text-neutral-200"])}function o(t,e,a){let n=t.querySelector("span");n&&(n.classList.remove(...a),n.classList.add(...e))}const r=document.querySelectorAll("[data-target]");r.length>0&&o(r[0],["text-orange-400","dark:text-orange-300"],[]),r.forEach(t=>{t.addEventListener("click",()=>{r.forEach(e=>d(e,t)),c(t)})})});</script> <script type="module" src="../../_astro/_...slug_.astro_astro_type_script_index_1_lang.DaSW5oKf.js"></script> | html | 69275 | 2025-04-07 05:49:51.249991381 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTTCJZY46686HXZ12HH | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/qualityfolio/index.html | f10708d46ce7fb2d320119876f7cb1308930bb92 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Qualityfolio | surveilr","url":"https://www.surveilr.com/pattern/qualityfolio/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/qualityfolio/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/qualityfolio/"><meta property="og:type" content="website"><meta property="og:title" content="Qualityfolio | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/pattern/qualityfolio/"><meta name="twitter:title" content="Qualityfolio | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Qualityfolio | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="e0445e3a-401f-41c0-a711-49a1a2494fb8" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="e0445e3a-401f-41c0-a711-49a1a2494fb8"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../pattern.html" class="c-breadcrumbs__link" aria-current="false"> Pattern </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Qualityfolio </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/pattern/","name":"Pattern"}},{"@type":"ListItem","position":3,"item":{"@id":"/pattern/qualityfolio/","name":"Qualityfolio"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"></div> <section class="mx-auto flex max-w-[85rem] flex-col px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div> <p id="fadeText" class="mb-8 max-w-prose text-pretty font-light text-neutral-700 dark:text-neutral-300 sm:text-xl"> Qualityfolio is your comprehensive, code-first solution for quality management and test lifecycle optimization. Built on the principles of "Test Management as Code" (TMaC), Qualityfolio integrates seamlessly with surveilr to provide robust test artifact management, analytics, and reporting. </p> </div> <div class="flex flex-col items-center justify-between space-y-4 sm:flex-row sm:space-y-0"> <div id="fadeInUp"> <h1 class="block text-4xl font-bold tracking-tighter text-neutral-800 dark:text-neutral-200 sm:text-5xl md:text-6xl lg:text-7xl"> Qualityfolio </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> Unified Test and Quality Management System </p> </div> <div> <img src="../../_astro/quality-folio.BI_YY2zZ_1bR8P.avif" id="fadeInMoveRight" alt="Qualityfolio" loading="eager" width="1740" height="643" decoding="async" class="w-[600px]"> </div> </div> </section> <div class="mx-auto max-w-[85rem] px-4 pt-10 sm:px-6 lg:px-8 lg:pt-14"> <nav class="mx-auto grid max-w-6xl gap-y-px sm:flex sm:gap-x-4 sm:gap-y-0" aria-label="Tabs" role="tablist"> <!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 active bg-neutral-100 hover:border-transparent dark:bg-white/[.05]" id="tabs-with-card-item-1" data-target="#tabs-with-card-1" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-orange-400 dark:text-orange-300"> Overview </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-2" data-target="#tabs-with-card-2" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Capabilities </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-3" data-target="#tabs-with-card-3" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Screenshots </span> </button> </nav> <div class="mt-12 md:mt-16"> <div id="tabs-with-card-1" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid gap-12 md:grid-cols-2"> <div class="lg:w-3/4"> <h2 class="text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:leading-tight lg:text-4xl"> Unified Test and Quality Management System </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> Qualityfolio is an all-in-one test and quality management system designed to streamline the test lifecycle with a code-first approach. Built on "Test Management as Code" (TMaC) principles, it enables secure storage, execution, and analysis of test artifacts through Surveilr. Featuring centralized test management, seamless CI/CD integration, real-time dashboards, and full traceability with FII codes, Qualityfolio simplifies workflows, ensures compliance, and fosters collaboration across industries. </p> <p class="mt-5"> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../lib/service/qualityfolio/package.sql"> Use the SQL <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 ml-1 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../../eg.surveilr.com/lib/service/qualityfolio.html" target="_blank"> Live Demo <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> </p> </div> <div class="space-y-6 lg:space-y-10"> <div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Centralized Test Management </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Organize and manage all test artifacts, including test cases, suites, and projects, in a single location. Leverage Markdown-driven content organization to ensure clarity and consistency. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Code-First Approach </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Treat test management as code (TMaC) to improve collaboration, version control, and scalability. Seamlessly integrate with GitOps workflows and CI/CD pipelines. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Automated and Manual Test Execution </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Support both automated and manual execution of test cases, ensuring flexibility in testing strategies. Utilize surveilr for structured ingestion and tracking of test results. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Real-Time Dashboards and Reporting </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Access intuitive web-based dashboards for monitoring test execution, defect metrics, and compliance tracking. Generate insights with custom filters, charts, and trend analysis. </p> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-2" class="hidden" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid w-full grid-cols-1 gap-x-16 md:grid-cols-2"> <div class="max-w-md space-y-6"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Test Lifecycle Automation </h3> <p class="text-neutral-600 dark:text-neutral-400"> Supports automated and manual execution of test cases integrated with CI/CD pipelines. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Scalable Architecture </h3> <p class="text-neutral-600 dark:text-neutral-400"> Handles complex projects and test artifacts with ease, ensuring scalability for growing teams. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Comprehensive Traceability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Track test case histories, results, and associated defects with unique identifiers. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Structured Content Storage </h3> <p class="text-neutral-600 dark:text-neutral-400"> Store test artifacts in surveilr's Resource Surveillance State Database (RSSD) for efficient querying, analytics, and auditing. </p> </div> </div> <div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Markdown-Driven Content </h3> <p class="text-neutral-600 dark:text-neutral-400"> Organize test cases, suites, and projects using structured Markdown for clarity and flexibility. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Advanced Integration Support </h3> <p class="text-neutral-600 dark:text-neutral-400"> Seamlessly connect with version control systems, CI/CD tools, and third-party platforms. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Web-Based Dashboard </h3> <p class="text-neutral-600 dark:text-neutral-400"> Visualize test cases, execution history, and metrics with an intuitive web interface. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Customizable Workflows </h3> <p class="text-neutral-600 dark:text-neutral-400"> Adapt Qualityfolio to meet your organization's specific quality management needs. </p> </div> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"> <img src="../../_astro/qualityfolio-1.l0geP3C2_1eC96X.avif" alt="Blueprint Illustration" width="1869" height="938" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <img src="../../_astro/qualityfolio-5.DZmgwzOe_Uffnn.avif" alt="Blueprint Illustration" width="1919" height="662" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> </div> </div> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../../blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> <script type="module">document.addEventListener("DOMContentLoaded",function(){function d(t,e){if(t!==e){t.classList.remove("active","bg-neutral-100","hover:border-transparent","dark:bg-white/[.05]");const a=t.getAttribute("data-target");if(a){const n=document.querySelector(a);n&&n.classList.add("hidden")}o(t,["text-neutral-800","dark:text-neutral-200"],["text-orange-400","dark:text-orange-300"])}}function c(t){t.classList.add("active","bg-neutral-100",",hover:border-transparent","dark:bg-white/[.05]");const e=t.getAttribute("data-target");if(e){const a=document.querySelector(e);a&&a.classList.remove("hidden")}o(t,["text-orange-400","dark:text-orange-300"],["text-neutral-800","dark:text-neutral-200"])}function o(t,e,a){let n=t.querySelector("span");n&&(n.classList.remove(...a),n.classList.add(...e))}const r=document.querySelectorAll("[data-target]");r.length>0&&o(r[0],["text-orange-400","dark:text-orange-300"],[]),r.forEach(t=>{t.addEventListener("click",()=>{r.forEach(e=>d(e,t)),c(t)})})});</script> <script type="module" src="../../_astro/_...slug_.astro_astro_type_script_index_1_lang.DaSW5oKf.js"></script> | html | 69533 | 2025-04-07 05:49:51.263991277 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTTRMW1DG237SEVGCCF | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/osquery/index.html | d1fbe2f3de8bb2cc5569f4c52859c09110a61bea | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"osQuery Integration Pattern | surveilr","url":"https://www.surveilr.com/pattern/osquery/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/osquery/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/osquery/"><meta property="og:type" content="website"><meta property="og:title" content="osQuery Integration Pattern | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/pattern/osquery/"><meta name="twitter:title" content="osQuery Integration Pattern | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>osQuery Integration Pattern | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="b7d279d2-9ffd-4de4-95fb-d35465be1e31" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="b7d279d2-9ffd-4de4-95fb-d35465be1e31"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../pattern.html" class="c-breadcrumbs__link" aria-current="false"> Pattern </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Osquery </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/pattern/","name":"Pattern"}},{"@type":"ListItem","position":3,"item":{"@id":"/pattern/osquery/","name":"Osquery"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"></div> <section class="mx-auto flex max-w-[85rem] flex-col px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div> <p id="fadeText" class="mb-8 max-w-prose text-pretty font-light text-neutral-700 dark:text-neutral-300 sm:text-xl"> The surveilr osQuery Integration Pattern provides a seamless method to integrate any surveilr-managed database into osQuery using the Automatic Table Construction (ATC) pattern. This allows organizations to query and analyze data from a variety of sources—collected and standardized within surveilr—via osQuery’s SQL interface. </p> </div> <div class="flex flex-col items-center justify-between space-y-4 sm:flex-row sm:space-y-0"> <div id="fadeInUp"> <h1 class="block text-4xl font-bold tracking-tighter text-neutral-800 dark:text-neutral-200 sm:text-5xl md:text-6xl lg:text-7xl"> osQuery Integration Pattern </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> Surface surveilr RSSD tables via osQuery </p> </div> <div> <img src="../../_astro/osquery-pattern.CJYgu4S2_ZDP31U.avif" id="fadeInMoveRight" alt="osQuery Integration Pattern" loading="eager" width="1251" height="768" decoding="async" class="w-[600px]"> </div> </div> </section> <div class="mx-auto max-w-[85rem] px-4 pt-10 sm:px-6 lg:px-8 lg:pt-14"> <nav class="mx-auto grid max-w-6xl gap-y-px sm:flex sm:gap-x-4 sm:gap-y-0" aria-label="Tabs" role="tablist"> <!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 active bg-neutral-100 hover:border-transparent dark:bg-white/[.05]" id="tabs-with-card-item-1" data-target="#tabs-with-card-1" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-orange-400 dark:text-orange-300"> Description </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-2" data-target="#tabs-with-card-2" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Capabilities </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-3" data-target="#tabs-with-card-3" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Screenshots </span> </button> </nav> <div class="mt-12 md:mt-16"> <div id="tabs-with-card-1" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid gap-12 md:grid-cols-2"> <div class="lg:w-3/4"> <h2 class="text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:leading-tight lg:text-4xl"> osQuery Integration Pattern </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> By leveraging the ATC JSON pattern, users can automatically surface custom tables in osQuery to interact directly with the content stored in surveilr's Resource Surveillance State Database (RSSD). This enables osQuery to dynamically join data from multiple sources (emails, logs, compliance evidence, PLM/CRM systems, etc.), providing powerful querying capabilities for security audits, compliance reporting, and decision-making. </p> <p class="mt-5"> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../lib/pattern/osquery/package.sql"> Use the SQL <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> </p> </div> <div class="space-y-6 lg:space-y-10"> <div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Unified Data Access </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> The integration allows organizations to leverage surveilr as a universal data aggregator, pulling from a multitude of data sources. osQuery users benefit from this by gaining a unified interface to query all of the data—regardless of where it originally came from—using standard SQL. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Edge-Based Security </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Since surveilr employs a local-first, edge-based approach, sensitive data is handled securely at the source, before it is ever integrated into the central system or osQuery tables. This enhances data security by reducing the risks associated with transferring sensitive information over networks. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Seamless Extensibility with ATC </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> The Automatic Table Construction (ATC) pattern simplifies extending osQuery’s capabilities. No need to write complex C++ extensions or plugins. Instead, users define custom tables in JSON format, making it easy to add new data sources or modify the structure of the tables without redeploying osQuery. </p> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-2" class="hidden" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid w-full grid-cols-1 gap-x-16 md:grid-cols-2"> <div class="max-w-md space-y-6"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div> </div> <div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Capability </h3> <p class="text-neutral-600 dark:text-neutral-400"> Capability Description </p> </div> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"> <img src="../../_astro/osquery-pattern-ss-2.Ds_ByT8M_4Bo2w.avif" alt="Blueprint Illustration" width="720" height="495" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <img src="../../_astro/osquery-pattern-ss-1.UHUNrmzD_Ln0rU.avif" alt="Blueprint Illustration" width="1503" height="735" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> </div> </div> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../../blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> <script type="module">document.addEventListener("DOMContentLoaded",function(){function d(t,e){if(t!==e){t.classList.remove("active","bg-neutral-100","hover:border-transparent","dark:bg-white/[.05]");const a=t.getAttribute("data-target");if(a){const n=document.querySelector(a);n&&n.classList.add("hidden")}o(t,["text-neutral-800","dark:text-neutral-200"],["text-orange-400","dark:text-orange-300"])}}function c(t){t.classList.add("active","bg-neutral-100",",hover:border-transparent","dark:bg-white/[.05]");const e=t.getAttribute("data-target");if(e){const a=document.querySelector(e);a&&a.classList.remove("hidden")}o(t,["text-orange-400","dark:text-orange-300"],["text-neutral-800","dark:text-neutral-200"])}function o(t,e,a){let n=t.querySelector("span");n&&(n.classList.remove(...a),n.classList.add(...e))}const r=document.querySelectorAll("[data-target]");r.length>0&&o(r[0],["text-orange-400","dark:text-orange-300"],[]),r.forEach(t=>{t.addEventListener("click",()=>{r.forEach(e=>d(e,t)),c(t)})})});</script> <script type="module" src="../../_astro/_...slug_.astro_astro_type_script_index_1_lang.DaSW5oKf.js"></script> | html | 67909 | 2025-04-07 05:49:50.511996858 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTV296A4MSZP1SWQAAD | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/research-study-explorer/index.html | 834322620f3fa39bb977796d0f7e30de8ce4e05a | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Diabetes Research Hub Study Pattern | surveilr","url":"https://www.surveilr.com/pattern/research-study-explorer/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/research-study-explorer/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/research-study-explorer/"><meta property="og:type" content="website"><meta property="og:title" content="Diabetes Research Hub Study Pattern | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/pattern/research-study-explorer/"><meta name="twitter:title" content="Diabetes Research Hub Study Pattern | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Diabetes Research Hub Study Pattern | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="51ba0289-3fe2-46ea-b1bf-184c7097e573" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="51ba0289-3fe2-46ea-b1bf-184c7097e573"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../pattern.html" class="c-breadcrumbs__link" aria-current="false"> Pattern </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Research Study Explorer </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/pattern/","name":"Pattern"}},{"@type":"ListItem","position":3,"item":{"@id":"/pattern/research-study-explorer/","name":"Research Study Explorer"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"></div> <section class="mx-auto flex max-w-[85rem] flex-col px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div> <p id="fadeText" class="mb-8 max-w-prose text-pretty font-light text-neutral-700 dark:text-neutral-300 sm:text-xl"> The Diabetes Research Hub (DRH) pattern simplifies the ingestion of CGM (Continuous Glucose Monitoring) files and supporting datasets. It allows seamless conversion to SQLite databases, executing advanced queries, and generating visual insights such as AGP (Ambulatory Glucose Profile) graphs and key metrics like J-Index, GRI, and more. </p> </div> <div class="flex flex-col items-center justify-between space-y-4 sm:flex-row sm:space-y-0"> <div id="fadeInUp"> <h1 class="block text-4xl font-bold tracking-tighter text-neutral-800 dark:text-neutral-200 sm:text-5xl md:text-6xl lg:text-7xl"> Diabetes Research Hub Study Pattern </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> A seamless integration for converting study files and generating metrics, visual insights for diabetes research. </p> </div> <div> <img src="../../_astro/research-study-explorer-pattern-ss-4.CC8jC-eH_HnpfP.avif" id="fadeInMoveRight" alt="Diabetes Research Hub Workflow" loading="eager" width="1856" height="904" decoding="async" class="w-[600px]"> </div> </div> </section> <div class="mx-auto max-w-[85rem] px-4 pt-10 sm:px-6 lg:px-8 lg:pt-14"> <nav class="mx-auto grid max-w-6xl gap-y-px sm:flex sm:gap-x-4 sm:gap-y-0" aria-label="Tabs" role="tablist"> <!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 active bg-neutral-100 hover:border-transparent dark:bg-white/[.05]" id="tabs-with-card-item-1" data-target="#tabs-with-card-1" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-orange-400 dark:text-orange-300"> Overview </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-2" data-target="#tabs-with-card-2" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Capabilities </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-3" data-target="#tabs-with-card-3" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Screenshots </span> </button> </nav> <div class="mt-12 md:mt-16"> <div id="tabs-with-card-1" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid gap-12 md:grid-cols-2"> <div class="lg:w-3/4"> <h2 class="text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:leading-tight lg:text-4xl"> Diabetes Research Hub Study Pattern </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> This pattern enables researchers to ingest CGM data and related datasets into SQLite databases for dynamic querying and visualizing results. By using DRH's standardized workflow, researchers can process datasets to derive critical insights such as daily glucose profiles, AGP graphs, and metrics like J-Index and GRI, supporting in-depth diabetes research. </p> <p class="mt-5"> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../lib/pattern/research-study-explorer/package.sql"> Explore SQL Workflow <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 ml-1 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../../eg.surveilr.com/lib/pattern/research-study-explorer.html" target="_blank"> Live Demo <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> </p> </div> <div class="space-y-6 lg:space-y-10"> <div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Standardized CGM Data Integration </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> DRH supports the ingestion of study data from CGM files and associated participant datasets, transforming them into structured SQLite databases. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Advanced Metrics Calculation </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Automatically compute critical diabetes metrics like AGP, J-Index, and GRI for in-depth participant insights. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Dynamic Query Execution </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> DRH allows querying datasets to generate participant-level reports, group-level summaries, and graphical visualizations. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Visualization Ready </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Supports rendering of AGP graphs, daily glucose profiles, and statistical summaries using SQLite views and integrated visualization tools. </p> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-2" class="hidden" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid w-full grid-cols-1 gap-x-16 md:grid-cols-2"> <div class="max-w-md space-y-6"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Secure and Scalable </h3> <p class="text-neutral-600 dark:text-neutral-400"> Handles large datasets securely, ensuring participant data integrity and compliance with research standards. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Cross-Study Comparison </h3> <p class="text-neutral-600 dark:text-neutral-400"> Facilitates comparisons across studies by standardizing CGM data ingestion and processing workflows. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Automated Data Validation </h3> <p class="text-neutral-600 dark:text-neutral-400"> Detects anomalies and validates data integrity for robust research outputs. </p> </div> </div> <div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Comprehensive Metrics </h3> <p class="text-neutral-600 dark:text-neutral-400"> Calculates a wide range of metrics, including mean glucose, glucose variability, and risk indicators. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Custom Study Reports </h3> <p class="text-neutral-600 dark:text-neutral-400"> Generates customizable participant and study-level reports with visual insights. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Enhanced Collaboration </h3> <p class="text-neutral-600 dark:text-neutral-400"> Provides exportable results and insights for collaboration across institutions and teams. </p> </div> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"> <img src="../../_astro/research-study-explorer-pattern-ss-5.B5Avi_6V_1swxvY.avif" alt="Blueprint Illustration" width="908" height="662" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <img src="../../_astro/research-study-explorer-pattern-ss-2.CKgqLGXw_2mInmH.avif" alt="Blueprint Illustration" width="1862" height="916" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> </div> </div> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../../blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> <script type="module">document.addEventListener("DOMContentLoaded",function(){function d(t,e){if(t!==e){t.classList.remove("active","bg-neutral-100","hover:border-transparent","dark:bg-white/[.05]");const a=t.getAttribute("data-target");if(a){const n=document.querySelector(a);n&&n.classList.add("hidden")}o(t,["text-neutral-800","dark:text-neutral-200"],["text-orange-400","dark:text-orange-300"])}}function c(t){t.classList.add("active","bg-neutral-100",",hover:border-transparent","dark:bg-white/[.05]");const e=t.getAttribute("data-target");if(e){const a=document.querySelector(e);a&&a.classList.remove("hidden")}o(t,["text-orange-400","dark:text-orange-300"],["text-neutral-800","dark:text-neutral-200"])}function o(t,e,a){let n=t.querySelector("span");n&&(n.classList.remove(...a),n.classList.add(...e))}const r=document.querySelectorAll("[data-target]");r.length>0&&o(r[0],["text-orange-400","dark:text-orange-300"],[]),r.forEach(t=>{t.addEventListener("click",()=>{r.forEach(e=>d(e,t)),c(t)})})});</script> <script type="module" src="../../_astro/_...slug_.astro_astro_type_script_index_1_lang.DaSW5oKf.js"></script> | html | 69046 | 2025-04-07 05:49:50.726995262 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTVV498B80MWA3H3A5P | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/direct-messaging-service/index.html | e5bcf3fff3d8100dba409b8ed6443803488e7949 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Direct Secure Messaging Service | surveilr","url":"https://www.surveilr.com/pattern/direct-messaging-service/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/direct-messaging-service/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/direct-messaging-service/"><meta property="og:type" content="website"><meta property="og:title" content="Direct Secure Messaging Service | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/pattern/direct-messaging-service/"><meta name="twitter:title" content="Direct Secure Messaging Service | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Direct Secure Messaging Service | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="ebd3e5de-2e62-4f1c-9b0d-64ded27a31a8" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="ebd3e5de-2e62-4f1c-9b0d-64ded27a31a8"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../pattern.html" class="c-breadcrumbs__link" aria-current="false"> Pattern </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Direct Messaging Service </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/pattern/","name":"Pattern"}},{"@type":"ListItem","position":3,"item":{"@id":"/pattern/direct-messaging-service/","name":"Direct Messaging Service"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"></div> <section class="mx-auto flex max-w-[85rem] flex-col px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div> <p id="fadeText" class="mb-8 max-w-prose text-pretty font-light text-neutral-700 dark:text-neutral-300 sm:text-xl"> The Direct Secure Messaging Service Pattern for surveilr ingests clinical data CCDA XML files and allows querying, summarizing episodes of care and exploration of those files. </p> </div> <div class="flex flex-col items-center justify-between space-y-4 sm:flex-row sm:space-y-0"> <div id="fadeInUp"> <h1 class="block text-4xl font-bold tracking-tighter text-neutral-800 dark:text-neutral-200 sm:text-5xl md:text-6xl lg:text-7xl"> Direct Secure Messaging Service </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> Trusted and protected health information exchange is backed by the Direct Standard® </p> </div> <div> <img src="../../_astro/direct-message-pattern.MIDcmLaO_Z1C1DMN.avif" id="fadeInMoveRight" alt="Direct Secure Messaging Service" loading="eager" width="1678" height="643" decoding="async" class="w-[600px]"> </div> </div> </section> <div class="mx-auto max-w-[85rem] px-4 pt-10 sm:px-6 lg:px-8 lg:pt-14"> <nav class="mx-auto grid max-w-6xl gap-y-px sm:flex sm:gap-x-4 sm:gap-y-0" aria-label="Tabs" role="tablist"> <!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 active bg-neutral-100 hover:border-transparent dark:bg-white/[.05]" id="tabs-with-card-item-1" data-target="#tabs-with-card-1" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-orange-400 dark:text-orange-300"> Overview </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-2" data-target="#tabs-with-card-2" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Capabilities </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-3" data-target="#tabs-with-card-3" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Screenshots </span> </button> </nav> <div class="mt-12 md:mt-16"> <div id="tabs-with-card-1" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid gap-12 md:grid-cols-2"> <div class="lg:w-3/4"> <h2 class="text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:leading-tight lg:text-4xl"> Direct Secure Messaging Service </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> This pattern is designed to facilitate the secure exchange of clinical data using the phiMail service. It consists of four main modules, each serving a distinct purpose within the overall system. These modules work together to securely and efficiently send, receive, process, and analyze clinical messages. PhiMail is a secure messaging service that facilitates the exchange of protected health information (PHI) in compliance with healthcare regulations like HIPAA. It is designed to support healthcare providers, organizations, and other stakeholders in securely transmitting health-related data, ensuring both privacy and integrity. </p> <p class="mt-5"> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../lib/pattern/direct-messaging-service/package.sql"> Use the SQL <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 ml-1 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../../eg.surveilr.com/lib/pattern/direct-messaging-service.html" target="_blank"> Live Demo <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> </p> </div> <div class="space-y-6 lg:space-y-10"> <div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Compliance with HIPAA </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> PhiMail ensures that all communications involving PHI meet the stringent requirements of the Health Insurance Portability and Accountability Act (HIPAA). This includes encryption of data in transit, secure storage, and proper handling of sensitive information. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> DIRECT Protocol Support </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> PhiMail is built on the DIRECT protocol, a standardized method for secure email communication in healthcare. This enables seamless and secure transmission of health information between different systems and organizations, such as hospitals, laboratories, and physician offices. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Encryption and Security </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> PhiMail utilizes robust encryption mechanisms to protect data, ensuring that only authorized parties can access the information. This includes the use of SSL/TLS for secure connections and digital signatures to verify the authenticity of messages. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Interoperability </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> PhiMail supports interoperability with various healthcare systems, enabling the exchange of data in different formats like CDA (Clinical Document Architecture). This allows for smooth integration with electronic health records (EHR) systems and other health information exchanges (HIEs). </p> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-2" class="hidden" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid w-full grid-cols-1 gap-x-16 md:grid-cols-2"> <div class="max-w-md space-y-6"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Message Tracking and Acknowledgments </h3> <p class="text-neutral-600 dark:text-neutral-400"> phiMail provides detailed tracking of message delivery, including delivery status and read receipts. This is crucial in healthcare settings, where confirmation of receipt and action on health-related messages is often required. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Scalability and Customization </h3> <p class="text-neutral-600 dark:text-neutral-400"> phiMail can be tailored to the specific needs of healthcare organizations, whether they require a standalone messaging solution or integration with existing systems. It is scalable to accommodate the needs of small practices as well as large healthcare networks. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Secure Attachments </h3> <p class="text-neutral-600 dark:text-neutral-400"> phiMail supports the secure exchange of attachments, such as medical records, lab results, and other documents. These attachments are encrypted and can be managed securely within the platform. </p> </div> </div> <div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Clinical Communication </h3> <p class="text-neutral-600 dark:text-neutral-400"> Facilitates the exchange of medical records, referrals, and other critical health information between providers, ensuring timely and secure communication. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Laboratory Results </h3> <p class="text-neutral-600 dark:text-neutral-400"> Enables labs to send results directly to providers, integrating seamlessly with EHR systems for quick access. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Patient Communication </h3> <p class="text-neutral-600 dark:text-neutral-400"> Allows healthcare providers to securely send and receive information directly with patients, such as test results, care instructions, or appointment reminders. </p> </div> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"> <img src="../../_astro/direct-message-ss-2.-NkgDban_24UsnL.avif" alt="Blueprint Illustration" width="1338" height="633" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <img src="../../_astro/direct-message-ss-3.DyWW9lWT_Z1pdfAs.avif" alt="Blueprint Illustration" width="1289" height="641" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> </div> </div> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../../blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> <script type="module">document.addEventListener("DOMContentLoaded",function(){function d(t,e){if(t!==e){t.classList.remove("active","bg-neutral-100","hover:border-transparent","dark:bg-white/[.05]");const a=t.getAttribute("data-target");if(a){const n=document.querySelector(a);n&&n.classList.add("hidden")}o(t,["text-neutral-800","dark:text-neutral-200"],["text-orange-400","dark:text-orange-300"])}}function c(t){t.classList.add("active","bg-neutral-100",",hover:border-transparent","dark:bg-white/[.05]");const e=t.getAttribute("data-target");if(e){const a=document.querySelector(e);a&&a.classList.remove("hidden")}o(t,["text-orange-400","dark:text-orange-300"],["text-neutral-800","dark:text-neutral-200"])}function o(t,e,a){let n=t.querySelector("span");n&&(n.classList.remove(...a),n.classList.add(...e))}const r=document.querySelectorAll("[data-target]");r.length>0&&o(r[0],["text-orange-400","dark:text-orange-300"],[]),r.forEach(t=>{t.addEventListener("click",()=>{r.forEach(e=>d(e,t)),c(t)})})});</script> <script type="module" src="../../_astro/_...slug_.astro_astro_type_script_index_1_lang.DaSW5oKf.js"></script> | html | 70170 | 2025-04-07 05:49:50.171999382 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTV1PQWYXG621EGJ6E5 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/lectio/index.html | a4aea8d618161613748f3e5e44059cd47f3ed03c | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Netspective Lectio | surveilr","url":"https://www.surveilr.com/pattern/lectio/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/lectio/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/lectio/"><meta property="og:type" content="website"><meta property="og:title" content="Netspective Lectio | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/pattern/lectio/"><meta name="twitter:title" content="Netspective Lectio | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Netspective Lectio | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="420d0bd4-ecc9-412d-9690-04cc428f33dc" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="420d0bd4-ecc9-412d-9690-04cc428f33dc"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../pattern.html" class="c-breadcrumbs__link" aria-current="false"> Pattern </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Lectio </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/pattern/","name":"Pattern"}},{"@type":"ListItem","position":3,"item":{"@id":"/pattern/lectio/","name":"Lectio"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"></div> <section class="mx-auto flex max-w-[85rem] flex-col px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div> <p id="fadeText" class="mb-8 max-w-prose text-pretty font-light text-neutral-700 dark:text-neutral-300 sm:text-xl"> Netspective Lectio is a cutting-edge, team-based reading assignment and content collaboration solution designed to address these challenges. By integrating advanced tracking mechanisms, role-based content sharing, and continuous education tools, Lectio ensures that knowledge is not only shared but also understood and acted upon. </p> </div> <div class="flex flex-col items-center justify-between space-y-4 sm:flex-row sm:space-y-0"> <div id="fadeInUp"> <h1 class="block text-4xl font-bold tracking-tighter text-neutral-800 dark:text-neutral-200 sm:text-5xl md:text-6xl lg:text-7xl"> Netspective Lectio </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> Team-based reading assignment and content collaboration solution </p> </div> <div> <img src="../../_astro/lectio-pattern.g9zmiR7c_XE2Uk.avif" id="fadeInMoveRight" alt="Mockup boxes of a tap bolts and nuts set" loading="eager" width="2412" height="1056" decoding="async" class="w-[600px]"> </div> </div> </section> <div class="mx-auto max-w-[85rem] px-4 pt-10 sm:px-6 lg:px-8 lg:pt-14"> <nav class="mx-auto grid max-w-6xl gap-y-px sm:flex sm:gap-x-4 sm:gap-y-0" aria-label="Tabs" role="tablist"> <!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 active bg-neutral-100 hover:border-transparent dark:bg-white/[.05]" id="tabs-with-card-item-1" data-target="#tabs-with-card-1" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-orange-400 dark:text-orange-300"> Description </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-2" data-target="#tabs-with-card-2" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Capabilities </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-3" data-target="#tabs-with-card-3" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Screenshots </span> </button> </nav> <div class="mt-12 md:mt-16"> <div id="tabs-with-card-1" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid gap-12 md:grid-cols-2"> <div class="lg:w-3/4"> <h2 class="text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:leading-tight lg:text-4xl"> Netspective Lectio </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> In today’s rapidly evolving business landscape, the ability to efficiently disseminate, retain, and apply knowledge is more critical than ever. However, traditional methods of sharing knowledge—such as emailing links, PDFs, or other resources—are often ineffective, particularly in B2B environments where roles, disciplines, and subject areas vary widely. Netspective Lectio is a cutting-edge, team-based reading assignment and content collaboration solution designed to address these challenges. By integrating advanced tracking mechanisms, role-based content sharing, and continuous education tools, Lectio ensures that knowledge is not only shared but also understood and acted upon. </p> <p class="mt-5"> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="https://www.surveilr.com/pattern/lectio/package.sql"> Use the SQL <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> </p> </div> <div class="space-y-6 lg:space-y-10"> <div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Team-based </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Netspective Lectio is designed to revolutionize team-based knowledge sharing and collaboration by addressing the inefficiencies of traditional methods. By offering robust tools for creating, tracking, and applying knowledge, Lectio ensures that organizations can keep pace with the growing demands of knowledge management. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Comprehensive data aggregation </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> The integration of surveilr within Lectio’s architecture enhances its capabilities, allowing for comprehensive data aggregation and analysis across multiple sources. This data strategy, combined with advanced tracking mechanisms and role-based content sharing, positions Lectio as an essential tool for any organization looking to enhance its knowledge management processes. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Continuous education and effectiveness tracking </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Lectio’s targeted approach—catering to specific roles, disciplines, and subject areas—ensures that knowledge is not only disseminated effectively but also applied in a way that drives tangible results. With a strong focus on continuous education and effectiveness tracking, Lectio is poised to become a cornerstone of modern knowledge management strategies. </p> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-2" class="hidden" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid w-full grid-cols-1 gap-x-16 md:grid-cols-2"> <div class="max-w-md space-y-6"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Create Team Reading Assignments </h3> <p class="text-neutral-600 dark:text-neutral-400"> Lectio shares content (URLs, PDFs, etc.) with your team members as reading assignments. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Track Reading Assignments </h3> <p class="text-neutral-600 dark:text-neutral-400"> Lectio tracks who read the links, PDFs, and documents and who is ignoring them or hasn’t opened them. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Track Knowledge Sharing Effectiveness </h3> <p class="text-neutral-600 dark:text-neutral-400"> Lectio encourages discussions through comments and questions for each link. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Apply The Knowledge </h3> <p class="text-neutral-600 dark:text-neutral-400"> Lectio follows the usage of the knowledge and how it was applied and acted upon. </p> </div> </div> <div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Content Sharers (“Assigners”) </h3> <p class="text-neutral-600 dark:text-neutral-400"> The executives, individuals, or business units that are sharing “check this out” style links, PDFs, etc. to educate their teams and collaborate around specialized knowledge </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Content Educators (“Facilitators”) </h3> <p class="text-neutral-600 dark:text-neutral-400"> Usually individuals who need to make sure that the knowledge required to do a workforce’s job is properly disseminated </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Content Students (“Assignees”) </h3> <p class="text-neutral-600 dark:text-neutral-400"> The individuals, either internal to an organization or external vendors or partners, that need to be given reading assignments to understand how to do their job(s) </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Knowledge Auditors (“Enforcers”) </h3> <p class="text-neutral-600 dark:text-neutral-400"> Subject matter specialists who can score and analyze how knowledge is being consumed; auditors can be the same as facilitators and educators or external to an organization </p> </div> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"> <img src="../../_astro/lectio-pattern-ss-1.qKsXv9u-_Z1ly0mY.avif" alt="Blueprint Illustration" width="794" height="484" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <img src="../../_astro/lectio-pattern-ss-2.zJD0Yndi_6rvN.avif" alt="Blueprint Illustration" width="1161" height="647" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> </div> </div> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../../blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> <script type="module">document.addEventListener("DOMContentLoaded",function(){function d(t,e){if(t!==e){t.classList.remove("active","bg-neutral-100","hover:border-transparent","dark:bg-white/[.05]");const a=t.getAttribute("data-target");if(a){const n=document.querySelector(a);n&&n.classList.add("hidden")}o(t,["text-neutral-800","dark:text-neutral-200"],["text-orange-400","dark:text-orange-300"])}}function c(t){t.classList.add("active","bg-neutral-100",",hover:border-transparent","dark:bg-white/[.05]");const e=t.getAttribute("data-target");if(e){const a=document.querySelector(e);a&&a.classList.remove("hidden")}o(t,["text-orange-400","dark:text-orange-300"],["text-neutral-800","dark:text-neutral-200"])}function o(t,e,a){let n=t.querySelector("span");n&&(n.classList.remove(...a),n.classList.add(...e))}const r=document.querySelectorAll("[data-target]");r.length>0&&o(r[0],["text-orange-400","dark:text-orange-300"],[]),r.forEach(t=>{t.addEventListener("click",()=>{r.forEach(e=>d(e,t)),c(t)})})});</script> <script type="module" src="../../_astro/_...slug_.astro_astro_type_script_index_1_lang.DaSW5oKf.js"></script> | html | 69318 | 2025-04-07 05:49:49.686002989 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTVBXNXX380329M1AQ4 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/compliance-explorer/index.html | e78c586ea6ced07e8d2c76161c0d4ae1a4755881 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Compliance Explorer | surveilr","url":"https://www.surveilr.com/pattern/compliance-explorer/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/compliance-explorer/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/compliance-explorer/"><meta property="og:type" content="website"><meta property="og:title" content="Compliance Explorer | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/pattern/compliance-explorer/"><meta name="twitter:title" content="Compliance Explorer | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Compliance Explorer | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="dcae2ac2-a203-46a3-8b72-e4e428e8655e" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="dcae2ac2-a203-46a3-8b72-e4e428e8655e"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../pattern.html" class="c-breadcrumbs__link" aria-current="false"> Pattern </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Compliance Explorer </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/pattern/","name":"Pattern"}},{"@type":"ListItem","position":3,"item":{"@id":"/pattern/compliance-explorer/","name":"Compliance Explorer"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"></div> <section class="mx-auto flex max-w-[85rem] flex-col px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div> <p id="fadeText" class="mb-8 max-w-prose text-pretty font-light text-neutral-700 dark:text-neutral-300 sm:text-xl"> The Compliance Explorer Pattern for surveilr ingests SCF controls and create a web-based user interface that lists and displays SCF controls Aggregator and Explorer. </p> </div> <div class="flex flex-col items-center justify-between space-y-4 sm:flex-row sm:space-y-0"> <div id="fadeInUp"> <h1 class="block text-4xl font-bold tracking-tighter text-neutral-800 dark:text-neutral-200 sm:text-5xl md:text-6xl lg:text-7xl"> Compliance Explorer </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> Web-based user interface that lists and displays SCF controls Aggregator and Explorer </p> </div> <div> <img src="../../_astro/compliance-explorer-pattern-ss-2.Clembp9e_1FvH8P.avif" id="fadeInMoveRight" alt="Compliance Explorer" loading="eager" width="1236" height="680" decoding="async" class="w-[600px]"> </div> </div> </section> <div class="mx-auto max-w-[85rem] px-4 pt-10 sm:px-6 lg:px-8 lg:pt-14"> <nav class="mx-auto grid max-w-6xl gap-y-px sm:flex sm:gap-x-4 sm:gap-y-0" aria-label="Tabs" role="tablist"> <!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 active bg-neutral-100 hover:border-transparent dark:bg-white/[.05]" id="tabs-with-card-item-1" data-target="#tabs-with-card-1" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-orange-400 dark:text-orange-300"> Overview </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-2" data-target="#tabs-with-card-2" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Capabilities </span> </button><!-- Tab button element --><button type="button" class="flex w-full justify-center rounded-xl border border-transparent p-3 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus-visible:ring dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:focus:outline-none md:p-5 " id="tabs-with-card-item-3" data-target="#tabs-with-card-3" role="tab"> <!-- Tab text --> <span class="block text-center font-bold text-neutral-800 dark:text-neutral-200"> Screenshots </span> </button> </nav> <div class="mt-12 md:mt-16"> <div id="tabs-with-card-1" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid gap-12 md:grid-cols-2"> <div class="lg:w-3/4"> <h2 class="text-balance text-3xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:leading-tight lg:text-4xl"> Compliance Content Aggregator and Explorer </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> The compliance Explorer Pattern for surveilr ingests SCF data files and allows querying, quality metrics, and exploration of those files. surveilr ingests SCF data (represented as CSVfiles), stores it securely in a local SQL database, prepares SQL views for convenient querying, generates metrics of the FHIR content, and has an easy to use Web UI with options to filter, search, and visualize various healthcare records. </p> <p class="mt-5"> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../lib/pattern/compliance-explorer/package.sql"> Use the SQL <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> <!-- Link styled as a button, with dynamic title, URL, and optional arrow --><a class="group inline-flex items-center justify-center gap-x-2 rounded-lg px-4 ml-1 py-3 text-sm font-bold text-neutral-50 ring-zinc-500 transition duration-300 focus-visible:ring outline-none border border-transparent bg-orange-400 hover:bg-orange-500 active:bg-orange-500 dark:focus:outline-none disabled:pointer-events-none disabled:opacity-50 2xl:text-base dark:ring-zinc-200" href="../../../eg.surveilr.com/lib/pattern/compliance-explorer.html" target="_blank"> Live Demo <!-- Display the arrow based on the 'noArrow' property --> <svg class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </a> </p> </div> <div class="space-y-6 lg:space-y-10"> <div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Explore SCF data </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Easily search, filter, and interact with SCF Controls in CSV dowladable format. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Quality Assurance </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Ensure SCF Controls data meets your organization's standards with built-in checks. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Visualize insights </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Quickly analyze healthcare records with intuitive tools and data quality and compliance with real-time metrics and reporting. </p> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-2" class="hidden" role="tabpanel"> <div class="mx-auto max-w-[85rem] px-4 pb-10 sm:px-6 lg:px-8 lg:pb-14"> <div class="grid w-full grid-cols-1 gap-x-16 md:grid-cols-2"> <div class="max-w-md space-y-6"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Multiple FHIR versions </h3> <p class="text-neutral-600 dark:text-neutral-400"> Ingests FHIR JSON files conforming to FHIR versions R4 and DSTU2, ensuring compatibility with the most widely adopted healthcare data standards. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Wide resource coverage </h3> <p class="text-neutral-600 dark:text-neutral-400"> Ingests a wide range of FHIR resources, including Patient, Observation, Encounter, MedicationRequest, Practitioner, Condition, and Procedure. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Handles large data volumes </h3> <p class="text-neutral-600 dark:text-neutral-400"> Supports batch ingestion to handle large volumes of FHIR data efficiently in a local workstation or server. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Automatic schema validation </h3> <p class="text-neutral-600 dark:text-neutral-400"> Validates SCF Controls definitions, ensuring structural and standards compliance. </p> </div> </div> <div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0"> <div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Ingests SCF bundles </h3> <p class="text-neutral-600 dark:text-neutral-400"> Supports ingestion of SCF Bundles, including Transaction and Searchset types, enabling batch data imports and API-driven retrieval. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Advanced metadata indexing </h3> <p class="text-neutral-600 dark:text-neutral-400"> Extracts and indexes metadata such as resource identifiers, timestamps, and provenance information for querying and audit trails. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Supports custom mappings </h3> <p class="text-neutral-600 dark:text-neutral-400"> Allows for custom mappings and transformations to align non-standard FHIR implementations with the core schema. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Extension and profile exploration </h3> <p class="text-neutral-600 dark:text-neutral-400"> Provides full access to FHIR extensions and profiles for custom elements and jurisdiction-specific constraints. </p> </div> </div> </div> </div> </div> </div> </div> <div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"> <img src="../../_astro/compliance-explorer-pattern-ss-3.DiO7uket_Z1DkYmV.avif" alt="Blueprint Illustration" width="1239" height="678" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <img src="../../_astro/compliance-explorer-pattern-ss-1.CgPz0X02_Z1uMJDo.avif" alt="Blueprint Illustration" width="1255" height="656" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> </div> </div> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../../blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> <script type="module">document.addEventListener("DOMContentLoaded",function(){function d(t,e){if(t!==e){t.classList.remove("active","bg-neutral-100","hover:border-transparent","dark:bg-white/[.05]");const a=t.getAttribute("data-target");if(a){const n=document.querySelector(a);n&&n.classList.add("hidden")}o(t,["text-neutral-800","dark:text-neutral-200"],["text-orange-400","dark:text-orange-300"])}}function c(t){t.classList.add("active","bg-neutral-100",",hover:border-transparent","dark:bg-white/[.05]");const e=t.getAttribute("data-target");if(e){const a=document.querySelector(e);a&&a.classList.remove("hidden")}o(t,["text-orange-400","dark:text-orange-300"],["text-neutral-800","dark:text-neutral-200"])}function o(t,e,a){let n=t.querySelector("span");n&&(n.classList.remove(...a),n.classList.add(...e))}const r=document.querySelectorAll("[data-target]");r.length>0&&o(r[0],["text-orange-400","dark:text-orange-300"],[]),r.forEach(t=>{t.addEventListener("click",()=>{r.forEach(e=>d(e,t)),c(t)})})});</script> <script type="module" src="../../_astro/_...slug_.astro_astro_type_script_index_1_lang.DaSW5oKf.js"></script> | html | 69067 | 2025-04-07 05:49:51.295991039 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTWBBN0JQRPF93GCAYX | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/docs.html | 6e252aa700af8603ce0bbd9d3c9f5f0a73cfcca9 | <!DOCTYPE html><html lang="en" dir="ltr" data-theme="dark" data-has-hero class="astro-bguv2lll"> <head><meta name="astro-view-transitions-enabled" content="true"><meta name="astro-view-transitions-fallback" content="animate"><script type="module" src="_astro/ClientRouter.astro_astro_type_script_index_0_lang.QENdKRY9.js"></script> <meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>Survelir Docs</title><link rel="canonical" href="docs.html"/><link rel="sitemap" href="sitemap-index.xml"/><link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/><meta name="generator" content="Astro v5.6.1"/><meta name="generator" content="Starlight v0.32.6"/><meta property="og:title" content="Survelir Docs"/><meta property="og:type" content="article"/><meta property="og:url" content="https://www.surveilr.com/docs/"/><meta property="og:locale" content="en"/><meta property="og:description" content="Explore Survelir's comprehensive documentation for an in-depth look at our premium tools and construction services."/><meta property="og:site_name" content="surveilr Docs"/><meta name="twitter:card" content="summary_large_image"/><meta name="description" content="Explore Survelir's comprehensive documentation for an in-depth look at our premium tools and construction services."/><meta property="og:image" content="https://www.surveilr.com/social.webp"/><meta property="twitter:image" content="https://www.surveilr.com/social.webp"/> <meta name="vtbot-replace-swap" content="data-theme"><script type="module" src="_astro/ReplacementSwap.astro_astro_type_script_index_0_lang.w-JJFnOc.js"></script> <script type="module" src="_astro/StarlightConnector.astro_astro_type_script_index_0_lang.PTcfxOe0.js"></script> <script> window.StarlightThemeProvider = (() => { const storedTheme = typeof localStorage !== 'undefined' && localStorage.getItem('starlight-theme'); const theme = storedTheme || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'); document.documentElement.dataset.theme = theme === 'light' ? 'light' : 'dark'; return { updatePickers(theme = storedTheme || 'auto') { document.querySelectorAll('starlight-theme-select').forEach((picker) => { const select = picker.querySelector('select'); if (select) select.value = theme; /** @type {HTMLTemplateElement | null} */ const tmpl = document.querySelector(`#theme-icons`); const newIcon = tmpl && tmpl.content.querySelector('.' + theme); if (newIcon) { const oldIcon = picker.querySelector('svg.label-icon'); if (oldIcon) { oldIcon.replaceChildren(...newIcon.cloneNode(true).childNodes); } } }); }, }; })(); </script><template id="theme-icons"><svg aria-hidden="true" class="light astro-c6vsoqas" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M5 12a1 1 0 0 0-1-1H3a1 1 0 0 0 0 2h1a1 1 0 0 0 1-1Zm.64 5-.71.71a1 1 0 0 0 0 1.41 1 1 0 0 0 1.41 0l.71-.71A1 1 0 0 0 5.64 17ZM12 5a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v1a1 1 0 0 0 1 1Zm5.66 2.34a1 1 0 0 0 .7-.29l.71-.71a1 1 0 1 0-1.41-1.41l-.66.71a1 1 0 0 0 0 1.41 1 1 0 0 0 .66.29Zm-12-.29a1 1 0 0 0 1.41 0 1 1 0 0 0 0-1.41l-.71-.71a1.004 1.004 0 1 0-1.43 1.41l.73.71ZM21 11h-1a1 1 0 0 0 0 2h1a1 1 0 0 0 0-2Zm-2.64 6A1 1 0 0 0 17 18.36l.71.71a1 1 0 0 0 1.41 0 1 1 0 0 0 0-1.41l-.76-.66ZM12 6.5a5.5 5.5 0 1 0 5.5 5.5A5.51 5.51 0 0 0 12 6.5Zm0 9a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7Zm0 3.5a1 1 0 0 0-1 1v1a1 1 0 0 0 2 0v-1a1 1 0 0 0-1-1Z"/></svg> <svg aria-hidden="true" class="dark astro-c6vsoqas" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M21.64 13a1 1 0 0 0-1.05-.14 8.049 8.049 0 0 1-3.37.73 8.15 8.15 0 0 1-8.14-8.1 8.59 8.59 0 0 1 .25-2A1 1 0 0 0 8 2.36a10.14 10.14 0 1 0 14 11.69 1 1 0 0 0-.36-1.05Zm-9.5 6.69A8.14 8.14 0 0 1 7.08 5.22v.27a10.15 10.15 0 0 0 10.14 10.14 9.784 9.784 0 0 0 2.1-.22 8.11 8.11 0 0 1-7.18 4.32v-.04Z"/></svg> <svg aria-hidden="true" class="auto astro-c6vsoqas" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M21 14h-1V7a3 3 0 0 0-3-3H7a3 3 0 0 0-3 3v7H3a1 1 0 0 0-1 1v2a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3v-2a1 1 0 0 0-1-1ZM6 7a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v7H6V7Zm14 10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-1h16v1Z"/></svg> </template><link rel="stylesheet" href="_astro/print.BL8QyxEA.css" media="print"><link rel="stylesheet" href="_astro/index.x-iyR4LI.css"> <link rel="stylesheet" href="_astro/index.BcY-adz4.css"><script type="module" src="_astro/page.CJRj5HRh.js"></script><style>:root{--primary-button-hover: #ff801f;--backdrop-color: #272727cc;--sl-color-accent: #ff801f;--sl-color-accent-high: #ffa057;--sl-color-accent-low: #562800;--sl-color-black: #181818;--sl-color-gray-1: #eee;--sl-color-gray-2: #c2c2c2;--sl-color-gray-3: #8b8b8b;--sl-color-gray-4: #585858;--sl-color-gray-5: #383838;--sl-color-gray-6: #272727;--sl-color-white: #fff;--yellow-hsl: 43.3, 96.4%, 56.3%;--overlay-yellow: hsla(var(--yellow-hsl), .2);--border: hsla(var(--border-neutral), .4);--border-neutral: 0, 0%, 25.1%}:root[data-theme=light]{--primary-button-hover: #ff801f;--backdrop-color: #f6f6f699;--sl-color-accent: #f76b15;--sl-color-accent-high: #562800;--sl-color-accent-low: #ffa057;--sl-color-black: #fff;--sl-color-gray-1: #272727;--sl-color-gray-2: #383838;--sl-color-gray-3: #585858;--sl-color-gray-4: #8b8b8b;--sl-color-gray-5: #c2c2c2;--sl-color-gray-6: #eee;--sl-color-gray-7: #f6f6f6;--sl-color-white: #181818;--yellow-hsl: 47.9, 95.8%, 53.1%;--border-yellow: 54.9, 96.7%, 88%;--border: hsla(var(--border-yellow), .4)}.page{background:linear-gradient(215deg,var(--overlay-yellow),transparent 40%),radial-gradient(var(--overlay-yellow),transparent 40%) no-repeat center center / cover,radial-gradient(var(--overlay-yellow),transparent 65%) no-repeat center center / cover;background-blend-mode:overlay}header{border:none!important;padding:0!important}header.header{background-color:transparent!important;height:4.5rem!important;margin-inline:auto!important;padding-block:0!important;padding-inline:2rem!important}header>div:first-of-type{-webkit-backdrop-filter:blur(12px)!important;backdrop-filter:blur(12px)!important;background-color:var(--backdrop-color)!important;border:1px var(--border) solid;border-radius:36px;height:100%!important;margin-inline:auto!important;margin-top:1rem!important;max-width:1536px;padding-inline:2rem!important;width:auto!important}select{background-image:none;box-shadow:none}.sl-flex.action.primary:hover{background-color:var(--primary-button-hover);transition:background-color .3s cubic-bezier(.4,0,.2,1)}.sl-flex.action.primary:hover svg{transform:translate(.25rem);transition:transform .3s cubic-bezier(.4,0,.2,1)} </style></head> <body class="astro-bguv2lll"> <a href="docs.html#_top" class="astro-7q3lir66">Skip to content</a> <div class="page sl-flex astro-vrdttmbt"> <header class="header astro-vrdttmbt"><div class="header sl-flex astro-kmkmnagf"> <div class="title-wrapper sl-flex astro-kmkmnagf"> <span class="site-title flex astro-cdy74xqe"> <a class="main-logo astro-cdy74xqe" href="../surveilr.com/index.html" aria-label="Survelir" style="width: 180px;"><svg width="480" height="135" viewBox="0 0 480 135" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M101 62.8638C58.0713 44.0467 22.8968 69.0455 9 76.886V77.5C34 66.5 65 73.5 71.8993 76.8862C70.2482 80.6859 59.1032 93.698 53.7372 99.7291L43.8305 89.3254C35.9052 89.5064 25.806 93.4718 21.747 95.4319C29.6723 108.278 46.376 122.497 53.7372 128C83.7872 105.202 97.7666 75.0768 101 62.8638Z" fill="#CB3038"/> <path d="M2.28736 56.0714C0.432566 47.9576 -0.117437 39.979 0.0200397 36.5983C46.5422 15.3402 90.41 30.2591 106.426 39.3871V40.0526C62 22.0526 18.8533 48.0252 2.28736 56.0714Z" fill="#B1865C"/> <path d="M180.81 77.9496C180.81 81.1297 180.058 83.8473 178.555 86.1023C177.051 88.2995 174.796 89.9763 171.79 91.1327C168.783 92.2891 165.053 92.8673 160.601 92.8673C157.305 92.8673 154.472 92.636 152.102 92.1735C149.731 91.7687 147.36 91.0749 144.99 90.0919V79.424C147.534 80.5804 150.28 81.5345 153.229 82.2861C156.178 83.0378 158.78 83.4136 161.035 83.4136C163.579 83.4136 165.371 83.0378 166.412 82.2861C167.511 81.5345 168.06 80.5515 168.06 79.3373C168.06 78.5278 167.829 77.805 167.366 77.169C166.961 76.533 166.036 75.8102 164.591 75.0007C163.145 74.1912 160.89 73.1505 157.826 71.8784C154.877 70.6064 152.448 69.3632 150.54 68.149C148.632 66.8769 147.216 65.3736 146.291 63.639C145.365 61.8465 144.903 59.6204 144.903 56.9607C144.903 52.5663 146.609 49.2705 150.02 47.0733C153.431 44.8762 157.97 43.7776 163.637 43.7776C166.586 43.7776 169.39 44.0667 172.05 44.6449C174.709 45.2231 177.456 46.1771 180.289 47.507L176.386 56.7872C174.825 56.0934 173.322 55.4863 171.876 54.9659C170.431 54.4455 169.014 54.0407 167.626 53.7516C166.297 53.4625 164.909 53.318 163.463 53.318C161.555 53.318 160.11 53.5782 159.127 54.0986C158.202 54.6189 157.739 55.3995 157.739 56.4403C157.739 57.192 157.97 57.8858 158.433 58.5218C158.953 59.1 159.907 59.7361 161.295 60.4299C162.741 61.1238 164.851 62.0489 167.626 63.2053C170.344 64.3039 172.686 65.4603 174.652 66.6745C176.618 67.831 178.121 69.3054 179.162 71.0978C180.26 72.8325 180.81 75.1164 180.81 77.9496ZM234.329 44.6449V92H224.441L222.707 85.9288H222.013C221.03 87.5478 219.758 88.8777 218.197 89.9185C216.693 90.9014 215.017 91.6242 213.166 92.0867C211.316 92.6071 209.408 92.8673 207.442 92.8673C204.088 92.8673 201.14 92.2602 198.595 91.046C196.051 89.8317 194.085 87.9526 192.698 85.4084C191.31 82.8643 190.616 79.5686 190.616 75.5211V44.6449H203.539V72.3121C203.539 75.6657 204.146 78.2098 205.36 79.9444C206.575 81.679 208.512 82.5463 211.171 82.5463C213.831 82.5463 215.884 81.9392 217.329 80.725C218.833 79.5107 219.873 77.7472 220.452 75.4344C221.088 73.1216 221.406 70.2883 221.406 66.9347V44.6449H234.329ZM274.331 43.7776C274.967 43.7776 275.719 43.8065 276.586 43.8643C277.454 43.9221 278.147 44.0089 278.668 44.1245L277.714 56.2668C277.309 56.1512 276.702 56.0645 275.892 56.0066C275.141 55.891 274.476 55.8332 273.898 55.8332C272.221 55.8332 270.602 56.0645 269.041 56.527C267.48 56.9318 266.063 57.5967 264.791 58.5218C263.577 59.447 262.594 60.6901 261.842 62.2513C261.148 63.7546 260.801 65.6338 260.801 67.8888V92H247.878V44.6449H257.679L259.587 52.6241H260.194C261.119 51.0052 262.276 49.5307 263.663 48.2009C265.051 46.871 266.641 45.8013 268.434 44.9918C270.284 44.1823 272.25 43.7776 274.331 43.7776ZM298.538 92L280.498 44.6449H294.028L303.135 71.6182C303.482 72.659 303.771 73.7576 304.002 74.914C304.291 76.0704 304.494 77.1979 304.609 78.2965C304.783 79.3951 304.898 80.407 304.956 81.3321H305.303C305.361 80.3491 305.477 79.3084 305.65 78.2098C305.823 77.1112 306.026 76.0126 306.257 74.914C306.546 73.7576 306.864 72.659 307.211 71.6182L316.318 44.6449H329.848L311.808 92H298.538ZM356.157 43.7776C360.551 43.7776 364.309 44.616 367.432 46.2928C370.612 47.9696 373.069 50.398 374.804 53.5782C376.538 56.7583 377.406 60.6612 377.406 65.2869V71.5315H346.876C346.992 75.1742 348.062 78.0363 350.085 80.1179C352.167 82.1994 355.029 83.2402 358.672 83.2402C361.736 83.2402 364.512 82.9511 366.998 82.3729C369.484 81.7368 372.057 80.7828 374.717 79.5107V89.4848C372.404 90.6412 369.947 91.4796 367.345 92C364.801 92.5782 361.707 92.8673 358.065 92.8673C353.323 92.8673 349.131 92 345.489 90.2654C341.846 88.4729 338.984 85.7843 336.902 82.1994C334.821 78.6145 333.78 74.1045 333.78 68.6694C333.78 63.1186 334.705 58.5218 336.555 54.8791C338.463 51.1786 341.094 48.4032 344.448 46.553C347.801 44.7027 351.704 43.7776 356.157 43.7776ZM356.243 52.9711C353.757 52.9711 351.675 53.7805 349.999 55.3995C348.38 57.0185 347.426 59.5337 347.137 62.9451H365.263C365.263 61.037 364.916 59.3313 364.223 57.828C363.586 56.3247 362.604 55.1393 361.274 54.272C359.944 53.4047 358.267 52.9711 356.243 52.9711ZM400.807 44.6449V92H387.884V44.6449H400.807ZM394.389 26.0844C396.297 26.0844 397.945 26.547 399.333 27.4721C400.721 28.3395 401.415 29.9873 401.415 32.4158C401.415 34.7865 400.721 36.4343 399.333 37.3595C397.945 38.2846 396.297 38.7472 394.389 38.7472C392.423 38.7472 390.747 38.2846 389.359 37.3595C388.029 36.4343 387.364 34.7865 387.364 32.4158C387.364 29.9873 388.029 28.3395 389.359 27.4721C390.747 26.547 392.423 26.0844 394.389 26.0844ZM427.233 92H414.31V26.0844H427.233V92Z" fill="#333333"/> <path d="M467.189 43.7776C467.825 43.7776 468.577 43.8065 469.444 43.8643C470.311 43.9221 471.005 44.0089 471.526 44.1245L470.572 56.2668C470.167 56.1512 469.56 56.0645 468.75 56.0066C467.999 55.891 467.334 55.8332 466.756 55.8332C465.079 55.8332 463.46 56.0645 461.899 56.527C460.337 56.9318 458.921 57.5967 457.649 58.5218C456.435 59.447 455.452 60.6901 454.7 62.2513C454.006 63.7546 453.659 65.6338 453.659 67.8888V92H440.736V44.6449H450.537L452.445 52.6241H453.052C453.977 51.0052 455.134 49.5307 456.521 48.2009C457.909 46.871 459.499 45.8013 461.291 44.9918C463.142 44.1823 465.108 43.7776 467.189 43.7776Z" fill="#AE885C"/> <path d="M144.864 128V113.117H147.134V115.373C147.713 114.318 148.246 113.622 148.732 113.285C149.227 112.949 149.769 112.781 150.357 112.781C151.208 112.781 152.072 113.052 152.95 113.594L152.081 115.934C151.464 115.57 150.848 115.387 150.231 115.387C149.68 115.387 149.185 115.556 148.746 115.892C148.307 116.219 147.994 116.677 147.807 117.265C147.527 118.162 147.386 119.143 147.386 120.208V128H144.864ZM167.508 123.207L170.114 123.53C169.703 125.052 168.942 126.234 167.83 127.075C166.718 127.916 165.298 128.336 163.57 128.336C161.393 128.336 159.664 127.668 158.385 126.332C157.114 124.987 156.479 123.104 156.479 120.685C156.479 118.181 157.123 116.238 158.413 114.855C159.702 113.472 161.374 112.781 163.43 112.781C165.42 112.781 167.045 113.458 168.306 114.813C169.568 116.168 170.198 118.073 170.198 120.531C170.198 120.68 170.194 120.904 170.184 121.203H159.085C159.179 122.838 159.641 124.09 160.473 124.959C161.304 125.828 162.341 126.262 163.584 126.262C164.509 126.262 165.298 126.019 165.952 125.534C166.606 125.048 167.125 124.272 167.508 123.207ZM159.225 119.129H167.536C167.424 117.877 167.106 116.938 166.583 116.312C165.779 115.341 164.738 114.855 163.458 114.855C162.299 114.855 161.323 115.243 160.529 116.018C159.744 116.794 159.309 117.831 159.225 119.129ZM175.156 123.558L177.651 123.165C177.791 124.165 178.179 124.931 178.814 125.463C179.459 125.996 180.356 126.262 181.505 126.262C182.663 126.262 183.523 126.029 184.083 125.562C184.644 125.085 184.924 124.529 184.924 123.894C184.924 123.324 184.677 122.876 184.181 122.549C183.836 122.324 182.976 122.039 181.603 121.694C179.753 121.227 178.468 120.825 177.749 120.489C177.039 120.143 176.497 119.671 176.123 119.073C175.759 118.466 175.577 117.798 175.577 117.069C175.577 116.406 175.726 115.794 176.025 115.233C176.334 114.663 176.749 114.192 177.273 113.818C177.665 113.528 178.197 113.285 178.87 113.089C179.552 112.884 180.281 112.781 181.056 112.781C182.224 112.781 183.247 112.949 184.125 113.285C185.013 113.622 185.667 114.079 186.087 114.659C186.508 115.229 186.797 115.995 186.956 116.957L184.49 117.293C184.378 116.527 184.051 115.929 183.509 115.5C182.976 115.07 182.219 114.855 181.238 114.855C180.08 114.855 179.253 115.046 178.758 115.429C178.263 115.813 178.015 116.261 178.015 116.775C178.015 117.102 178.118 117.396 178.324 117.658C178.529 117.929 178.851 118.153 179.291 118.33C179.543 118.424 180.286 118.639 181.519 118.975C183.303 119.451 184.546 119.844 185.246 120.152C185.956 120.451 186.512 120.89 186.914 121.469C187.316 122.049 187.517 122.768 187.517 123.628C187.517 124.468 187.269 125.263 186.774 126.01C186.288 126.748 185.583 127.323 184.658 127.734C183.733 128.135 182.687 128.336 181.519 128.336C179.585 128.336 178.109 127.935 177.09 127.131C176.081 126.328 175.437 125.136 175.156 123.558ZM192.447 120.559C192.447 117.803 193.213 115.761 194.745 114.434C196.025 113.332 197.585 112.781 199.426 112.781C201.472 112.781 203.144 113.454 204.443 114.799C205.741 116.135 206.391 117.985 206.391 120.348C206.391 122.264 206.101 123.772 205.522 124.875C204.952 125.968 204.116 126.818 203.013 127.425C201.92 128.033 200.724 128.336 199.426 128.336C197.342 128.336 195.656 127.668 194.367 126.332C193.087 124.996 192.447 123.072 192.447 120.559ZM195.039 120.559C195.039 122.464 195.455 123.894 196.287 124.847C197.118 125.79 198.165 126.262 199.426 126.262C200.678 126.262 201.719 125.786 202.551 124.833C203.382 123.88 203.798 122.427 203.798 120.475C203.798 118.634 203.378 117.242 202.537 116.298C201.705 115.345 200.668 114.869 199.426 114.869C198.165 114.869 197.118 115.341 196.287 116.284C195.455 117.228 195.039 118.653 195.039 120.559ZM221.985 128V125.814C220.827 127.495 219.253 128.336 217.263 128.336C216.385 128.336 215.562 128.168 214.796 127.832C214.04 127.495 213.474 127.075 213.101 126.571C212.736 126.057 212.479 125.431 212.33 124.693C212.227 124.198 212.176 123.413 212.176 122.338V113.117H214.698V121.371C214.698 122.689 214.75 123.576 214.852 124.034C215.011 124.697 215.347 125.221 215.861 125.604C216.375 125.977 217.01 126.164 217.767 126.164C218.524 126.164 219.234 125.973 219.897 125.59C220.561 125.197 221.028 124.669 221.299 124.006C221.579 123.333 221.719 122.362 221.719 121.091V113.117H224.242V128H221.985ZM231.05 128V113.117H233.32V115.373C233.899 114.318 234.432 113.622 234.918 113.285C235.413 112.949 235.955 112.781 236.543 112.781C237.393 112.781 238.257 113.052 239.136 113.594L238.267 115.934C237.65 115.57 237.034 115.387 236.417 115.387C235.866 115.387 235.371 115.556 234.932 115.892C234.492 116.219 234.179 116.677 233.993 117.265C233.712 118.162 233.572 119.143 233.572 120.208V128H231.05ZM253.217 122.549L255.697 122.871C255.426 124.581 254.73 125.921 253.609 126.893C252.498 127.855 251.129 128.336 249.503 128.336C247.467 128.336 245.827 127.673 244.584 126.346C243.351 125.01 242.734 123.1 242.734 120.615C242.734 119.008 243.001 117.602 243.533 116.396C244.066 115.191 244.874 114.29 245.958 113.692C247.051 113.084 248.237 112.781 249.517 112.781C251.134 112.781 252.456 113.192 253.483 114.014C254.511 114.827 255.17 115.985 255.459 117.49L253.007 117.868C252.773 116.868 252.357 116.116 251.759 115.612C251.171 115.107 250.456 114.855 249.615 114.855C248.345 114.855 247.312 115.313 246.518 116.228C245.724 117.135 245.327 118.573 245.327 120.545C245.327 122.544 245.71 123.997 246.476 124.903C247.242 125.809 248.242 126.262 249.475 126.262C250.466 126.262 251.292 125.959 251.956 125.351C252.619 124.744 253.039 123.81 253.217 122.549ZM270.914 123.207L273.52 123.53C273.109 125.052 272.348 126.234 271.236 127.075C270.124 127.916 268.704 128.336 266.976 128.336C264.799 128.336 263.071 127.668 261.791 126.332C260.52 124.987 259.885 123.104 259.885 120.685C259.885 118.181 260.529 116.238 261.819 114.855C263.108 113.472 264.78 112.781 266.836 112.781C268.826 112.781 270.451 113.458 271.713 114.813C272.974 116.168 273.604 118.073 273.604 120.531C273.604 120.68 273.6 120.904 273.59 121.203H262.491C262.585 122.838 263.047 124.09 263.879 124.959C264.71 125.828 265.747 126.262 266.99 126.262C267.915 126.262 268.704 126.019 269.358 125.534C270.012 125.048 270.531 124.272 270.914 123.207ZM262.631 119.129H270.942C270.83 117.877 270.512 116.938 269.989 116.312C269.185 115.341 268.144 114.855 266.864 114.855C265.705 114.855 264.729 115.243 263.935 116.018C263.15 116.794 262.716 117.831 262.631 119.129ZM289.421 123.558L291.915 123.165C292.055 124.165 292.443 124.931 293.078 125.463C293.723 125.996 294.62 126.262 295.769 126.262C296.927 126.262 297.787 126.029 298.347 125.562C298.908 125.085 299.188 124.529 299.188 123.894C299.188 123.324 298.941 122.876 298.446 122.549C298.1 122.324 297.24 122.039 295.867 121.694C294.017 121.227 292.733 120.825 292.013 120.489C291.303 120.143 290.761 119.671 290.388 119.073C290.023 118.466 289.841 117.798 289.841 117.069C289.841 116.406 289.99 115.794 290.289 115.233C290.598 114.663 291.013 114.192 291.537 113.818C291.929 113.528 292.462 113.285 293.134 113.089C293.816 112.884 294.545 112.781 295.32 112.781C296.488 112.781 297.511 112.949 298.389 113.285C299.277 113.622 299.931 114.079 300.351 114.659C300.772 115.229 301.061 115.995 301.22 116.957L298.754 117.293C298.642 116.527 298.315 115.929 297.773 115.5C297.24 115.07 296.484 114.855 295.503 114.855C294.344 114.855 293.517 115.046 293.022 115.429C292.527 115.813 292.279 116.261 292.279 116.775C292.279 117.102 292.382 117.396 292.588 117.658C292.793 117.929 293.116 118.153 293.555 118.33C293.807 118.424 294.55 118.639 295.783 118.975C297.567 119.451 298.81 119.844 299.511 120.152C300.221 120.451 300.777 120.89 301.178 121.469C301.58 122.049 301.781 122.768 301.781 123.628C301.781 124.468 301.533 125.263 301.038 126.01C300.552 126.748 299.847 127.323 298.922 127.734C297.997 128.135 296.951 128.336 295.783 128.336C293.849 128.336 292.373 127.935 291.354 127.131C290.345 126.328 289.701 125.136 289.421 123.558ZM317.404 128V125.814C316.245 127.495 314.671 128.336 312.681 128.336C311.803 128.336 310.981 128.168 310.214 127.832C309.458 127.495 308.892 127.075 308.519 126.571C308.154 126.057 307.897 125.431 307.748 124.693C307.645 124.198 307.594 123.413 307.594 122.338V113.117H310.116V121.371C310.116 122.689 310.168 123.576 310.271 124.034C310.429 124.697 310.766 125.221 311.28 125.604C311.793 125.977 312.429 126.164 313.185 126.164C313.942 126.164 314.652 125.973 315.316 125.59C315.979 125.197 316.446 124.669 316.717 124.006C316.997 123.333 317.137 122.362 317.137 121.091V113.117H319.66V128H317.404ZM326.468 128V113.117H328.738V115.373C329.317 114.318 329.85 113.622 330.336 113.285C330.831 112.949 331.373 112.781 331.961 112.781C332.811 112.781 333.676 113.052 334.554 113.594L333.685 115.934C333.068 115.57 332.452 115.387 331.835 115.387C331.284 115.387 330.789 115.556 330.35 115.892C329.911 116.219 329.598 116.677 329.411 117.265C329.13 118.162 328.99 119.143 328.99 120.208V128H326.468ZM343.058 128L337.396 113.117H340.059L343.254 122.03C343.599 122.992 343.917 123.992 344.207 125.029C344.431 124.244 344.744 123.301 345.146 122.198L348.453 113.117H351.046L345.412 128H343.058ZM366.332 123.207L368.939 123.53C368.527 125.052 367.766 126.234 366.654 127.075C365.542 127.916 364.122 128.336 362.394 128.336C360.217 128.336 358.489 127.668 357.209 126.332C355.938 124.987 355.303 123.104 355.303 120.685C355.303 118.181 355.948 116.238 357.237 114.855C358.526 113.472 360.198 112.781 362.254 112.781C364.244 112.781 365.869 113.458 367.131 114.813C368.392 116.168 369.023 118.073 369.023 120.531C369.023 120.68 369.018 120.904 369.009 121.203H357.91C358.003 122.838 358.465 124.09 359.297 124.959C360.128 125.828 361.165 126.262 362.408 126.262C363.333 126.262 364.122 126.019 364.776 125.534C365.43 125.048 365.949 124.272 366.332 123.207ZM358.05 119.129H366.36C366.248 117.877 365.93 116.938 365.407 116.312C364.604 115.341 363.562 114.855 362.282 114.855C361.123 114.855 360.147 115.243 359.353 116.018C358.568 116.794 358.134 117.831 358.05 119.129ZM375.004 110.356V107.456H377.526V110.356H375.004ZM375.004 128V113.117H377.526V128H375.004ZM384.194 128V107.456H386.717V128H384.194ZM393.455 128V107.456H395.977V128H393.455ZM412.483 126.164C411.548 126.958 410.647 127.519 409.778 127.846C408.918 128.173 407.994 128.336 407.003 128.336C405.368 128.336 404.112 127.939 403.233 127.145C402.355 126.342 401.916 125.319 401.916 124.076C401.916 123.347 402.08 122.684 402.407 122.086C402.743 121.479 403.177 120.993 403.71 120.629C404.252 120.264 404.859 119.989 405.532 119.802C406.027 119.671 406.774 119.545 407.774 119.423C409.811 119.181 411.31 118.891 412.272 118.555C412.282 118.209 412.286 117.989 412.286 117.896C412.286 116.868 412.048 116.144 411.572 115.724C410.927 115.154 409.97 114.869 408.699 114.869C407.512 114.869 406.634 115.079 406.064 115.5C405.504 115.911 405.088 116.644 404.817 117.7L402.351 117.363C402.575 116.308 402.944 115.458 403.458 114.813C403.972 114.159 404.714 113.659 405.686 113.313C406.658 112.958 407.783 112.781 409.063 112.781C410.334 112.781 411.366 112.93 412.16 113.229C412.954 113.528 413.538 113.907 413.912 114.364C414.286 114.813 414.547 115.383 414.697 116.074C414.781 116.504 414.823 117.279 414.823 118.4V121.764C414.823 124.109 414.874 125.594 414.977 126.22C415.089 126.837 415.304 127.43 415.622 128H412.987C412.726 127.477 412.557 126.865 412.483 126.164ZM412.272 120.531C411.357 120.904 409.984 121.222 408.152 121.484C407.115 121.633 406.382 121.801 405.952 121.988C405.522 122.175 405.191 122.45 404.957 122.815C404.724 123.17 404.607 123.567 404.607 124.006C404.607 124.679 404.859 125.239 405.364 125.688C405.877 126.136 406.625 126.36 407.606 126.36C408.577 126.36 409.442 126.15 410.198 125.73C410.955 125.3 411.511 124.716 411.866 123.978C412.137 123.408 412.272 122.567 412.272 121.455V120.531ZM421.617 128V113.117H423.887V115.233C424.98 113.598 426.559 112.781 428.624 112.781C429.521 112.781 430.343 112.944 431.09 113.271C431.847 113.589 432.412 114.009 432.786 114.533C433.16 115.056 433.421 115.677 433.571 116.396C433.664 116.864 433.711 117.681 433.711 118.849V128H431.189V118.947C431.189 117.919 431.09 117.153 430.894 116.649C430.698 116.135 430.348 115.728 429.843 115.429C429.348 115.121 428.764 114.967 428.091 114.967C427.017 114.967 426.087 115.308 425.303 115.99C424.527 116.672 424.139 117.966 424.139 119.872V128H421.617ZM450.175 122.549L452.655 122.871C452.384 124.581 451.688 125.921 450.567 126.893C449.455 127.855 448.087 128.336 446.461 128.336C444.424 128.336 442.785 127.673 441.542 126.346C440.309 125.01 439.692 123.1 439.692 120.615C439.692 119.008 439.958 117.602 440.491 116.396C441.023 115.191 441.832 114.29 442.915 113.692C444.008 113.084 445.195 112.781 446.475 112.781C448.091 112.781 449.413 113.192 450.441 114.014C451.469 114.827 452.127 115.985 452.417 117.49L449.964 117.868C449.731 116.868 449.315 116.116 448.717 115.612C448.129 115.107 447.414 114.855 446.573 114.855C445.302 114.855 444.27 115.313 443.476 116.228C442.682 117.135 442.285 118.573 442.285 120.545C442.285 122.544 442.668 123.997 443.434 124.903C444.2 125.809 445.2 126.262 446.433 126.262C447.423 126.262 448.25 125.959 448.913 125.351C449.577 124.744 449.997 123.81 450.175 122.549ZM467.871 123.207L470.478 123.53C470.067 125.052 469.306 126.234 468.194 127.075C467.082 127.916 465.662 128.336 463.934 128.336C461.757 128.336 460.028 127.668 458.748 126.332C457.478 124.987 456.842 123.104 456.842 120.685C456.842 118.181 457.487 116.238 458.776 114.855C460.066 113.472 461.738 112.781 463.793 112.781C465.783 112.781 467.409 113.458 468.67 114.813C469.931 116.168 470.562 118.073 470.562 120.531C470.562 120.68 470.557 120.904 470.548 121.203H459.449C459.542 122.838 460.005 124.09 460.836 124.959C461.668 125.828 462.705 126.262 463.948 126.262C464.872 126.262 465.662 126.019 466.316 125.534C466.97 125.048 467.488 124.272 467.871 123.207ZM459.589 119.129H467.899C467.787 117.877 467.47 116.938 466.947 116.312C466.143 115.341 465.101 114.855 463.821 114.855C462.663 114.855 461.687 115.243 460.892 116.018C460.108 116.794 459.673 117.831 459.589 119.129Z" fill="#808080"/> </svg> </a> <a class="docs-logo astro-cdy74xqe" href="docs.html" aria-label="Survelir Docs"><svg viewBox="0 0 275 104" width="275" height="104" fill="none" style="height: 1.5rem; margin-bottom: 0.2rem;" xmlns="http://www.w3.org/2000/svg"> <path d="M69.312 69.616C69.312 79.1733 65.984 87.28 59.328 93.936C52.7573 100.592 44.6933 103.92 35.136 103.92C25.4933 103.92 17.344 100.635 10.688 94.064C4.11733 87.408 0.832001 79.2587 0.832001 69.616C0.832001 60.0587 4.16 51.9947 10.816 45.424C17.472 38.768 25.5787 35.44 35.136 35.44C41.1947 35.44 46.8267 36.9333 52.032 39.92V0.623993H69.312V69.616ZM52.032 69.616C52.032 65.008 50.368 61.04 47.04 57.712C43.712 54.384 39.744 52.72 35.136 52.72C30.4427 52.72 26.432 54.384 23.104 57.712C19.776 60.9547 18.112 64.9227 18.112 69.616C18.112 74.3093 19.776 78.32 23.104 81.648C26.432 84.976 30.4427 86.64 35.136 86.64C39.8293 86.64 43.7973 84.976 47.04 81.648C50.368 78.32 52.032 74.3093 52.032 69.616ZM146.562 69.616C146.562 79.1733 143.234 87.28 136.578 93.936C130.007 100.592 121.943 103.92 112.386 103.92C102.743 103.92 94.594 100.635 87.938 94.064C81.3673 87.408 78.082 79.2587 78.082 69.616C78.082 60.0587 81.41 51.9947 88.066 45.424C94.722 38.768 102.829 35.44 112.386 35.44C121.943 35.44 130.007 38.768 136.578 45.424C143.234 51.9947 146.562 60.0587 146.562 69.616ZM129.282 69.616C129.282 65.008 127.618 61.04 124.29 57.712C120.962 54.384 116.994 52.72 112.386 52.72C107.693 52.72 103.682 54.384 100.354 57.712C97.026 60.9547 95.362 64.9227 95.362 69.616C95.362 74.3093 97.026 78.32 100.354 81.648C103.682 84.976 107.693 86.64 112.386 86.64C117.079 86.64 121.047 84.976 124.29 81.648C127.618 78.32 129.282 74.3093 129.282 69.616ZM213.566 94.32C206.91 100.72 199.017 103.92 189.886 103.92C180.243 103.92 172.094 100.635 165.438 94.064C158.867 87.408 155.582 79.2587 155.582 69.616C155.582 60.0587 158.91 51.9947 165.566 45.424C172.222 38.768 180.329 35.44 189.886 35.44C198.59 35.44 206.185 38.384 212.67 44.272L202.302 58.224C198.974 54.5547 194.835 52.72 189.886 52.72C185.193 52.72 181.182 54.384 177.854 57.712C174.526 60.9547 172.862 64.9227 172.862 69.616C172.862 74.3093 174.526 78.32 177.854 81.648C181.182 84.976 185.193 86.64 189.886 86.64C195.006 86.64 199.23 84.6773 202.558 80.752L213.566 94.32ZM274.05 82.416C274.05 86.512 272.685 90.224 269.954 93.552C264.493 100.208 256.727 103.408 246.658 103.152C242.647 103.067 238.253 102.171 233.474 100.464C228.781 98.7573 224.941 96.624 221.954 94.064L231.554 81.648C236.162 86 241.069 88.176 246.274 88.176H246.658C248.791 88.176 250.711 87.792 252.418 87.024C254.637 86 255.746 84.5493 255.746 82.672V82.16C255.49 80.1973 254.167 78.7893 251.778 77.936C250.839 77.7653 248.834 77.3813 245.762 76.784C241.922 76.016 238.679 75.0773 236.034 73.968C228.269 70.64 224.386 64.7947 224.386 56.432C224.386 48.4107 228.354 42.3947 236.29 38.384C239.789 36.592 243.586 35.6533 247.682 35.568C251.949 35.4827 256.386 36.208 260.994 37.744C266.285 39.536 270.039 41.8827 272.258 44.784L260.738 55.152C257.751 52.1653 254.509 50.672 251.01 50.672C245.549 50.672 242.818 52.464 242.818 56.048V56.304C242.818 58.0107 245.037 59.4613 249.474 60.656C249.815 60.7413 252.631 61.296 257.922 62.32C268.674 64.368 274.05 70.9387 274.05 82.032V82.416Z" class="docs-logo-svg" fill="#404040"/> <style> [data-theme="dark"] .docs-logo-svg { fill: #d4d4d4; } </style> </svg> </a> </span> </div> <div class="sl-flex print:hidden astro-kmkmnagf"> <site-search class="astro-kmkmnagf astro-v37mnknz" data-translations="{"placeholder":"Search"}"> <button data-open-modal disabled aria-label="Search" aria-keyshortcuts="Control+K" class="astro-v37mnknz"> <svg aria-hidden="true" class="astro-v37mnknz astro-c6vsoqas" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M21.71 20.29 18 16.61A9 9 0 1 0 16.61 18l3.68 3.68a.999.999 0 0 0 1.42 0 1 1 0 0 0 0-1.39ZM11 18a7 7 0 1 1 0-14 7 7 0 0 1 0 14Z"/></svg> <span class="sl-hidden md:sl-block astro-v37mnknz" aria-hidden="true">Search</span> <kbd class="sl-hidden md:sl-flex astro-v37mnknz" style="display: none;"> <kbd class="astro-v37mnknz">Ctrl</kbd><kbd class="astro-v37mnknz">K</kbd> </kbd> </button> <dialog style="padding:0" aria-label="Search" class="astro-v37mnknz"> <div class="dialog-frame sl-flex astro-v37mnknz"> <button data-close-modal class="sl-flex md:sl-hidden astro-v37mnknz"> Cancel </button> <div class="search-container astro-v37mnknz"> <div id="starlight__search" class="astro-v37mnknz"></div> </div> </div> </dialog> </site-search> <script> (() => { const openBtn = document.querySelector('button[data-open-modal]'); const shortcut = openBtn?.querySelector('kbd'); if (!openBtn || !(shortcut instanceof HTMLElement)) return; const platformKey = shortcut.querySelector('kbd'); if (platformKey && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) { platformKey.textContent = '⌘'; openBtn.setAttribute('aria-keyshortcuts', 'Meta+K'); } shortcut.style.display = ''; })(); </script> <script type="module" src="_astro/Search.astro_astro_type_script_index_0_lang.18-vQxR-.js"></script> </div> <div class="sl-hidden md:sl-flex print:hidden right-group astro-kmkmnagf"> <div class="sl-flex social-icons astro-kmkmnagf"> <a href="https://github.com/surveilr" rel="me" class="sl-flex astro-wy4te6ga"><span class="sr-only astro-wy4te6ga">GitHub</span><svg aria-hidden="true" class="astro-wy4te6ga astro-c6vsoqas" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z"/></svg> </a> </div> <!-- Dark Theme Toggle Button --><button type="button" aria-label="Dark Theme Toggle" id="dark-theme-toggle" class="group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400" data-hs-theme-click-value="dark"> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path> </svg> </button> <!-- Light Theme Toggle Button --> <button type="button" aria-label="Light Theme Toggle" id="light-theme-toggle" class="group flex hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-400 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-700 hover:text-orange-400" data-hs-theme-click-value="light"> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="4"></circle> <path d="M12 8a2 2 0 1 0 4 4"></path> <path d="M12 2v2"></path> <path d="M12 20v2"></path> <path d="m4.93 4.93 1.41 1.41"></path> <path d="m17.66 17.66 1.41 1.41"></path> <path d="M2 12h2"></path> <path d="M20 12h2"></path> <path d="m6.34 17.66-1.41 1.41"></path> <path d="m19.07 4.93-1.41 1.41"></path> </svg> </button> <script type="module">function d(e){document.documentElement.setAttribute("data-theme",e),localStorage.setItem("starlight-theme",e),o(e)}function o(e){const t=document.getElementById("dark-theme-toggle"),n=document.getElementById("light-theme-toggle");e==="dark"?(t?.classList.add("hidden"),n?.classList.remove("hidden")):(t?.classList.remove("hidden"),n?.classList.add("hidden"))}document.getElementById("dark-theme-toggle")?.addEventListener("click",()=>{d("dark")});document.getElementById("light-theme-toggle")?.addEventListener("click",()=>{d("light")});document.addEventListener("DOMContentLoaded",()=>{const t=localStorage.getItem("starlight-theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");d(t)});</script> <script type="module">class s extends HTMLElement{constructor(){super();const e=this.querySelector("select");e&&(e.addEventListener("change",t=>{t.currentTarget instanceof HTMLSelectElement&&(window.location.pathname=t.currentTarget.value)}),window.addEventListener("pageshow",t=>{if(!t.persisted)return;const n=e.querySelector("option[selected]")?.index;n!==e.selectedIndex&&(e.selectedIndex=n??0)}))}}customElements.define("starlight-lang-select",s);</script> </div> </div> </header> <div class="main-frame astro-vrdttmbt"> <script type="module">const a=document.getElementById("starlight__sidebar"),n=a?.querySelector("sl-sidebar-state-persist"),o="sl-sidebar-state",i=()=>{let t=[];const e=n?.dataset.hash||"";try{const s=sessionStorage.getItem(o),r=JSON.parse(s||"{}");Array.isArray(r.open)&&r.hash===e&&(t=r.open)}catch{}return{hash:e,open:t,scroll:a?.scrollTop||0}},c=t=>{try{sessionStorage.setItem(o,JSON.stringify(t))}catch{}},d=()=>c(i()),l=(t,e)=>{const s=i();s.open[e]=t,c(s)};n?.addEventListener("click",t=>{if(!(t.target instanceof Element))return;const e=t.target.closest("summary")?.closest("details");if(!e)return;const s=e.querySelector("sl-sidebar-restore"),r=parseInt(s?.dataset.index||"");isNaN(r)||l(!e.open,r)});addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&d()});addEventListener("pageHide",d);</script> <div class="lg:sl-flex astro-67yu43on"> <div class="main-pane astro-67yu43on"> <main data-pagefind-body class="astro-bguv2lll" lang="en" dir="ltr"> <div class="content-panel astro-7nkwcw3z"> <div class="sl-container astro-7nkwcw3z"> <div class="hero astro-jbfsktt5"> <img src="_astro/surveilr-logo-with-subtitle.Bolv885d_Z1W3H0m.webp" loading="eager" decoding="async" alt="A Survelir's Logo" width="400" height="400" class="light:sl-hidden astro-jbfsktt5"> <img src="_astro/surveilr-logo-with-subtitle.Bolv885d_Z1W3H0m.webp" loading="eager" decoding="async" alt="A Survelir's Logo" width="400" height="400" class="dark:sl-hidden astro-jbfsktt5"> <div class="sl-flex stack astro-jbfsktt5"> <div class="sl-flex copy astro-jbfsktt5"> <h1 id="_top" data-page-title class="astro-jbfsktt5">Welcome to Resource Surveliance Documentation</h1> </div> <div class="sl-flex actions astro-jbfsktt5"> <a class="sl-link-button not-content primary astro-jbfsktt5 astro-xwgiixxa" href="docs/core/what-is-surveilr.html"> Resource Surveillance <svg aria-hidden="true" class="astro-xwgiixxa astro-c6vsoqas" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M17.92 11.62a1.001 1.001 0 0 0-.21-.33l-5-5a1.003 1.003 0 1 0-1.42 1.42l3.3 3.29H7a1 1 0 0 0 0 2h7.59l-3.3 3.29a1.002 1.002 0 0 0 .325 1.639 1 1 0 0 0 1.095-.219l5-5a1 1 0 0 0 .21-.33 1 1 0 0 0 0-.76Z"/></svg> </a> <a class="sl-link-button not-content primary astro-jbfsktt5 astro-xwgiixxa" href="https://github.com/surveilr"> View on GitHub <svg aria-hidden="true" class="astro-xwgiixxa astro-c6vsoqas" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M19.33 10.18a1 1 0 0 1-.77 0 1 1 0 0 1-.62-.93l.01-1.83-8.2 8.2a1 1 0 0 1-1.41-1.42l8.2-8.2H14.7a1 1 0 0 1 0-2h4.25a1 1 0 0 1 1 1v4.25a1 1 0 0 1-.62.93Z"/><path d="M11 4a1 1 0 1 1 0 2H7a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-4a1 1 0 1 1 2 0v4a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h4Z"/></svg> </a> </div> </div> </div> <div class="sl-markdown-content"> </div> <footer class="sl-flex astro-3yyafb3n"> <div class="meta sl-flex astro-3yyafb3n"> </div> <div class="pagination-links print:hidden astro-u2l5gyhi" dir="ltr"> </div> </footer> </div> </div> </main> </div> </div> </div> </div> </body></html> | html | 39107 | 2025-04-07 05:49:50.096999939 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTWCBAGGN37TDASZP41 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/content-assembler/index.html | e29da3e6e0e672cb3542c016c6736c1adfda46ea | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/content-assembler/"},"headline":"Surveilr Content Assembler: Streamline Curated Content for B2B Success","description":"Discover how Surveilr's Content Assembler Pattern aggregates, cleans, and scores curated content from multiple sources, transforming shared links into enriched, reusable assets for B2B marketing and community engagement.","image":"https://www.surveilr.com/_astro/content-assembler.Bv3C7Riz_Z2jshri.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-11-04T00:00:00.000Z","dateModified":"2024-11-04T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Surveilr Content Assembler: Streamline Curated Content for B2B Success","url":"https://www.surveilr.com/blog/content-assembler/","description":"Discover how Surveilr's Content Assembler Pattern aggregates, cleans, and scores curated content from multiple sources, transforming shared links into enriched, reusable assets for B2B marketing and community engagement.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Discover how Surveilr's Content Assembler Pattern aggregates, cleans, and scores curated content from multiple sources, transforming shared links into enriched, reusable assets for B2B marketing and community engagement." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/content-assembler/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/content-assembler/"><meta property="og:type" content="website"><meta property="og:title" content="Surveilr Content Assembler: Streamline Curated Content for B2B Success"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Discover how Surveilr's Content Assembler Pattern aggregates, cleans, and scores curated content from multiple sources, transforming shared links into enriched, reusable assets for B2B marketing and community engagement."><meta property="og:image" content="https://www.surveilr.com/_astro/content-assembler.Bv3C7Riz_Z2jshri.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/content-assembler/"><meta name="twitter:title" content="Surveilr Content Assembler: Streamline Curated Content for B2B Success"><meta name="twitter:description" content="Discover how Surveilr's Content Assembler Pattern aggregates, cleans, and scores curated content from multiple sources, transforming shared links into enriched, reusable assets for B2B marketing and community engagement."><meta name="twitter:image" content="https://www.surveilr.com/_astro/content-assembler.Bv3C7Riz_Z2jshri.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Surveilr Content Assembler: Streamline Curated Content for B2B Success</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="732f69a7-1d32-4f3b-be9e-925056d2219c" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="732f69a7-1d32-4f3b-be9e-925056d2219c"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Content Assembler </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/content-assembler/","name":"Content Assembler"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/geo-vl.BQ3YuuRe_ZlEYQp.avif" alt="Geo V L" draggable="false" width="901" height="1293" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Geo V L </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Nov 4, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 5 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p><strong>Maximizing Curated Content with Surveilr’s Content Assembler Pattern</strong></p> <p>In the content-driven world, staying relevant and engaging requires continuous access to authoritative and curated information from across the internet. Surveilr’s <strong>Content Assembler Pattern</strong> is designed to do exactly this: aggregate and refine valuable, user-shared content from platforms like email newsletters, Twitter, LinkedIn, and more. By cleaning, organizing, and scoring these shared links, Content Assembler provides a unified, authoritative content stream for effective reuse in B2B marketing, community building, and other professional engagements.</p> <h3 id="key-features-of-the-content-assembler-workflow">Key Features of the Content Assembler Workflow</h3> <ol> <li> <p><strong>Link Ingestion from Diverse Sources</strong></p> <ul> <li>Accepts content links from platforms including email, social media, and RSS feeds.</li> <li>Integrates with Surveilr to store links in a uniform database schema, enabling streamlined content access.</li> </ul> </li> <li> <p><strong>Link Cleaning and Normalization</strong></p> <ul> <li>Removes unnecessary query parameters, ensuring all URLs are clear of tracking and marketing strings.</li> <li>Processes short URLs and redirects to yield direct, canonical links for each piece of content.</li> </ul> </li> <li> <p><strong>Canonical Link Structuring</strong></p> <ul> <li>Standardizes URLs to a canonical form, removing inconsistencies (e.g., http/https differences) and promoting uniformity.</li> </ul> </li> <li> <p><strong>Metadata Extraction</strong></p> <ul> <li>Extracts core metadata, including page descriptions and OpenGraph data, enabling deeper content insights.</li> <li>Filters and processes content to remove ads and irrelevant elements, leaving only essential information.</li> </ul> </li> <li> <p><strong>De-Duplication and Link Scoring</strong></p> <ul> <li>Eliminates duplicate links through hashing and clusters similar links for comprehensive content indexing.</li> <li>Scores links based on source reliability, engagement metrics, and metadata quality, giving priority to the most relevant and popular content.</li> </ul> </li> <li> <p><strong>Output and Integration</strong></p> <ul> <li>Outputs a well-organized collection of scored links, available for API access, allowing for real-time content querying and insights.</li> <li>Provides enriched metadata and a ranked list of links, making it easy to filter and report on content popularity and engagement.</li> </ul> </li> </ol> <h3 id="how-content-assembler-commands-power-ingestion">How Content Assembler Commands Power Ingestion</h3> <ol> <li> <p><strong>Ingesting Email Data</strong></p> <ul> <li>Using the command: <div class="expressive-code"><link rel="stylesheet" href="../../_astro/ec.tm3va.css"><script type="module" src="../../_astro/ec.8zarh.js"></script><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">surveilr</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">ingest</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">imap</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-f=</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#ECC48D;--1:#984E4D">Inbox</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-u=</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#ECC48D;--1:#984E4D">account@test.com</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-p=</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#ECC48D;--1:#984E4D">password</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-a=</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#ECC48D;--1:#984E4D">imap.com</span><span style="--0:#D9F5DD;--1:#111111">"</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="surveilr ingest imap -f="Inbox" -u="account@test.com" -p="password" -a="imap.com""><div></div></button></div></figure></div> </li> <li>This pulls in email data, linking it within the Surveilr database to track each email’s folder, content, and message details.</li> </ul> </li> <li> <p><strong>Transforming and Saving Email Content</strong></p> <ul> <li>This command: <div class="expressive-code"><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">surveilr</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">orchestrate</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">transform-html</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">--css-select</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">email-anchors:a</span><span style="--0:#D9F5DD;--1:#111111">'</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="surveilr orchestrate transform-html --css-select 'email-anchors:a'"><div></div></button></div></figure></div> </li> <li>Selects relevant email content based on CSS selectors, transforming it into a processed format, stored in the database for easy access and analysis.</li> </ul> </li> </ol> <h3 id="simplifying-link-categorization-with-additional-tables">Simplifying Link Categorization with Additional Tables</h3> <p>Content Assembler provides tailored tables for easy categorization:</p> <ul> <li><strong>Flattened Email Anchors Table</strong> - Captures all URLs for each email’s main content links.</li> <li><strong>Subscription Management Anchors Table</strong> - Categorizes subscription actions, like “unsubscribe” and “manage preferences.”</li> <li><strong>General Email Anchors Table</strong> - Isolates general links, leaving out subscription-related URLs.</li> </ul> <h3 id="running-and-testing-surveilrs-content-assembler">Running and Testing Surveilr’s Content Assembler</h3> <ol> <li> <p><strong>Launching Surveilr’s Web UI</strong></p> <ul> <li>Initialize the environment with either of the following commands: <div class="expressive-code"><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">deno</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">run</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-A</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">./package.sql.ts</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#7FDBCA;--1:#096E72">|</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">surveilr</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">shell</span></div></div><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">surveilr</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">shell</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">./package.sql.ts</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="deno run -A ./package.sql.ts | surveilr shellsurveilr shell ./package.sql.ts"><div></div></button></div></figure></div> </li> <li>Browse to <code dir="auto">http://localhost:9000/</code> to explore Surveilr’s web UI and see the assembled data.</li> </ul> </li> <li> <p><strong>Testing for Consistency</strong></p> <ul> <li>Run automated tests with: <div class="expressive-code"><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">deno</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">test</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-A</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="deno test -A"><div></div></button></div></figure></div> </li> <li>This generates test files, databases, and folders in an <code dir="auto">assurance</code> folder for review.</li> </ul> </li> </ol> <p>The <strong>Content Assembler Pattern</strong> is a comprehensive approach to harnessing the value of pre-curated content, making it accessible and insightful for marketing, analysis, and decision-making.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Content Aggregation </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> B2B Marketing </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> RSSD </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/content-assembler/&title=Maximizing Curated Content with Surveilr’s Content Assembler Pattern"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Maximizing Curated Content with Surveilr’s Content Assembler Patternhttps://www.surveilr.com/blog/content-assembler/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/content-assembler/&title=Maximizing Curated Content with Surveilr’s Content Assembler Pattern"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 93213 | 2025-04-07 05:49:49.286005958 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTWPEB0JY2S9PDF8X3C | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/sql-based-etl-elt/index.html | 723b839fe5b04e1c7c658c00abbb05d099979cce | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/sql-based-etl-elt/"},"headline":"Leverage SQLite for Lightweight ELT in Remote Patient Monitoring Data","description":"Explore how to use SQLite and SQL views for an efficient ELT process, unifying remote patient monitoring data for seamless analysis and reporting.","image":"https://www.surveilr.com/_astro/why-stateful-integration.TtFEGayC_ZJEjbQ.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-10-08T00:00:00.000Z","dateModified":"2024-10-08T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Leverage SQLite for Lightweight ELT in Remote Patient Monitoring Data","url":"https://www.surveilr.com/blog/sql-based-etl-elt/","description":"Explore how to use SQLite and SQL views for an efficient ELT process, unifying remote patient monitoring data for seamless analysis and reporting.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Explore how to use SQLite and SQL views for an efficient ELT process, unifying remote patient monitoring data for seamless analysis and reporting." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/sql-based-etl-elt/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/sql-based-etl-elt/"><meta property="og:type" content="website"><meta property="og:title" content="Leverage SQLite for Lightweight ELT in Remote Patient Monitoring Data"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Explore how to use SQLite and SQL views for an efficient ELT process, unifying remote patient monitoring data for seamless analysis and reporting."><meta property="og:image" content="https://www.surveilr.com/_astro/why-stateful-integration.TtFEGayC_ZJEjbQ.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/sql-based-etl-elt/"><meta name="twitter:title" content="Leverage SQLite for Lightweight ELT in Remote Patient Monitoring Data"><meta name="twitter:description" content="Explore how to use SQLite and SQL views for an efficient ELT process, unifying remote patient monitoring data for seamless analysis and reporting."><meta name="twitter:image" content="https://www.surveilr.com/_astro/why-stateful-integration.TtFEGayC_ZJEjbQ.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Leverage SQLite for Lightweight ELT in Remote Patient Monitoring Data</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="aec874e4-a088-4eb1-b276-4ce4a8b4a7f9" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="aec874e4-a088-4eb1-b276-4ce4a8b4a7f9"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Sql Based Etl Elt </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/sql-based-etl-elt/","name":"Sql Based Etl Elt"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/shahid-shah.B2DFcsvR_ZITVg0.avif" alt="Shahid Shah" draggable="false" width="2818" height="2746" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Shahid N. Shah </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Oct 8, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 3 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Modern Lightweight ETL with SQLite </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>If you’re an SQL engineer trying to learn the ropes of data engineering, you might have heard the term <em>ELT</em> and wondered how it differs from <em>ETL</em>. Both are processes for integrating data from multiple sources, but ELT stands for Extract, Load, Transform, while ETL is Extract, Transform, Load. In this blog post, we will explore how to leverage SQLite and SQL views for a lightweight ELT process that integrates disparate tables into a unified view.</p> <p>Our specific use case will involve aggregating patient remote monitoring data from various devices into a single unified view for Continuous Glucose Monitoring (CGM) tracings. We’ll break down each step in a way that’s approachable and practical, giving you the tools to work with real data while keeping the infrastructure lightweight.</p> <h2 id="background-on-elt-and-why-we-use-it">Background on ELT and Why We Use It</h2> <p>The classic ETL strategy involves transforming data before loading it into your storage system, which typically requires more complex workflows, external tools, and a lot of up-front work. In contrast, ELT lets you extract the data as-is, load it into your database, and then transform it <em>in place</em>, often with SQL views, which makes it great for exploratory work or environments with less infrastructure.</p> <p>SQLite is a great fit here because it’s lightweight, widely supported, and doesn’t require complex setup—perfect for small to medium datasets or rapid prototyping.</p> <h2 id="setting-the-scene-ingesting-the-data">Setting the Scene: Ingesting the Data</h2> <p>Imagine we have data from multiple devices—perhaps CGMs, smartwatches, and other monitoring devices—that all capture remote patient monitoring data. After ingesting these data sources, we end up with tables like <code dir="auto">table_1</code>, <code dir="auto">table_2</code>, <code dir="auto">table_3</code>, and <code dir="auto">table_4</code> in our SQLite database. Each table represents a different device and has different columns, even though they all describe patient data for similar remote monitoring purposes.</p> <p>For example:</p> <ul> <li><strong>table_1</strong> has columns like <code dir="auto">patient_id</code>, <code dir="auto">device_id</code>, <code dir="auto">timestamp</code>, <code dir="auto">glucose_level</code></li> <li><strong>table_2</strong> has columns like <code dir="auto">id</code>, <code dir="auto">time_recorded</code>, <code dir="auto">patient_number</code>, <code dir="auto">cgm_value</code></li> <li><strong>table_3</strong> has columns like <code dir="auto">pat_id</code>, <code dir="auto">recorded_at</code>, <code dir="auto">glucose_reading</code>, <code dir="auto">sensor</code></li> <li><strong>table_4</strong> has columns like <code dir="auto">identifier</code>, <code dir="auto">time_taken</code>, <code dir="auto">patient_ref</code>, <code dir="auto">sugar_level</code></li> </ul> <h2 id="the-challenge-creating-a-unified-view">The Challenge: Creating a Unified View</h2> <p>We need to create a single unified view called <code dir="auto">patient_rpm_mode_cgm</code> that gives us all CGM tracings in a common format. Since ELT focuses on transforming data in place, we will write SQL to transform and union the data from these disparate tables. Our ultimate goal is to create a view that presents common column names—let’s standardize them to:</p> <ul> <li><code dir="auto">patient_id</code></li> <li><code dir="auto">timestamp</code></li> <li><code dir="auto">glucose_level</code></li> <li><code dir="auto">device_type</code> (a new column that does not exist in the physical tables)</li> <li><code dir="auto">source</code> (a new column to indicate the origin table)</li> </ul> <h3 id="step-1-understanding-the-source-tables">Step 1: Understanding the Source Tables</h3> <p>The first step in transforming this data is to understand how each source table maps to our target columns. To standardize the columns:</p> <table><thead><tr><th>Source Table</th><th>Source Columns</th><th>Target Columns</th></tr></thead><tbody><tr><td>table_1</td><td><code dir="auto">patient_id</code>, <code dir="auto">timestamp</code>, <code dir="auto">glucose_level</code></td><td><code dir="auto">patient_id</code>, <code dir="auto">timestamp</code>, <code dir="auto">glucose_level</code>, ‘CGM’ AS <code dir="auto">device_type</code>, ‘table_1’ AS <code dir="auto">source</code></td></tr><tr><td>table_2</td><td><code dir="auto">patient_number</code>, <code dir="auto">time_recorded</code>, <code dir="auto">cgm_value</code></td><td><code dir="auto">patient_id</code>, <code dir="auto">timestamp</code>, <code dir="auto">glucose_level</code>, ‘CGM’ AS <code dir="auto">device_type</code>, ‘table_2’ AS <code dir="auto">source</code></td></tr><tr><td>table_3</td><td><code dir="auto">pat_id</code>, <code dir="auto">recorded_at</code>, <code dir="auto">glucose_reading</code></td><td><code dir="auto">patient_id</code>, <code dir="auto">timestamp</code>, <code dir="auto">glucose_level</code>, ‘CGM’ AS <code dir="auto">device_type</code>, ‘table_3’ AS <code dir="auto">source</code></td></tr><tr><td>table_4</td><td><code dir="auto">patient_ref</code>, <code dir="auto">time_taken</code>, <code dir="auto">sugar_level</code></td><td><code dir="auto">patient_id</code>, <code dir="auto">timestamp</code>, <code dir="auto">glucose_level</code>, ‘CGM’ AS <code dir="auto">device_type</code>, ‘table_4’ AS <code dir="auto">source</code></td></tr></tbody></table> <h3 id="step-2-writing-the-transformation-queries">Step 2: Writing the Transformation Queries</h3> <p>We need to write queries that extract the relevant fields from each table, aliasing the columns to standardize their names, and adding new columns as needed.</p> <p>For example, to transform <code dir="auto">table_2</code>:</p> <div class="expressive-code"><link rel="stylesheet" href="../../_astro/ec.tm3va.css"><script type="module" src="../../_astro/ec.8zarh.js"></script><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_number </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">time_recorded </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">cgm_value </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">CGM</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">table_2</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">table_2;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="SELECT patient_number AS patient_id, time_recorded AS timestamp, cgm_value AS glucose_level, 'CGM' AS device_type, 'table_2' AS sourceFROM table_2;"><div></div></button></div></figure></div> <p>Similarly, for <code dir="auto">table_3</code>:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">pat_id </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">recorded_at </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">glucose_reading </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">CGM</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">table_3</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">table_3;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="SELECT pat_id AS patient_id, recorded_at AS timestamp, glucose_reading AS glucose_level, 'CGM' AS device_type, 'table_3' AS sourceFROM table_3;"><div></div></button></div></figure></div> <h3 id="step-3-combining-the-queries-with-union">Step 3: Combining the Queries with UNION</h3> <p>Next, we need to combine these transformed queries using <code dir="auto">UNION ALL</code>. Using <code dir="auto">UNION ALL</code> is appropriate here because it ensures we retain all records, even if they have duplicate values (which may be necessary for auditing or detailed analysis).</p> <p>Here’s the complete SQL to create our view:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">CREATE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">VIEW</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">patient_rpm_mode_cgm</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">CGM</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">table_1</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">table_1</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">UNION ALL</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_number </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">time_recorded </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">cgm_value </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">CGM</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">table_2</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">table_2</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">UNION ALL</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">pat_id </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">recorded_at </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">glucose_reading </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">CGM</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">table_3</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">table_3</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">UNION ALL</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_ref </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">time_taken </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">sugar_level </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">CGM</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">table_4</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">table_4</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">UNION ALL</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">unknown</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">1970-01-01 00:00:00</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#F78C6C;--1:#AA0982">0</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">CGM</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">synthetic</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> source;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="CREATE VIEW patient_rpm_mode_cgm ASSELECT patient_id, timestamp, glucose_level, 'CGM' AS device_type, 'table_1' AS sourceFROM table_1UNION ALLSELECT patient_number AS patient_id, time_recorded AS timestamp, cgm_value AS glucose_level, 'CGM' AS device_type, 'table_2' AS sourceFROM table_2UNION ALLSELECT pat_id AS patient_id, recorded_at AS timestamp, glucose_reading AS glucose_level, 'CGM' AS device_type, 'table_3' AS sourceFROM table_3UNION ALLSELECT patient_ref AS patient_id, time_taken AS timestamp, sugar_level AS glucose_level, 'CGM' AS device_type, 'table_4' AS sourceFROM table_4UNION ALLSELECT 'unknown' AS patient_id, '1970-01-01 00:00:00' AS timestamp, 0 AS glucose_level, 'CGM' AS device_type, 'synthetic' AS source;"><div></div></button></div></figure></div> <h3 id="step-4-adding-more-transformations-with-views">Step 4: Adding More Transformations with Views</h3> <p>One of the key benefits of ELT using views is the ability to easily add more transformations without altering the raw data or writing complex ETL pipelines. Here are some additional common transformations that are better handled through views:</p> <h4 id="1-standardizing-data-formats">1. Standardizing Data Formats</h4> <p>In many cases, different tables may store data in different formats. For example, timestamps might be stored in different formats or time zones. Using a view, you can standardize these formats:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">CREATE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">VIEW</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">standardized_patient_rpm_mode_cgm</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">DATETIME</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">) </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> standardized_timestamp,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_rpm_mode_cgm;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="CREATE VIEW standardized_patient_rpm_mode_cgm ASSELECT patient_id, DATETIME(timestamp) AS standardized_timestamp, glucose_level, device_type, sourceFROM patient_rpm_mode_cgm;"><div></div></button></div></figure></div> <p>This view ensures that all timestamps are in the same format, making downstream analysis much easier.</p> <h4 id="2-filtering-and-cleaning-data">2. Filtering and Cleaning Data</h4> <p>You may want to exclude certain rows from analysis, such as rows with missing or invalid data. Views are a great way to create a “clean” dataset:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">CREATE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">VIEW</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">clean_patient_rpm_mode_cgm</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_rpm_mode_cgm</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">WHERE</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">glucose_level </span><span style="--0:#C792EA;--1:#8844AE">></span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#F78C6C;--1:#AA0982">0</span><span style="--0:#D6DEEB;--1:#403F53">;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="CREATE VIEW clean_patient_rpm_mode_cgm ASSELECT patient_id, timestamp, glucose_level, device_type, sourceFROM patient_rpm_mode_cgmWHERE glucose_level > 0;"><div></div></button></div></figure></div> <p>This view filters out any rows where <code dir="auto">glucose_level</code> is 0 or negative, which may represent invalid data.</p> <h4 id="3-aggregating-data">3. Aggregating Data</h4> <p>You can also use views to create aggregate data that can be used for reporting or analysis. For example, creating a view that provides daily average glucose levels for each patient:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">CREATE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">VIEW</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">daily_avg_glucose</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">DATE</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">) </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">day</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C5E478;--1:#3B61B0">AVG</span><span style="--0:#D6DEEB;--1:#403F53">(glucose_level) </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> avg_glucose_level</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_rpm_mode_cgm</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">GROUP BY</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id, </span><span style="--0:#C792EA;--1:#8844AE">day</span><span style="--0:#D6DEEB;--1:#403F53">;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="CREATE VIEW daily_avg_glucose ASSELECT patient_id, DATE(timestamp) AS day, AVG(glucose_level) AS avg_glucose_levelFROM patient_rpm_mode_cgmGROUP BY patient_id, day;"><div></div></button></div></figure></div> <p>This aggregated view makes it easy to analyze trends over time without needing to write aggregation queries repeatedly.</p> <h4 id="4-creating-derived-metrics">4. Creating Derived Metrics</h4> <p>If you need to create new metrics based on existing columns, views are a great way to handle this. For example, you might want to create a derived metric called <code dir="auto">glucose_category</code> to categorize glucose levels:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">CREATE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">VIEW</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">patient_glucose_category</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">timestamp</span><span style="--0:#D6DEEB;--1:#403F53">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">glucose_level,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">CASE</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">WHEN</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level </span><span style="--0:#C792EA;--1:#8844AE"><</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#F78C6C;--1:#AA0982">70</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">THEN</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">Low</span><span style="--0:#D9F5DD;--1:#111111">'</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">WHEN</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level </span><span style="--0:#C792EA;--1:#8844AE">BETWEEN</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#F78C6C;--1:#AA0982">70</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AND</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#F78C6C;--1:#AA0982">140</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">THEN</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">Normal</span><span style="--0:#D9F5DD;--1:#111111">'</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">WHEN</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_level </span><span style="--0:#C792EA;--1:#8844AE">></span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#F78C6C;--1:#AA0982">140</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">THEN</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">High</span><span style="--0:#D9F5DD;--1:#111111">'</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">ELSE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">Unknown</span><span style="--0:#D9F5DD;--1:#111111">'</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">END</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> glucose_category,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">device_type,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">source</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_rpm_mode_cgm;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="CREATE VIEW patient_glucose_category ASSELECT patient_id, timestamp, glucose_level, CASE WHEN glucose_level < 70 THEN 'Low' WHEN glucose_level BETWEEN 70 AND 140 THEN 'Normal' WHEN glucose_level > 140 THEN 'High' ELSE 'Unknown' END AS glucose_category, device_type, sourceFROM patient_rpm_mode_cgm;"><div></div></button></div></figure></div> <p>This view adds a new column that categorizes glucose levels into ‘Low’, ‘Normal’, or ‘High’.</p> <h3 id="step-5-validating-the-unified-view">Step 5: Validating the Unified View</h3> <p>After creating the view, it’s always good practice to validate the results. You can use a <code dir="auto">SELECT</code> query to make sure everything looks right:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#7FDBCA;--1:#096E72">*</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">FROM</span><span style="--0:#D6DEEB;--1:#403F53"> patient_rpm_mode_cgm </span><span style="--0:#C792EA;--1:#8844AE">LIMIT</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#F78C6C;--1:#AA0982">10</span><span style="--0:#D6DEEB;--1:#403F53">;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="SELECT * FROM patient_rpm_mode_cgm LIMIT 10;"><div></div></button></div></figure></div> <p>Review the data to ensure that the column names are standardized and that the values align as expected. Pay particular attention to the <code dir="auto">timestamp</code> column to ensure formats are consistent.</p> <h3 id="step-6-leveraging-the-view-for-downstream-analysis">Step 6: Leveraging the View for Downstream Analysis</h3> <p>With the <code dir="auto">patient_rpm_mode_cgm</code> view in place, downstream processes can now treat this data as a consistent and unified source. Analysts can run queries like:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id,</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C5E478;--1:#3B61B0">AVG</span><span style="--0:#D6DEEB;--1:#403F53">(glucose_level) </span><span style="--0:#C792EA;--1:#8844AE">AS</span><span style="--0:#D6DEEB;--1:#403F53"> avg_glucose_level</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_rpm_mode_cgm</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">GROUP BY</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#D6DEEB;--1:#403F53"> </span></span><span style="--0:#D6DEEB;--1:#403F53">patient_id;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="SELECT patient_id, AVG(glucose_level) AS avg_glucose_levelFROM patient_rpm_mode_cgmGROUP BY patient_id;"><div></div></button></div></figure></div> <p>This allows for seamless analysis without needing to worry about device-specific table structures.</p> <h2 id="why-elt-with-sqlite">Why ELT with SQLite?</h2> <p>You might wonder why ELT is a good fit for this scenario. Here are some reasons:</p> <ul> <li><strong>Flexibility</strong>: ELT allows you to load data as-is and apply transformations later when you have a better understanding of the data.</li> <li><strong>Simplicity</strong>: SQLite is simple to set up, and using views means that transformations are written declaratively with SQL, which is easy for teams to understand and modify.</li> <li><strong>Lightweight</strong>: No heavyweight ETL tools are required, which makes this approach perfect for small datasets or prototyping.</li> </ul> <h2 id="conclusion">Conclusion</h2> <p>By using SQLite and SQL views, we’ve demonstrated a lightweight and modern approach to ETL (or, more precisely, ELT) that helps simplify the process of integrating data from multiple sources. This approach allows for greater flexibility, and by leveraging SQL views, we can keep the transformation logic declarative and transparent.</p> <p>Whether you’re prototyping a new data pipeline, working with smaller datasets, or need a low-maintenance integration solution, this ELT strategy with SQLite is an excellent option. We hope this guide helps you get started on your journey towards modern data engineering!</p> <h2 id="next-steps">Next Steps</h2> <p>To deepen your understanding, try adding more transformations or aggregations to the <code dir="auto">patient_rpm_mode_cgm</code> view. You could, for example, normalize the <code dir="auto">timestamp</code> formats or add additional metadata to the view to help with analysis. Feel free to experiment and explore how SQLite’s capabilities can further simplify your data engineering workflow.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Etl </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Elt </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/sql-based-etl-elt/&title=Modern Lightweight ETL with SQLite"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Modern Lightweight ETL with SQLitehttps://www.surveilr.com/blog/sql-based-etl-elt/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/sql-based-etl-elt/&title=Modern Lightweight ETL with SQLite"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 126737 | 2025-04-07 05:49:49.339005565 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTWGE73GXXQVE50Q7B8 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/direct-messaging-service-pattern/index.html | b5732fe0eabda2fe352c595d0da41e18cee7b603 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/direct-messaging-service-pattern/"},"headline":"How `surveilr` Enhances Secure Health Data Exchange for HISPs","description":"`surveilr` automates Direct Secure Messaging for HISPs, ensuring regulatory compliance, data integrity, and seamless integration with healthcare IT systems.","image":"https://www.surveilr.com/_astro/secure-health-data-exchange.CLZ3b6ma_BslOU.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-10-07T00:00:00.000Z","dateModified":"2024-10-07T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"How `surveilr` Enhances Secure Health Data Exchange for HISPs","url":"https://www.surveilr.com/blog/direct-messaging-service-pattern/","description":"`surveilr` automates Direct Secure Messaging for HISPs, ensuring regulatory compliance, data integrity, and seamless integration with healthcare IT systems.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="`surveilr` automates Direct Secure Messaging for HISPs, ensuring regulatory compliance, data integrity, and seamless integration with healthcare IT systems." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/direct-messaging-service-pattern/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/direct-messaging-service-pattern/"><meta property="og:type" content="website"><meta property="og:title" content="How `surveilr` Enhances Secure Health Data Exchange for HISPs"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="`surveilr` automates Direct Secure Messaging for HISPs, ensuring regulatory compliance, data integrity, and seamless integration with healthcare IT systems."><meta property="og:image" content="https://www.surveilr.com/_astro/secure-health-data-exchange.CLZ3b6ma_BslOU.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/direct-messaging-service-pattern/"><meta name="twitter:title" content="How `surveilr` Enhances Secure Health Data Exchange for HISPs"><meta name="twitter:description" content="`surveilr` automates Direct Secure Messaging for HISPs, ensuring regulatory compliance, data integrity, and seamless integration with healthcare IT systems."><meta name="twitter:image" content="https://www.surveilr.com/_astro/secure-health-data-exchange.CLZ3b6ma_BslOU.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>How `surveilr` Enhances Secure Health Data Exchange for HISPs</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="64845344-20d1-4abc-a597-ab2545ee269d" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="64845344-20d1-4abc-a597-ab2545ee269d"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Direct Messaging Service Pattern </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/direct-messaging-service-pattern/","name":"Direct Messaging Service Pattern"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/user-no-image.6C6x2-VQ_2pDaat.avif" alt="Ditty Bijil" draggable="false" width="886" height="886" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Ditty Bijil </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Oct 7, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 3 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <!-- ## How `surveilr` Transforms Secure Health Data Exchange in Clinical Workflows --> <!--  --> <p>In today’s rapidly changing healthcare landscape, the exchange of clinical data is paramount, where safety and efficiency are essentials. Therefore, <strong>Direct Secure Messaging</strong> (DSM) is a crucial concept for safe communication among the stakeholders within the healthcare sector, ensuring sensitive information not openly shared but among authorized parties. However, with all its benefits, managing, processing, and consolidating such messages becomes a challenge for the HISP. This is where <code dir="auto">surveilr</code> comes in-a stateful data preparation and integration platform designed to simplify and enhance DSM services by automating message ingestion, processing, and ensuring regulatory compliance.</p> <p>In this blog, we will not only be looking into how <code dir="auto">surveilr</code> augments Direct Secure Messaging but also how it solves the challenges for HISPs.</p> <h2 id="understanding-surveilr-in-the-dsm-ecosystem">Understanding <code dir="auto">surveilr</code> in the DSM Ecosystem</h2> <p>In health care communication, <strong>Direct Secure Messaging</strong> has become one of the critical standards for secure health information exchange. <code dir="auto">surveilr</code> builds on this ecosystem in an innovative open-source implementation, automating important aspects of message handling and data processing to enhance the overall system.</p> <p><strong>Direct Secure Messaging</strong> (DSM) refers to a protocol, enabling secure, end-to-end encrypted messaging between healthcare providers, patients, and organizations sharing health information. It is also a tool towards HIPAA compliance because direct encryption, authentication, and audit trails ensure safe health data.</p> <h2 id="challenges-faced-by-health-information-service-providers-hisps">Challenges Faced by Health Information Service Providers (HISPs)</h2> <p>HISPs play a critical role in ensuring the secure transmission of health information. However, they encounter several challenges in the process:</p> <ul> <li> <p><strong>Message Format Variability</strong>: DSM messages often come in various formats (e.g., HL7, CCDA), making it difficult to standardize processing and extract relevant data.</p> </li> <li> <p><strong>Handling Large Message Volumes</strong>: Healthcare organizations deal with high volumes of DSM messages daily, increasing the need for scalable and efficient processing systems.</p> </li> <li> <p><strong>Data Integrity and Compliance</strong>: Ensuring data accuracy while complying with healthcare regulations such as HIPAA is resource-intensive and prone to errors without the right tools.</p> </li> <li> <p><strong>System Integration Issues</strong>: Integrating DSM messages into existing Electronic Health Record (EHR) systems and other healthcare platforms can be challenging, especially when dealing with multiple formats, protocols, and legacy systems.</p> </li> <li> <p><strong>Security Threats</strong>: Despite encryption, DSM is still susceptible to human error, which can result in compromised security if proper validation and compliance mechanisms are not in place.</p> </li> </ul> <h2 id="how-surveilr-solves-hisp-challenges">How <code dir="auto">surveilr</code> Solves HISP Challenges</h2> <p><code dir="auto">surveilr</code> addresses these challenges through its powerful automation, integration, and security features, which streamline the DSM process for HISPs.</p> <ul> <li> <p><strong>Automated Message Processing</strong>: <code dir="auto">surveilr</code> continuously monitors DSM inboxes and automatically processes messages, regardless of format (HL7, CCDA, JSON, XML, PDF etc.). It validates the sender’s authenticity, extracts relevant data, and ensures proper encryption, saving time and reducing manual workload.</p> </li> <li> <p><strong>Scalability for High Volumes</strong>: <code dir="auto">surveilr</code> is designed to handle large volumes of messages efficiently. By automating the ingestion and processing of messages, it ensures that even high-throughput DSM environments can operate smoothly without delays or data bottlenecks.</p> </li> <li> <p><strong>Ensuring Data Integrity and HIPAA Compliance</strong>: <code dir="auto">surveilr</code> ensures that all DSM messages are processed with complete data integrity. It can de-identify or anonymize sensitive patient data to maintain HIPAA compliance, while providing comprehensive audit trails for secure, trackable communication.</p> </li> <li> <p><strong>Seamless System Integration</strong>: <code dir="auto">surveilr</code> integrates DSM data with existing EHR and Health Information Systems (HIS) via APIs or direct database connections (e.g., PostgreSQL). This facilitates real-time data updates, ensuring that healthcare providers have access to the most current information across various platforms.</p> </li> <li> <p><strong>Enhanced Security</strong>: <code dir="auto">surveilr</code> enhances DSM security through advanced encryption, automatic validation, and audit trails, protecting sensitive health data from unauthorized access and ensuring compliance with healthcare regulations.</p> </li> </ul> <h2 id="benefits-of-using-surveilr-for-dsm">Benefits of Using <code dir="auto">surveilr</code> for DSM</h2> <ul> <li><strong>Improved Efficiency</strong>: Automating message processing minimizes manual intervention, speeds up workflows, and reduces human errors.</li> <li><strong>Regulatory Compliance</strong>: <code dir="auto">surveilr</code> helps ensure HIPAA compliance by anonymizing patient data, validating message integrity, and maintaining detailed audit logs.</li> <li><strong>Interoperability</strong>: <code dir="auto">surveilr</code> supports multiple message formats and seamlessly integrates with various EHR systems, making it ideal for organizations with complex healthcare IT infrastructures.</li> <li><strong>Reduced Administrative Burden</strong>: With automation handling repetitive tasks like data extraction, healthcare staff can focus on delivering better patient care.</li> <li><strong>Scalable and Secure</strong>: Whether dealing with large message volumes or ensuring the secure exchange of health information, <code dir="auto">surveilr</code> offers a scalable and robust solution to meet the growing needs of HISPs.</li> </ul> <h3 id="better-data-governance">Better Data Governance</h3> <ul> <li>Local first and edge-based</li> <li>Centralized data repository</li> <li>Enhanced audit trails</li> <li>Simplified compliance reporting</li> <li>Local first visualization, visualize the episodes of care from the local PC/Laptop level</li> </ul> <h3 id="real-time-processing">Real-Time Processing</h3> <ul> <li>Minimal delay in message processing</li> <li>Immediate availability of extracted data</li> <li>Fast integration capability with existing systems</li> </ul> <h3 id="robust-data-validation-and-transformation">Robust Data Validation and Transformation</h3> <ul> <li>Automated error detection and reporting</li> <li>Data validation and transformation capability</li> <li>Data security through data anonymization</li> </ul> <h2 id="conclusion">Conclusion</h2> <p>Being an unavoidable tool for healthcare communication, <strong>Direct Messaging Service</strong> came with a challenge of effective management by HISPs. <code dir="auto">surveilr</code> revolutionizes <strong>Direct Messaging Service</strong> workflows by automatically processing the messages, ensuring regulatory compliance, and integrating seamlessly into the healthcare IT systems. This makes <code dir="auto">surveilr</code> very impactful because it addresses specific issues HISPs face in the optimization of secure communication towards better patient care with reduced administrative overhead.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Pattern </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/direct-messaging-service-pattern/&title=How surveilr Transforms Secure Health Data Exchange in Clinical Workflows"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=How surveilr Transforms Secure Health Data Exchange in Clinical Workflowshttps://www.surveilr.com/blog/direct-messaging-service-pattern/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/direct-messaging-service-pattern/&title=How surveilr Transforms Secure Health Data Exchange in Clinical Workflows"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 90826 | 2025-04-07 05:49:50.962993511 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTX7YXBGVZAC1AYKVF6 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/research-study-explorer-pattern/index.html | 134d297c853afce8e90469964582d476bf835355 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/research-study-explorer-pattern/"},"headline":"How `surveilr` Enhances Diabetes Data Exchange for Research Studies","description":"`surveilr` automates the management of health data, ensuring regulatory compliance, data integrity, and seamless integration with diabetes research systems.","image":"https://www.surveilr.com/_astro/research-explorer.CKy9kAYJ_C83Vp.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-12-05T00:00:00.000Z","dateModified":"2024-12-05T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"How `surveilr` Enhances Diabetes Data Exchange for Research Studies","url":"https://www.surveilr.com/blog/research-study-explorer-pattern/","description":"`surveilr` automates the management of health data, ensuring regulatory compliance, data integrity, and seamless integration with diabetes research systems.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="`surveilr` automates the management of health data, ensuring regulatory compliance, data integrity, and seamless integration with diabetes research systems." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/research-study-explorer-pattern/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/research-study-explorer-pattern/"><meta property="og:type" content="website"><meta property="og:title" content="How `surveilr` Enhances Diabetes Data Exchange for Research Studies"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="`surveilr` automates the management of health data, ensuring regulatory compliance, data integrity, and seamless integration with diabetes research systems."><meta property="og:image" content="https://www.surveilr.com/_astro/research-explorer.CKy9kAYJ_C83Vp.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/research-study-explorer-pattern/"><meta name="twitter:title" content="How `surveilr` Enhances Diabetes Data Exchange for Research Studies"><meta name="twitter:description" content="`surveilr` automates the management of health data, ensuring regulatory compliance, data integrity, and seamless integration with diabetes research systems."><meta name="twitter:image" content="https://www.surveilr.com/_astro/research-explorer.CKy9kAYJ_C83Vp.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>How `surveilr` Enhances Diabetes Data Exchange for Research Studies</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="dc75b0b8-e4ab-409e-987f-62554fdeb74a" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="dc75b0b8-e4ab-409e-987f-62554fdeb74a"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Research Study Explorer Pattern </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/research-study-explorer-pattern/","name":"Research Study Explorer Pattern"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/user-no-image.6C6x2-VQ_2pDaat.avif" alt="Anitha Varghese" draggable="false" width="886" height="886" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Anitha Varghese </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Dec 5, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 3 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> How `surveilr` Transforms Diabetes Research Study Data Management </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>In the evolving landscape of diabetes research, managing and analyzing vast amounts of data from diverse participants is crucial for advancing medical understanding. The challenge, however, lies in securely and efficiently exchanging, processing, and consolidating data from multiple sources—especially when different datasets exhibit varied patterns. <code dir="auto">surveilr</code> provides an innovative solution to these challenges, transforming how diabetes data is handled in research studies.</p> <h2 id="the-role-of-surveilr-in-diabetes-research-data-management">The Role of <code dir="auto">surveilr</code> in Diabetes Research Data Management</h2> <p><code dir="auto">surveilr</code> is a state-of-the-art platform designed to simplify data management in health-related research, specifically for studies involving complex datasets, like Continuous Glucose Monitoring (CGM) data. In diabetes research, these datasets often come from a variety of sources and participant profiles, requiring tools that can efficiently process and integrate the data into a unified format. By automating data ingestion, processing, and ensuring regulatory compliance, <code dir="auto">surveilr</code> helps streamline these tasks, enabling researchers to focus on analysis and insights.</p> <h2 id="challenges-in-managing-diabetes-research-study-data">Challenges in Managing Diabetes Research Study Data</h2> <p>Managing diabetes research study data poses several unique challenges:</p> <ul> <li><strong>Dataset Variability</strong>: Diabetes research datasets often differ in structure, with each dataset representing CGM data from different participants or study sites, which complicates data integration.</li> <li><strong>Data Volume</strong>: The sheer volume of data generated in long-term diabetes studies is overwhelming. Processing this data efficiently and ensuring its accuracy is a critical task.</li> <li><strong>Participant-Level Data</strong>: Diabetes studies typically involve tracking multiple participants, each with unique data points, such as CGM readings, blood glucose levels, and demographic information.</li> <li><strong>Data Security and Privacy</strong>: Ensuring that sensitive patient information remains secure and compliant with privacy regulations such as HIPAA is a constant challenge.</li> </ul> <h2 id="how-surveilr-solves-diabetes-research-data-challenges">How <code dir="auto">surveilr</code> Solves Diabetes Research Data Challenges</h2> <p><code dir="auto">surveilr</code> addresses these challenges by providing a comprehensive suite of features designed to handle complex, large-scale datasets securely and efficiently.</p> <h3 id="1-automated-data-processing-and-integration">1. Automated Data Processing and Integration</h3> <p><code dir="auto">surveilr</code> automates the ingestion and processing of diverse datasets, which might include CGM readings from different devices, demographic data, and clinical metrics. By validating the authenticity of the data sources and ensuring it is securely processed, <code dir="auto">surveilr</code> saves researchers significant time and reduces the risk of human error.</p> <h3 id="2-scalability-for-large-datasets">2. Scalability for Large Datasets</h3> <p>Diabetes research generates vast amounts of data, which can overwhelm traditional data management systems. <code dir="auto">surveilr</code> is designed to handle large-scale datasets seamlessly. It automatically processes and integrates the data, ensuring that even the largest datasets are handled without delays or performance issues.</p> <h3 id="3-data-validation-and-compliance">3. Data Validation and Compliance</h3> <p>In diabetes research, ensuring the integrity and compliance of the data is paramount. <code dir="auto">surveilr</code> ensures that all incoming data, including sensitive participant information, is processed in accordance with HIPAA and other regulatory standards. Additionally, <code dir="auto">surveilr</code> can anonymize or de-identify data as necessary, ensuring privacy while maintaining the usefulness of the data for analysis.</p> <h3 id="4-real-time-data-processing">4. Real-Time Data Processing</h3> <p>For diabetes research, real-time data availability is crucial, especially when analyzing patient responses to treatments or interventions. <code dir="auto">surveilr</code> provides real-time processing capabilities, ensuring that data from participants is immediately available for analysis, facilitating faster insights.</p> <h3 id="5-seamless-integration-with-research-systems">5. Seamless Integration with Research Systems</h3> <p><code dir="auto">surveilr</code> integrates effortlessly with existing research infrastructure, including databases and other health information systems (HIS). Researchers can connect <code dir="auto">surveilr</code> to their preferred platforms (e.g., PostgreSQL, EHR systems) to ensure that all data is synchronized and up-to-date, supporting collaborative research efforts.</p> <h3 id="6-enhanced-security-and-privacy">6. Enhanced Security and Privacy</h3> <p><code dir="auto">surveilr</code> strengthens the security of diabetes research data through advanced encryption, automatic validation, and detailed audit trails. These measures protect sensitive health information from unauthorized access and ensure compliance with healthcare regulations.</p> <h2 id="benefits-of-using-surveilr-in-diabetes-research-studies">Benefits of Using <code dir="auto">surveilr</code> in Diabetes Research Studies</h2> <ul> <li><strong>Efficient Data Management</strong>: <code dir="auto">surveilr</code> automates the processing of participant data, eliminating manual tasks and reducing the likelihood of errors.</li> <li><strong>Regulatory Compliance</strong>: Ensuring HIPAA compliance and data security is made simple with <code dir="auto">surveilr</code>’s built-in features for data anonymization and audit trails.</li> <li><strong>Seamless Data Integration</strong>: <code dir="auto">surveilr</code> supports multiple data formats and integrates with various systems, ensuring smooth data flow across research platforms.</li> <li><strong>Scalability and Performance</strong>: Whether dealing with small or large datasets, <code dir="auto">surveilr</code> scales to meet the demands of diabetes research studies.</li> <li><strong>Enhanced Research Collaboration</strong>: By automating data handling and improving data accessibility, <code dir="auto">surveilr</code> fosters better collaboration among research teams.</li> </ul> <h3 id="better-data-governance-in-diabetes-research">Better Data Governance in Diabetes Research</h3> <ul> <li>Centralized data repository for diabetes study information</li> <li>Enhanced audit trails for tracking data usage</li> <li>Simplified compliance reporting for research purposes</li> <li>Secure, localized data visualization for better study insights</li> </ul> <h3 id="real-time-data-processing">Real-Time Data Processing</h3> <ul> <li>Immediate availability of participant data for real-time analysis</li> <li>Fast integration with existing diabetes research databases and systems</li> <li>Minimizes delay in processing time for research updates</li> </ul> <h3 id="robust-data-validation-and-transformation">Robust Data Validation and Transformation</h3> <ul> <li>Automated error detection and reporting for diabetes study data</li> <li>Validation capabilities for ensuring accurate research results</li> <li>Data anonymization for privacy protection and compliance</li> </ul> <h2 id="conclusion">Conclusion</h2> <p>The complexities of managing diverse and voluminous data in diabetes research studies require efficient, secure, and compliant solutions. <code dir="auto">surveilr</code> offers an invaluable tool for diabetes research teams by automating data processing, ensuring regulatory compliance, and providing seamless integration with existing research systems. By enhancing data management workflows, <code dir="auto">surveilr</code> helps researchers focus on advancing medical knowledge and improving patient care, all while reducing administrative overhead and ensuring the privacy and integrity of the data.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Pattern </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Diabetes research </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Health data </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Secure exchange </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/research-study-explorer-pattern/&title=How `surveilr` Transforms Diabetes Research Study Data Management"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=How `surveilr` Transforms Diabetes Research Study Data Managementhttps://www.surveilr.com/blog/research-study-explorer-pattern/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/research-study-explorer-pattern/&title=How `surveilr` Transforms Diabetes Research Study Data Management"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 91861 | 2025-04-07 05:49:49.452004726 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTX0AV51V2X6RCZD646 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/why-stateful-integration/index.html | b1a45f0a5d7562a345a5fba264b592a85da3d160 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/why-stateful-integration/"},"headline":"Stateful Data Integration Simplifies Compliance and Data Management","description":"Discover how Surveilr's stateful integration and SQL interface help non-technical teams manage, query, and track data effortlessly while ensuring compliance.","image":"https://www.surveilr.com/_astro/why-stateful-integration.TtFEGayC_ZJEjbQ.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-02-10T00:00:00.000Z","dateModified":"2024-02-10T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Stateful Data Integration Simplifies Compliance and Data Management","url":"https://www.surveilr.com/blog/why-stateful-integration/","description":"Discover how Surveilr's stateful integration and SQL interface help non-technical teams manage, query, and track data effortlessly while ensuring compliance.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Discover how Surveilr's stateful integration and SQL interface help non-technical teams manage, query, and track data effortlessly while ensuring compliance." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/why-stateful-integration/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/why-stateful-integration/"><meta property="og:type" content="website"><meta property="og:title" content="Stateful Data Integration Simplifies Compliance and Data Management"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Discover how Surveilr's stateful integration and SQL interface help non-technical teams manage, query, and track data effortlessly while ensuring compliance."><meta property="og:image" content="https://www.surveilr.com/_astro/why-stateful-integration.TtFEGayC_ZJEjbQ.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/why-stateful-integration/"><meta name="twitter:title" content="Stateful Data Integration Simplifies Compliance and Data Management"><meta name="twitter:description" content="Discover how Surveilr's stateful integration and SQL interface help non-technical teams manage, query, and track data effortlessly while ensuring compliance."><meta name="twitter:image" content="https://www.surveilr.com/_astro/why-stateful-integration.TtFEGayC_ZJEjbQ.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Stateful Data Integration Simplifies Compliance and Data Management</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="ba4fc418-c4d7-41c7-865b-052d6a107726" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="ba4fc418-c4d7-41c7-865b-052d6a107726"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Why Stateful Integration </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/why-stateful-integration/","name":"Why Stateful Integration"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/shahid-shah.B2DFcsvR_ZITVg0.avif" alt="Avatar Description" draggable="false" width="2818" height="2746" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Shahid N. Shah </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Feb 10, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 5 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Why Stateful Integration? </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>In today’s increasingly data-driven world, businesses of all sizes must efficiently manage and integrate data from a variety of sources. But for many small and mid-sized organizations without large IT departments to rely on, this can seem like an overwhelming task. Enter <strong><code dir="auto">surveilr</code></strong>, a powerful tool designed to simplify the complexity of data management with its <strong>stateful data integration</strong>, <strong>SQL-centric interface</strong>, and <strong>opinionated schema</strong>.</p> <p>If you’re an analyst, compliance officer, or a business leader who isn’t a technical expert, understanding how your data is structured and making it usable across various systems can be frustrating. This is exactly where <strong>stateful integration</strong> makes a difference—helping non-technical staff access, query, and manage their data efficiently without the need for a large IT team.</p> <h2 id="how-surveilr-works">How Surveilr Works</h2> <ol> <li> <p><strong>Stateful Data Integration</strong>: Unlike simple data transfer tools, surveilr doesn’t just move data between systems. It stores and organizes the data in a <a href="../rssd-excel-portability-sql-power/index.html">Resource Surveillance State Database (RSSD)</a> powered by SQLite. SQL makes it easy to query, understand, and manage. This ensures that every piece of information retains its context, allowing for more meaningful analysis and easier retrieval when needed.</p> </li> <li> <p><strong>Local-First, Edge-Based Processing</strong>: To enhance security and efficiency, surveilr <a href="../rssd-excel-portability-sql-power/index.html">RSSDs</a> process data close to where it’s collected—on local devices or edge systems. This reduces unnecessary data transfers and makes the system easier to manage, even if you don’t have a dedicated IT team monitoring every transaction.</p> </li> <li> <p><strong>SQL-Centric Approach</strong>: Surveilr uses SQL, a universal and widely-known database language. For non-technical users, this means they don’t need to learn complex new systems or depend on IT specialists to query and analyze data. With basic SQL knowledge, analysts can access data, run reports, and generate insights quickly.</p> </li> </ol> <p>Now, let’s dive into why stateful integration is especially important for businesses that lack extensive IT resources.</p> <h2 id="what-is-stateful-integration-and-why-does-it-matter">What is Stateful Integration and Why Does it Matter?</h2> <p><strong>Stateful integration</strong> goes beyond moving data—it involves keeping the data’s <strong>history and context</strong> intact as it flows through different systems. When data is statefully integrated, it isn’t just passed from one platform to another; its origin, its transformations, and its current form are all tracked and preserved.</p> <p>This is crucial for businesses without large technical teams because it simplifies <strong>data management</strong>. Instead of needing technical experts to manually map out or trace where data came from, what was done to it, and how it’s been processed, surveilr does this automatically. It retains the “state” of the data, so non-technical staff can focus on <strong>using</strong> the data rather than trying to figure out how it got there.</p> <h2 id="why-is-this-so-important-for-non-technical-teams">Why is This So Important for Non-Technical Teams?</h2> <p>In many small and mid-sized businesses, the burden of data integration often falls on <strong>analysts</strong>, <strong>compliance officers</strong>, or <strong>business managers</strong>—not specialized IT professionals. These individuals need to be able to:</p> <ul> <li><strong>Access data</strong> quickly and reliably without spending hours figuring out how to extract it.</li> <li><strong>Ensure compliance</strong> with regulatory requirements by having a complete history of how data has been managed.</li> <li><strong>Run reports</strong> and generate insights easily, without needing to dive into complex technical tools.</li> </ul> <p>Stateful integration simplifies all of these tasks. It automatically tracks data through its entire lifecycle, so non-technical staff can see exactly how the data was collected, processed, and stored, making it easier to manage without technical intervention.</p> <h2 id="surveilrs-opinionated-schema-why-it-matters">Surveilr’s Opinionated Schema: Why It Matters</h2> <p>One of the most powerful features of surveilr is its <strong>opinionated schema</strong>—a standardized way of structuring data. But what does that mean, and why should you care?</p> <p>In technical terms, an “opinionated” system makes certain choices about how things should be done. Instead of giving users unlimited flexibility (and complexity), surveilr offers a structured, pre-defined approach to how data is stored and organized. This makes life easier for <strong>non-technical staff</strong> in several key ways:</p> <h3 id="1-less-guesswork-more-usability">1. Less Guesswork, More Usability</h3> <p>When a system imposes a standardized structure on your data, you don’t have to spend time figuring out how to organize or label everything yourself. The <strong>opinionated schema</strong> in surveilr gives you a consistent, predictable way to handle data. This means you don’t have to ask, “Where is this piece of information stored?” or “How do I access this specific dataset?”</p> <p>For non-technical users, this removes a major hurdle. With surveilr, the data is already organized in a meaningful, searchable way. You can start querying it immediately using <strong>basic SQL</strong> knowledge.</p> <h3 id="2-sql-queries-become-simpler">2. SQL Queries Become Simpler</h3> <p>In an unstructured or loosely structured system, writing SQL queries can become difficult and time-consuming. You need to know where the data is located, how it’s been named, and how different datasets relate to each other. With surveilr’s <strong>opinionated schema</strong>, those relationships are already mapped out for you. The system provides a clear, <strong>consistent format</strong> for the data, which simplifies the process of writing SQL queries.</p> <p>For example, instead of worrying about different naming conventions across departments or systems, surveilr ensures that everything is uniformly structured. As a result, analysts don’t need to spend time crafting complex queries. They can quickly access the information they need with simple, straightforward SQL commands.</p> <h3 id="3-fewer-errors-greater-accuracy">3. Fewer Errors, Greater Accuracy</h3> <p>When you don’t have a team of IT professionals maintaining your data systems, errors can slip through the cracks—especially if different parts of the organization are using different structures or conventions for their data. With surveilr’s opinionated schema, data is always stored and organized in a standardized way, minimizing the risk of errors.</p> <p>This leads to more <strong>accurate reporting</strong>, <strong>fewer mistakes</strong>, and <strong>less time spent troubleshooting</strong>. Non-technical users can trust that the system is handling the details correctly, allowing them to focus on <strong>analyzing data</strong> and making informed business decisions.</p> <h2 id="empowering-analysts-and-business-teams">Empowering Analysts and Business Teams</h2> <p>One of the key benefits of surveilr’s stateful integration and opinionated schema is that it puts the power back in the hands of <strong>analysts and business users</strong>. You don’t need to rely on IT to manage your data or run complex queries. With surveilr’s intuitive SQL-centric approach, non-technical users can:</p> <ul> <li><strong>Easily query data</strong> and get immediate answers to business questions.</li> <li><strong>Track the history</strong> of data without needing technical expertise.</li> <li><strong>Ensure compliance</strong> and generate accurate, traceable reports for regulators.</li> </ul> <p>This means that even if your organization doesn’t have a large IT team—or any IT department at all—you can still manage your data effectively. Surveilr handles the heavy lifting of data integration, organization, and compliance, freeing up non-technical staff to focus on <strong>using data to drive business results</strong>.</p> <p>In a world where data drives decisions, businesses without dedicated IT teams can often feel overwhelmed by the technical challenges of managing and integrating their data. With <strong>surveilr’s stateful data integration</strong>, <strong>opinionated schema</strong>, and <strong>SQL-centric interface</strong>, non-technical users can take control of their data, ensuring it’s always <strong>organized, traceable, and accessible</strong>.</p> <p>Stateful integration allows your organization to manage data across systems effortlessly while retaining important context and history, making compliance, reporting, and analysis easier than ever. Surveilr’s opinionated schema reduces complexity, letting your team focus on what matters most: making informed decisions based on reliable, well-organized data.</p> <p>With surveilr, you don’t need a large IT team to manage your data effectively. All you need are the right tools.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Stateful </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Stateless </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> RSSD </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/why-stateful-integration/&title=Why Stateful Integration?"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Why Stateful Integration?https://www.surveilr.com/blog/why-stateful-integration/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/why-stateful-integration/&title=Why Stateful Integration?"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 92601 | 2025-04-07 05:49:50.470997163 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTXG47YJKKEVD8H2S87 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/vendor-assessments/index.html | f9849f6273d10d30708e01fe2991521c2bcdf446 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/vendor-assessments/"},"headline":"Enhance Vendor Compliance with Effective Evidence Management","description":"Streamline vendor assessments and ensure compliance with surveilr's secure evidence management, protecting sensitive data while verifying policy adherence.","image":"https://www.surveilr.com/_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_6aGfy.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-05-22T00:00:00.000Z","dateModified":"2024-05-22T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Enhance Vendor Compliance with Effective Evidence Management","url":"https://www.surveilr.com/blog/vendor-assessments/","description":"Streamline vendor assessments and ensure compliance with surveilr's secure evidence management, protecting sensitive data while verifying policy adherence.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Streamline vendor assessments and ensure compliance with surveilr's secure evidence management, protecting sensitive data while verifying policy adherence." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/vendor-assessments/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/vendor-assessments/"><meta property="og:type" content="website"><meta property="og:title" content="Enhance Vendor Compliance with Effective Evidence Management"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Streamline vendor assessments and ensure compliance with surveilr's secure evidence management, protecting sensitive data while verifying policy adherence."><meta property="og:image" content="https://www.surveilr.com/_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_6aGfy.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/vendor-assessments/"><meta name="twitter:title" content="Enhance Vendor Compliance with Effective Evidence Management"><meta name="twitter:description" content="Streamline vendor assessments and ensure compliance with surveilr's secure evidence management, protecting sensitive data while verifying policy adherence."><meta name="twitter:image" content="https://www.surveilr.com/_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_6aGfy.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Enhance Vendor Compliance with Effective Evidence Management</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="a5f9a206-f2cc-4826-ab43-d2af3e038c0f" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="a5f9a206-f2cc-4826-ab43-d2af3e038c0f"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Vendor Assessments </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/vendor-assessments/","name":"Vendor Assessments"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/shahid-shah.B2DFcsvR_ZITVg0.avif" alt="Shahid N. Shah" draggable="false" width="2818" height="2746" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Shahid N. Shah </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> May 22, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 3 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>In industries where supply chain partners are involved—such as healthcare, energy, and cybersecurity—vendors must often evaluate and police each other’s policy adherence. <strong><code dir="auto">surveilr</code></strong> enables companies to do just that in a secure and efficient way.</p> <p>With <strong><code dir="auto">surveilr</code></strong>, you can collect <strong>policy adherence evidence</strong> directly from systems behind corporate firewalls. Sensitive data can be anonymized or removed entirely, allowing organizations to share just the evidence required to prove compliance without exposing proprietary or personal information. This is particularly valuable in <strong>vendor assessments</strong>, where transparency is essential, but security and privacy cannot be compromised.</p> <p>Corporate compliance leaders and cybersecurity officers can also use <strong><code dir="auto">surveilr</code></strong> to gather data anonymously or with attribution, depending on the need. Whether through automated processes or manual reviews, <code dir="auto">surveilr</code> allows organizations to enforce or audit policy adherence by capturing activities across systems and verifying whether individuals or teams are following established procedures. By pulling data from emails, lifecycle tools like GitHub, SaaS platforms, or logs, <strong><code dir="auto">surveilr</code></strong> provides a clear picture of whether key standards are being met.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Supply chain </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/vendor-assessments/&title=Vendor Assessment and Corporate Compliance Evidence Warehouse"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Vendor Assessment and Corporate Compliance Evidence Warehousehttps://www.surveilr.com/blog/vendor-assessments/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/vendor-assessments/&title=Vendor Assessment and Corporate Compliance Evidence Warehouse"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 84312 | 2025-04-07 05:49:50.636995930 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTYEHVMY82KF0CX97G8 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/surveilr-integration-engine/index.html | d7dd23f032a9d43c74cca1e7b8895b4a965db705 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/surveilr-integration-engine/"},"headline":"Local-First Edge-Based SQL Integration Engine for Data Management","description":"Discover how surveilr’s local-first, edge-based architecture enhances data integration and compliance for healthcare and regulated sectors.","image":"https://www.surveilr.com/_astro/surveilr-integration-engine.D4-bfeLm_1dHMes.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-09-27T00:00:00.000Z","dateModified":"2024-09-27T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Local-First Edge-Based SQL Integration Engine for Data Management","url":"https://www.surveilr.com/blog/surveilr-integration-engine/","description":"Discover how surveilr’s local-first, edge-based architecture enhances data integration and compliance for healthcare and regulated sectors.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Discover how surveilr’s local-first, edge-based architecture enhances data integration and compliance for healthcare and regulated sectors." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/surveilr-integration-engine/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/surveilr-integration-engine/"><meta property="og:type" content="website"><meta property="og:title" content="Local-First Edge-Based SQL Integration Engine for Data Management"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Discover how surveilr’s local-first, edge-based architecture enhances data integration and compliance for healthcare and regulated sectors."><meta property="og:image" content="https://www.surveilr.com/_astro/surveilr-integration-engine.D4-bfeLm_1dHMes.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/surveilr-integration-engine/"><meta name="twitter:title" content="Local-First Edge-Based SQL Integration Engine for Data Management"><meta name="twitter:description" content="Discover how surveilr’s local-first, edge-based architecture enhances data integration and compliance for healthcare and regulated sectors."><meta name="twitter:image" content="https://www.surveilr.com/_astro/surveilr-integration-engine.D4-bfeLm_1dHMes.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Local-First Edge-Based SQL Integration Engine for Data Management</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="b69cf2cd-bbf1-4d13-ba7b-896d0b8692eb" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="b69cf2cd-bbf1-4d13-ba7b-896d0b8692eb"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Surveilr Integration Engine </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/surveilr-integration-engine/","name":"Surveilr Integration Engine"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/pradeep-narayanan.DRyfIcLY_ZF4Jr3.avif" alt="Avatar Description" draggable="false" width="64" height="64" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Pradeep Narayanan </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Sep 27, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 5 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>In today’s data-driven world, businesses, especially in healthcare, need efficient ways to manage and integrate data across multiple systems. <code dir="auto">surveilr</code> is designed to address these needs. It’s a stateful data preparation and integration platform that allows systems to seamlessly operate on common data in a local-first, edge-based, and SQL-centric manner. Here’s what that means and why it’s crucial:</p> <h2 id="why-surveilrs-architecture-matters">Why surveilr’s Architecture Matters?</h2> <h3 id="local-first">Local-First:</h3> <p>Unlike traditional platforms where data is sent to the cloud for processing, <code dir="auto">surveilr</code> prioritizes local data handling. Data is prepared and processed locally before being transmitted to cloud or central servers, reducing latency and enhancing control over sensitive information.</p> <h3 id="edge-based">Edge-Based:</h3> <p><code dir="auto">surveilr</code> focuses on processing data as close to its source as possible. This means data is collected, processed, and sometimes even analyzed on devices near the point of collection, such as workstations, mobile phones, or local servers, minimizing the need for centralization.</p> <h3 id="stateful">Stateful:</h3> <p><code dir="auto">surveilr</code> doesn’t just pass data between systems—it stores it in a universal schema with full SQL querying capabilities. This means data can be analyzed, processed, and queried at any stage of the pipeline, giving users unparalleled control and flexibility.</p> <h3 id="sql-centric">SQL-Centric:</h3> <p>Data is structured to be fully queryable via SQL. This allows for orchestrated workflows and seamless data manipulation, making it easier to integrate, process, and analyze large datasets.</p> <h3 id="agility">Agility:</h3> <p>You can easily configure queries, data models, or applications without the need for pre-planning. In addition to SQL queries, the data ingestion and integration strategy is well suited to support real-time analytics, , and machine learning.</p> <h3 id="speed">Speed:</h3> <p>Keeping data in a raw state also makes it available for use far faster since you don’t have to perform time-intensive tasks such as transforming the data and developing additional table(s) and view(s) until you define the business question(s) that need to be addressed.</p> <h2 id="surveilr-features-and-use-cases"><code dir="auto">surveilr</code> Features and Use Cases</h2> <p>The various functional components/layers of the <strong>Resource Surveillance Integration Engine</strong> (<code dir="auto">surveilr</code>) are given below,</p> <table><thead><tr><th>Components/Layers</th><th>Details</th></tr></thead><tbody><tr><td>Acquisition of Content (Data)</td><td>Steps involves in the content acquisition i.e preparation of the files/data for ingestion. In addition to the local files, we can use technologies such as WebDAV, SFTP, AWS S3, Git and Virtual Printer capabilities are the part of this layer.</td></tr><tr><td>Advanced Data Acquisition Layer</td><td>This layer helps users for enhanced data preparation using Capturable Executables(CEs). With the support of processing instructions (PI) Capturable Executables(CEs) further helps the user to prepare data with specific message standards like JSON, plain/text etc</td></tr><tr><td>Message format/standard Support</td><td>The Resource Surveillance & Integration Engine supports a wide range of standards like HL7, FHIR, JSON, and XML but can also handle a variety of file types for exchange, such as CSV, Excel, or custom formats.</td></tr><tr><td>Stateful Ingestion</td><td>Involves the steps of ingesting and processing data into a structured universal schema with full SQL querying support. surveilr leverages state tables to track the status of ingested files, ensuring that files are not re-ingested unless changes are detected. This approach prevents redundant ingestion, optimizes performance, and supports incremental updates. By maintaining the state of ingested data, surveilr ensures efficient data management, scalability, and transparency, while also providing a clear audit trail of the ingestion history.</td></tr><tr><td>Web UI for Viewing Ingested Data Locally</td><td>Resource Surveillance & Integration Engine (<code dir="auto">surveilr</code>) provides a Web UI component that allows users to view ingested data in real time and access data processed offline</td></tr><tr><td>Data Synchronization and Aggregation</td><td>The Data Synchronization and Aggregation phase involves systematically synchronizing and aggregating the ingested and processed data into a central data store. This ensures the data is ready for advanced analytics, reporting, and integration with other supporting systems.</td></tr></tbody></table> <h2 id="surveilrs-ingestionintegration-pipeline">surveilr’s Ingestion/Integration Pipeline</h2> <p>surveilr’s architecture supports both <strong>real-time</strong> and <strong>offline/batch processing</strong>, enabling scalable and flexible data integration for various sectors. This approach allows businesses to optimize <strong>performance, security, and reliability</strong>, while adapting to their specific processing needs.</p> <h3 id="real-time-and-offline-processing">Real-Time and Offline Processing</h3> <ul> <li><strong>Real-Time Processing:</strong> <code dir="auto">surveilr</code> can handle live data streams, processing information as it arrives.</li> <li><strong>Offline/Batch Processing:</strong> For larger data sets or delayed ingestion, <code dir="auto">surveilr</code> supports batch processing, allowing for data to be ingested and analyzed at scheduled intervals.</li> </ul> <h3 id="improved-reliability">Improved Reliability</h3> <p>By storing and batch-processing data at the <strong>edge</strong>, <code dir="auto">surveilr</code> ensures continuous operation even when central systems are temporarily unavailable, making it ideal for mission-critical environments like healthcare and financial services.</p> <h3 id="security-and-compliance">Security and Compliance</h3> <p>Regardless of the ingestion method—real-time or batch uploads— <code dir="auto">surveilr</code> employs stringent security protocols, anonymizing or de-identifying sensitive data before transmission to central systems. This ensures compliance with <strong>HIPAA</strong> and other regulatory frameworks.</p> <h2 id="separation-of-content-acquisition-and-stateful-ingestion">Separation of Content Acquisition and Stateful Ingestion</h2> <p><code dir="auto">surveilr</code> differentiates between <strong>data acquisition</strong> and <strong>stateful ingestion</strong>, allowing for modular control and optimized data handling. This separation enhances both <strong>real-time</strong> and <strong>batch processing</strong>, ensuring efficient data capture and transformation.</p> <h3 id="content-acquisition-methods">Content Acquisition Methods</h3> <p>Data is collected via multiple acquisition methods, including:</p> <p><strong>WebDAV:</strong> Enables file uploads to designated ingestion folders for seamless integration with source systems.</p> <p><strong>Virtual Printers:</strong> Captures print jobs like reports or documents and stores them for later ingestion.</p> <p><strong>API, Direct Uploads, Local File Systems:</strong> Supports real-time API data feeds and batch uploads from sources like <strong>SFTP, Amazon S3, Git</strong>, and <strong>IMAP</strong>.</p> <p>This flexible acquisition process allows <code dir="auto">surveilr</code> to handle both <strong>on-demand</strong> data streams and <strong>scheduled</strong> batch uploads.</p> <h3 id="stateful-ingestion-process">Stateful Ingestion Process</h3> <p>Once acquired, the data moves to the <strong>stateful ingestion layer</strong>, where it undergoes transformation, enrichment, and validation. This process prepares the data for immediate analysis or later batch processing, ensuring that all data is structured and queryable.</p> <p><strong>File Ingestion:</strong> <code dir="auto">surveilr</code> scans directories, extracting and storing metadata in the <strong>Resource Surveillance State Database (RSSD)</strong>.</p> <p><strong>Task Ingestion:</strong> Automates shell tasks, converting output into structured data.</p> <p><strong>IMAP Email Ingestion:</strong> Retrieves emails and converts them into structured JSON data for ingestion.</p> <h2 id="advanced-data-processing-capturable-executables-ces">Advanced Data Processing: Capturable Executables (CEs)</h2> <p><code dir="auto">surveilr</code> uses <strong>Capturable Executables (CEs)</strong> to enhance its data ingestion and transformation pipelines. These scripts allow for automated tasks, including:</p> <ul> <li><strong>Transformation:</strong> Converts raw data into standardized formats.</li> <li><strong>Automation:</strong> Triggers real-time or scheduled tasks.</li> <li><strong>Validation:</strong> Ensures that all ingested data meets quality and regulatory standards.</li> </ul> <p>The file-naming conventions for CEs help determine the expected output format, such as JSON or plain text, enabling users to tailor ingestion processes to specific requirements.</p> <h2 id="data-quality-and-governance">Data Quality and Governance</h2> <p>Once processed, data is stored in the <strong>Resource Surveillance State Database (RSSD)</strong>, a universal schema that ensures consistency across datasets. The RSSD facilitates easy querying, analysis, and integration into external systems, data warehouses, or business intelligence platforms.</p> <ul> <li><strong>Stateful Context Management:</strong> Tracks data throughout its lifecycle, ensuring continuity and version control.</li> <li><strong>Data Synchronization and Aggregation:</strong> Surveilr synchronizes real-time and batch data, ensuring that all information is available for advanced analytics and reporting.</li> </ul> <h2 id="web-ui-for-data-visualization-and-auditing">Web UI for Data Visualization and Auditing</h2> <p><code dir="auto">surveilr</code> provides a Web UI for users to view ingested data in real-time or access processed offline data. Key features include:</p> <ul> <li><strong>Data Visualization:</strong> The Web UI module enable easy configurable web components to view the ingested data locally.</li> <li><strong>Querying Capabilities:</strong> Full SQL querying support enables users to extract and analyze data from both real-time and batch ingestion sources.</li> <li><strong>Audit and Traceability:</strong> The UI includes tracking features that provide visibility into both real-time and batch data flows, ensuring compliance and security audits are easily conducted.</li> </ul> <h2 id="data-synchronization-and-aggregation">Data Synchronization and Aggregation</h2> <p>The Data Synchronization and Aggregation phase is the final and critical step in the surveilr pipeline. After data has been ingested and processed through various stages, this phase ensures that the data is systematically synchronized and aggregated into a central data store. This final step consolidates both real-time and batch-processed data, making it accessible for advanced analytics, reporting, and integration with other supporting systems.</p> <h3 id="key-functions">Key Functions</h3> <ul> <li><strong>Data Synchronization:</strong> Ensures real-time and batch data are consistently updated in the central repository.</li> <li><strong>Data Aggregation:</strong> Consolidates data from different sources into a unified structure.</li> <li><strong>Data Transformation:</strong> Applies transformations to standardize data formats, ensure consistency, and enrich the data (e.g., merging fields, calculating metrics). The data transformation also includes anonymizing sensitive information before the transmission.</li> </ul> <h3 id="advanced-analytics-and-reporting">Advanced Analytics and Reporting</h3> <p>Consolidated data enables sophisticated analysis and reporting through:</p> <ul> <li><strong>Business Intelligence (BI):</strong> Data visualization tools and dashboards.</li> <li><strong>Predictive Analytics:</strong> Analyzes historical data to forecast trends.</li> <li><strong>Custom Reporting:</strong> Generates tailored reports based on user requirements.</li> </ul> <h3 id="integration-with-other-systems">Integration with Other Systems</h3> <p><code dir="auto">surveilr</code> facilitates data exchange across different systems through:</p> <ul> <li><strong>APIs:</strong> Provides APIs for external systems to access aggregated data.</li> <li><strong>Data Export:</strong> Exports data in formats like CSV and JSON.</li> </ul> <h3 id="data-quality-and-governance-1">Data Quality and Governance</h3> <p><code dir="auto">surveilr</code> maintains accuracy, consistency, and reliability through:</p> <ul> <li><strong>Data Validation:</strong> Ensures data correctness before synchronization.</li> <li><strong>Audit Trails:</strong> Tracks changes and updates to maintain transparency.</li> <li><strong>Compliance:</strong> Adheres to data privacy and regulatory standards such as GDPR and HIPAA.</li> </ul> <h2 id="data-flow-overview-of-surveilr-based-integration-pipeline">Data Flow Overview of surveilr based Integration Pipeline</h2> <p>The <code dir="auto">surveilr</code> platform operates as a sophisticated data integration and processing system, employing a local-first, edge-based approach with SQL at its core. Let’s explore how data flows through this comprehensive platform.</p> <h3 id="data-acquisition">Data Acquisition</h3> <p>The data journey begins with multiple acquisition pathways:</p> <ul> <li><strong>Traditional File Systems:</strong> Direct access to local OS file systems</li> <li><strong>Cloud Integration:</strong> Connection to cloud storage services like AWS S3</li> <li><strong>Web Protocols:</strong> Support for WebDAV for web-based file management</li> <li><strong>Secure Transfer:</strong> SFTP capabilities for secure data transmission</li> <li><strong>Document Conversion:</strong> Virtual printers enabling digital document conversion</li> </ul> <h3 id="data-ingestion-and-transformation">Data Ingestion and Transformation</h3> <p>Once acquired, data passes through robust ingestion pipelines:</p> <ul> <li> <p>Multiple Format Support:</p> <ul> <li>Structured data: JSON, XML, CSV</li> <li>Industry protocols: HL7, FHIR, EDI</li> </ul> </li> <li> <p>Data Transformation:</p> <ul> <li>Conversion into queryable formats, primarily JSON</li> <li>Optimization through columnar storage formats like Parquet</li> <li>Focus on enhancing analytics and reporting capabilities</li> </ul> </li> </ul> <h3 id="system-integration-and-storage">System Integration and Storage</h3> <p>Data flows seamlessly between various systems:</p> <ul> <li>Integration Points: <ul> <li>PLM systems (GitHub, Jira)</li> <li>ERP systems</li> <li>Messaging platforms</li> </ul> </li> <li>Data Storage and Processing: <ul> <li>Custom SQL tables</li> <li>Built-in SQL views</li> <li>Multiple database support: <ul> <li>SQLite,PostgreSQL,MySQL,Cloud-based systems (DuckDB)</li> </ul> </li> </ul> </li> </ul> <h3 id="user-interaction-layer">User Interaction Layer</h3> <p>The data flow culminates in two primary interfaces:</p> <ul> <li>Surveilr Web UI: <ul> <li>SQL query execution</li> <li>Content management capabilities</li> </ul> </li> <li>Console Interface: <ul> <li>SQL navigation tools</li> <li>Orchestration features</li> <li>Audit functionality</li> </ul> </li> </ul> <h2 id="looking-ahead">Looking Ahead</h2> <p>As edge computing continues to evolve, surveilr’s local-first, stateful approach to data integration positions it as a powerful tool for organizations looking to optimize their data processing and integration pipelines. Whether you’re dealing with healthcare data, infrastructure monitoring, or complex content assembly, surveilr provides the flexibility, security, and performance needed in today’s data landscape.</p> <p>Ready to transform your data integration strategy? Explore <code dir="auto">surveilr</code> and experience the power of local-first, edge-based, SQL centric data processing engine.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Integration </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/surveilr-integration-engine/&title=surveilr: A Local-First, Edge-based SQL-Centric Integration Engine"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=surveilr: A Local-First, Edge-based SQL-Centric Integration Enginehttps://www.surveilr.com/blog/surveilr-integration-engine/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/surveilr-integration-engine/&title=surveilr: A Local-First, Edge-based SQL-Centric Integration Engine"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 99007 | 2025-04-07 05:49:50.407997630 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTYKVT9A7RZVEMYQCPQ | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/power-of-sql-and-sql-views/index.html | bf15dd13b22fa54f971af6b5f7005eeb69f8f502 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/power-of-sql-and-sql-views/"},"headline":"Unlocking surveilr's Power with SQL Views for Data Integration","description":"Discover how SQL views enhance surveilr's data integration, simplifying complex queries while ensuring security and compliance for regulated sectors.","image":"https://www.surveilr.com/_astro/power-of-sql-and-sql-views.D9V6AARL_Z12Ot0b.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-10-07T00:00:00.000Z","dateModified":"2024-10-07T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Unlocking surveilr's Power with SQL Views for Data Integration","url":"https://www.surveilr.com/blog/power-of-sql-and-sql-views/","description":"Discover how SQL views enhance surveilr's data integration, simplifying complex queries while ensuring security and compliance for regulated sectors.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Discover how SQL views enhance surveilr's data integration, simplifying complex queries while ensuring security and compliance for regulated sectors." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/power-of-sql-and-sql-views/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/power-of-sql-and-sql-views/"><meta property="og:type" content="website"><meta property="og:title" content="Unlocking surveilr's Power with SQL Views for Data Integration"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Discover how SQL views enhance surveilr's data integration, simplifying complex queries while ensuring security and compliance for regulated sectors."><meta property="og:image" content="https://www.surveilr.com/_astro/power-of-sql-and-sql-views.D9V6AARL_Z12Ot0b.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/power-of-sql-and-sql-views/"><meta name="twitter:title" content="Unlocking surveilr's Power with SQL Views for Data Integration"><meta name="twitter:description" content="Discover how SQL views enhance surveilr's data integration, simplifying complex queries while ensuring security and compliance for regulated sectors."><meta name="twitter:image" content="https://www.surveilr.com/_astro/power-of-sql-and-sql-views.D9V6AARL_Z12Ot0b.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Unlocking surveilr's Power with SQL Views for Data Integration</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="a52b1a8b-ee5d-4dea-a959-76cf2cce49cc" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="a52b1a8b-ee5d-4dea-a959-76cf2cce49cc"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Power Of Sql And Sql Views </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/power-of-sql-and-sql-views/","name":"Power Of Sql And Sql Views"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/pradeep-narayanan.DRyfIcLY_ZF4Jr3.avif" alt="Avatar Description" draggable="false" width="64" height="64" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Pradeep Narayanan </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Oct 7, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 5 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>In the world of data integration and processing, flexibility and extensibility are paramount. The ability to easily prepare, integrate, and analyze data from multiple sources is critical. <code dir="auto">surveilr</code>, with its stateful, local-first, and edge-based architecture, stands out as a powerful solution for these challenges. One of the key strengths of <code dir="auto">surveilr</code> is its SQL-centric nature, making it both flexible and extendable. And when it comes to maximizing this power, there’s no better tool in the SQL toolbox than SQL views.</p> <h2 id="the-foundation-sql-in-surveilr">The Foundation: SQL in <code dir="auto">surveilr</code></h2> <p>At the core of <code dir="auto">surveilr</code> is its <strong>SQL-centric approach</strong>. Every piece of data it processes is queryable using SQL, allowing users to manipulate and organize information in a way that best fits their workflow. This SQL-centric design makes it easy to set up data pipelines, perform complex transformations, and create relationships between disparate data sources. Whether you’re working with clinical operations data, auditing evidence collection and reporting, pharmacy records, billing information, or any other type of clinical or non-clinical data, SQL provides a robust foundation to access and modify that data seamlessly and effortlessly.</p> <p>However, while basic SQL queries can deliver tremendous value, <code dir="auto">surveilr</code>’s real potential can be unleashed with the use of <strong>SQL views</strong>.</p> <h2 id="what-are-sql-views">What are SQL Views?</h2> <p>An <strong>SQL view</strong> is a virtual table defined by a query. It does not store data itself but acts as a window through which you can view and interact with data stored in underlying tables. Essentially, a view abstracts away the complexity of a query, letting users interact with data as though it were a single unified table.</p> <p>Here’s why views are so powerful in the context of surveilr:</p> <ul> <li><strong>Simplification of Complex Queries</strong>: Rather than repeatedly writing complex queries, you can define a view once and reuse it whenever needed. This is particularly helpful when dealing with intricate joins, filtering, or aggregations across multiple tables and systems.</li> <li><strong>Data Abstraction</strong>: Views provide a layer of abstraction, allowing you to hide certain complexities or fields from users who may not need access to all the underlying data. For example, you could create a view that shows only anonymized or deidentified data for specific use cases, ensuring HIPAA compliance without sacrificing usability.</li> <li><strong>Data Consistency</strong>: By defining a view, you ensure that everyone accessing the data sees the same results based on a consistent underlying query. This reduces errors and ensures that reports or analyses built on top of those views are based on uniform data.</li> </ul> <h2 id="extending-surveilrs-power-with-sql-views">Extending <code dir="auto">surveilr</code>’s Power with SQL Views</h2> <p><code dir="auto">surveilr</code> already excels at integrating data from multiple sources—be it clinical records, billing data, or operational logs. But the real power of <code dir="auto">surveilr</code> comes when you use SQL views to extend its capabilities. Let’s explore how SQL views make <code dir="auto">surveilr</code> even more powerful:</p> <ul> <li> <p><strong>Combining Data Across Systems</strong> <code dir="auto">surveilr</code> integrates data from various systems in real-time. By using SQL views, you can create virtual tables that combine data from multiple systems. For example, a view could bring together patient records, pharmacy orders, and billing details, offering a 360-degree view of patient care without manually joining or reprocessing data every time.</p> </li> <li> <p><strong>Preprocessing and Data Preparation</strong> Views in <code dir="auto">surveilr</code> can be used to preprocess or transform data before it’s consumed by downstream applications or users. You could create views that standardize data formats, filter out irrelevant information, or aggregate results—making data easier to analyze while maintaining a clean underlying schema.</p> </li> <li> <p><strong>Creating Custom Dashboards and Reports</strong> SQL views enable the creation of custom datasets that can be fed directly into BI tools, reports, or dashboards. <code dir="auto">surveilr</code> users can define views that pull in exactly the data they need, customized for each stakeholder—whether they need high-level summaries or granular operational data.</p> </li> <li> <p><strong>Enhanced Security and Compliance</strong> Views provide a way to control what data different users or systems can see. By setting up views that show only the fields or records that a user needs, <code dir="auto">surveilr</code> users can maintain security and regulatory compliance. For example, you could create views that display anonymized patient data for non-clinical staff while allowing full access for medical personnel.</p> </li> </ul> <h2 id="real-world-examples-of-extending-surveilr-with-sql-views">Real-World Examples of Extending <code dir="auto">surveilr</code> with SQL Views</h2> <ul> <li><strong>Customized Reporting</strong>: Create views to aggregate data from multiple sources, generating customized reports.</li> <li><strong>Data Validation</strong>: Use views to validate data against specific criteria, ensuring data quality and integrity.</li> <li><strong>Data Transformation</strong>: Create views to transform data formats, enabling seamless integration with third-party systems.</li> <li><strong>Simplified Data Modeling</strong>: Views allow users to create customized data models, making it easier to analyze and report on complex data.</li> <li><strong>Reusability</strong>: Views can be reused across multiple queries and applications, reducing development time and improving maintainability.</li> <li><strong>Data Abstraction</strong>: Views hide underlying data complexity, making it easier to manage and maintain data integrations.</li> <li><strong>Improved Security</strong>: Views enable fine-grained access control, ensuring sensitive data is only accessible to authorized users.</li> </ul> <h2 id="real-world-example-using-sql-views-for-healthcare-data-integration">Real-World Example: Using SQL Views for Healthcare Data Integration</h2> <p>Imagine a healthcare provider using <code dir="auto">surveilr</code> to integrate data from different departments—clinical records, pharmacy, and billing. The provider wants to track patient progress and costs without exposing sensitive information unnecessarily.</p> <p>Using SQL views, the provider can create:</p> <ul> <li>A <strong>view for clinicians</strong> that combines patient health records and pharmacy data, providing real-time updates on patient treatment plans while hiding financial data.</li> <li>A <strong>view for billing</strong> that aggregates treatment costs across departments without exposing confidential medical information.</li> <li>A <strong>view for administrators</strong> that offers a high-level overview of hospital operations, combining anonymized clinical data with financial performance metrics—all in one easily accessible table.</li> </ul> <p>These views can be reused across the organization, ensuring that each department gets exactly what it needs while maintaining security and consistency across all datasets.</p> <h2 id="conclusion">Conclusion</h2> <p><code dir="auto">surveilr</code>’s SQL-centric architecture is already a game-changer for integrating and analyzing data from multiple systems. However, its potential truly shines when extended using SQL views. Views allow you to simplify complex queries, combine data in powerful ways, and enhance both security and compliance. They enable you to preprocess and transform data effortlessly, all while keeping the underlying system flexible and scalable.</p> <p>Remember, the true power of <code dir="auto">surveilr</code> lies not just in what it can do out of the box, but in how easily you can extend and customize it to meet your specific needs. By mastering the use of SQL views, you unlock a world of possibilities for your data integration and processing workflows.</p> <p>By leveraging SQL views, <code dir="auto">surveilr</code> users can unlock new levels of functionality, making data integration and analysis not only more powerful but also more user-friendly. Whether you’re a developer, data engineer, or analyst, SQL views offer an elegant way to extend <code dir="auto">surveilr</code>’s already robust capabilities, giving you the power to customize your data workflows in ways that best suit your organization’s needs.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> SQL </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Views </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> RSSD </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/power-of-sql-and-sql-views/&title=Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilitieshttps://www.surveilr.com/blog/power-of-sql-and-sql-views/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/power-of-sql-and-sql-views/&title=Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 92229 | 2025-04-07 05:49:49.363005387 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTYZAJ5TPZF3MY38Q19 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/quality-management-pattern/index.html | 11a7d78db8aad046a1c280defaa2f0767d0c93e0 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/quality-management-pattern/"},"headline":"Quality Management for Safety-Critical Sectors with Surveilr","description":"`surveilr` ensures compliance in safety-critical industries by streamlining data audits and verifying adherence to quality protocols.","image":"https://www.surveilr.com/_astro/quality-management-pattern.DfE3CvUC_Z2s79F.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-02-18T00:00:00.000Z","dateModified":"2024-02-18T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Quality Management for Safety-Critical Sectors with Surveilr","url":"https://www.surveilr.com/blog/quality-management-pattern/","description":"`surveilr` ensures compliance in safety-critical industries by streamlining data audits and verifying adherence to quality protocols.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="`surveilr` ensures compliance in safety-critical industries by streamlining data audits and verifying adherence to quality protocols." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/quality-management-pattern/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/quality-management-pattern/"><meta property="og:type" content="website"><meta property="og:title" content="Quality Management for Safety-Critical Sectors with Surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="`surveilr` ensures compliance in safety-critical industries by streamlining data audits and verifying adherence to quality protocols."><meta property="og:image" content="https://www.surveilr.com/_astro/quality-management-pattern.DfE3CvUC_Z2s79F.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/quality-management-pattern/"><meta name="twitter:title" content="Quality Management for Safety-Critical Sectors with Surveilr"><meta name="twitter:description" content="`surveilr` ensures compliance in safety-critical industries by streamlining data audits and verifying adherence to quality protocols."><meta name="twitter:image" content="https://www.surveilr.com/_astro/quality-management-pattern.DfE3CvUC_Z2s79F.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Quality Management for Safety-Critical Sectors with Surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="d32937d6-1d53-4f59-94f3-d82906aa6caf" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="d32937d6-1d53-4f59-94f3-d82906aa6caf"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Quality Management Pattern </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/quality-management-pattern/","name":"Quality Management Pattern"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/shahid-shah.B2DFcsvR_ZITVg0.avif" alt="Avatar Description" draggable="false" width="2818" height="2746" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Shahid N. Shah </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Feb 18, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 3 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Quality Management for Safety-Critical Industries </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>Industries such as <strong>healthcare</strong>, <strong>energy</strong>, <strong>aviation</strong>, and other safety-critical sectors require stringent <strong>quality management</strong> protocols to ensure the safety of their operations. In these environments, failure to adhere to quality protocols can have serious consequences.</p> <p><strong><code dir="auto">surveilr</code></strong> is a powerful tool for quality management organizations tasked with collecting and auditing data to ensure that staff are following proper protocols. By aggregating data from disparate systems and auditing logs or records, <code dir="auto">surveilr</code> makes it easier to verify that proper safety and quality processes are in place. Whether for internal audits, external regulatory reviews, or continuous quality improvement, <code dir="auto">surveilr</code> helps ensure that critical operations adhere to the highest standards.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Pattern </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/quality-management-pattern/&title=Quality Management for Safety-Critical Industries"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Quality Management for Safety-Critical Industrieshttps://www.surveilr.com/blog/quality-management-pattern/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/quality-management-pattern/&title=Quality Management for Safety-Critical Industries"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 83574 | 2025-04-07 05:49:51.213991648 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTYQTCGHNJYRZMGVZJA | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/compliance-explorer/index.html | 0e9595091093ba265e718ab3f769553ec43cc668 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/compliance-explorer/"},"headline":"Compliance Explorer: SQL-Driven Solution for Information Controls Management","description":"Discover Compliance Explorer, an SQL-based tool built on surveilr to streamline compliance management. Learn how this solution enables efficient querying, reporting, and real-time control over regulatory data.","image":"https://www.surveilr.com/_astro/sql-for-compliance.R6ct7kQN_27FTlX.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-11-15T00:00:00.000Z","dateModified":"2024-11-15T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Compliance Explorer: SQL-Driven Solution for Information Controls Management","url":"https://www.surveilr.com/blog/compliance-explorer/","description":"Discover Compliance Explorer, an SQL-based tool built on surveilr to streamline compliance management. Learn how this solution enables efficient querying, reporting, and real-time control over regulatory data.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Discover Compliance Explorer, an SQL-based tool built on surveilr to streamline compliance management. Learn how this solution enables efficient querying, reporting, and real-time control over regulatory data." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/compliance-explorer/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/compliance-explorer/"><meta property="og:type" content="website"><meta property="og:title" content="Compliance Explorer: SQL-Driven Solution for Information Controls Management"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Discover Compliance Explorer, an SQL-based tool built on surveilr to streamline compliance management. Learn how this solution enables efficient querying, reporting, and real-time control over regulatory data."><meta property="og:image" content="https://www.surveilr.com/_astro/sql-for-compliance.R6ct7kQN_27FTlX.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/compliance-explorer/"><meta name="twitter:title" content="Compliance Explorer: SQL-Driven Solution for Information Controls Management"><meta name="twitter:description" content="Discover Compliance Explorer, an SQL-based tool built on surveilr to streamline compliance management. Learn how this solution enables efficient querying, reporting, and real-time control over regulatory data."><meta name="twitter:image" content="https://www.surveilr.com/_astro/sql-for-compliance.R6ct7kQN_27FTlX.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Compliance Explorer: SQL-Driven Solution for Information Controls Management</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="7f701ace-8bb4-42bb-ac05-371657aaef5f" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="7f701ace-8bb4-42bb-ac05-371657aaef5f"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Compliance Explorer </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/compliance-explorer/","name":"Compliance Explorer"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/ajay-kumaran.CJDSQGQJ_Z1kBgPT.avif" alt="Ajay Kumaran" draggable="false" width="508" height="508" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Ajay Kumaran </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Nov 15, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 3 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <h1 id="building-a-compliance-explorer-sql-based-approach-to-manage-information-controls">Building a Compliance Explorer: SQL-Based Approach to Manage Information Controls</h1> <p>In today’s data-driven landscape, organizations must rigorously manage risks related to information systems, security, and data compliance. Information Controls help address these needs by implementing regulatory, statutory, and operational measures that ensure organizational resilience and regulatory alignment. With Compliance Explorer, built on <code dir="auto">surveilr</code>, we introduce an SQL-based solution that enables effective compliance management and efficient data interaction.</p> <h2 id="what-is-compliance-explorer">What is Compliance Explorer?</h2> <p>Compliance Explorer is a SQL-driven tool for managing and exploring information controls. By leveraging SQL-based ETL (Extract, Transform, Load) patterns, Compliance Explorer can ingest, cache, and present compliance data through a web UI, creating an accessible framework for organizations to view, query, and report on data-driven compliance controls. This tool is powered by <code dir="auto">surveilr</code> and structured around three core scripts: <code dir="auto">stateless.sql</code>, <code dir="auto">stateful.sql</code>, and <code dir="auto">package.sql.ts</code>.</p> <h2 id="components-of-compliance-explorer">Components of Compliance Explorer</h2> <h3 id="1-statelesssql-defining-views-for-data-extraction">1. <code dir="auto">stateless.sql</code>: Defining Views for Data Extraction</h3> <p>The <code dir="auto">stateless.sql</code> script creates views that specify how controls data should be extracted from CSV files and presented. For instance, in a typical setup, the <code dir="auto">uniform_resource.csv</code> tables are ingested to outline compliance metrics across different regions and frameworks. By focusing on view-based transformations, <code dir="auto">stateless.sql</code> avoids data duplication and ensures up-to-date presentation of compliance controls.</p> <div class="expressive-code"><link rel="stylesheet" href="../../_astro/ec.tm3va.css"><script type="module" src="../../_astro/ec.8zarh.js"></script><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5F636F">-- Sample view creation in stateless.sql</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">CREATE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">VIEW</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">compliance_view</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span><span style="--0:#D6DEEB;--1:#403F53"> control_id, control_description, source, </span><span style="--0:#C792EA;--1:#8844AE">geography</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">FROM</span><span style="--0:#D6DEEB;--1:#403F53"> uniform_resource;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="-- Sample view creation in stateless.sqlCREATE VIEW compliance_view ASSELECT control_id, control_description, source, geographyFROM uniform_resource;"><div></div></button></div></figure></div> <h3 id="2-statefulsql-caching-extracted-data">2. <code dir="auto">stateful.sql</code>: Caching Extracted Data</h3> <p>Once data has been ingested and structured through <code dir="auto">stateless.sql</code> views, <code dir="auto">stateful.sql</code> takes over by creating tables to cache this extracted data. Caching enables quicker access to precomputed information, making data querying faster and more efficient. This script is vital for managing stateful operations where historical data and ongoing compliance insights are needed.</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="sql"><code><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5F636F">-- Sample table creation in stateful.sql</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">CREATE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">TABLE</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">compliance_cache</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">AS</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">SELECT</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#7FDBCA;--1:#096E72">*</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">FROM</span><span style="--0:#D6DEEB;--1:#403F53"> compliance_view;</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="-- Sample table creation in stateful.sqlCREATE TABLE compliance_cache ASSELECT * FROM compliance_view;"><div></div></button></div></figure></div> <h3 id="3-packagesqlts-orchestrating-the-database-and-web-ui">3. <code dir="auto">package.sql.ts</code>: Orchestrating the Database and Web UI</h3> <p>The <code dir="auto">package.sql.ts</code> file is the entry point of Compliance Explorer. It loads database objects, initializes a web UI for interaction, and sets up menu-based navigation within the web application. Using Deno for runtime execution, <code dir="auto">package.sql.ts</code> can dynamically apply SQL logic, update views, and orchestrate cached data tables in real time. The setup allows users to view controls data, query compliance information, and manage navigation seamlessly within the UI.</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="typescript"><code><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5D6376">// package.sql.ts entry point</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">export</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">class</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#FFCB8B;--1:#111111">ComplianceExplorerSqlPages</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">extends</span><span style="--0:#D6DEEB;--1:#403F53"> spn</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#C5E478;--1:#3B61B0">TypicalSqlPageNotebook</span><span style="--0:#D6DEEB;--1:#403F53"> {</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#919F9F;--1:#5D6376">// DML logic for navigation and page generation</span></div></div><div class="ec-line"><div class="code"><span style="--0:#D6DEEB;--1:#403F53">}</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="// package.sql.ts entry pointexport class ComplianceExplorerSqlPages extends spn.TypicalSqlPageNotebook { // DML logic for navigation and page generation}"><div></div></button></div></figure></div> <h2 id="setting-up-compliance-explorer">Setting Up Compliance Explorer</h2> <h3 id="step-1-directory-structure-and-ingestion">Step 1: Directory Structure and Ingestion</h3> <p>To get started, prepare a working directory for Compliance Explorer and an <code dir="auto">ingest</code> folder for control files.</p> <div class="expressive-code"><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">$</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">mkdir</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-p</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">/tmp/compliance-explorer/ingest</span></div></div><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">$</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">cd</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">/tmp/compliance-explorer</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="$ mkdir -p /tmp/compliance-explorer/ingest$ cd /tmp/compliance-explorer"><div></div></button></div></figure></div> <p>Place control files, such as <code dir="auto">SCF_2024.2.csv</code>, into the <code dir="auto">ingest</code> folder. The structure should resemble:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="plaintext"><code><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">compliance-explorer</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">├── ingest</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">│ ├── SCF_2024.2.csv</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">├── package.sql.ts</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">└── stateless.sql</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="compliance-explorer├── ingest│ ├── SCF_2024.2.csv├── package.sql.ts└── stateless.sql"><div></div></button></div></figure></div> <h3 id="step-2-ingesting-data-with-surveilr">Step 2: Ingesting Data with <code dir="auto">surveilr</code></h3> <p>Download the <code dir="auto">surveilr</code> binary into the <code dir="auto">compliance-explorer</code> directory, and then use the following command to ingest the files from the <code dir="auto">ingest</code> folder. This process generates an SQLite database, <code dir="auto">resource-surveillance.sqlite.db</code>, containing all the control data.</p> <div class="expressive-code"><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">$</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">./surveilr</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">ingest</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">files</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-r</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">ingest/</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="$ ./surveilr ingest files -r ingest/"><div></div></button></div></figure></div> <p>After ingestion, your directory should look like this:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="plaintext"><code><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">compliance-explorer</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">├── ingest</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">│ ├── SCF_2024.2.csv</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">├── package.sql.ts</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">└── stateless.sql</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">└── resource-surveillance.sqlite.db</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="compliance-explorer├── ingest│ ├── SCF_2024.2.csv├── package.sql.ts└── stateless.sql└── resource-surveillance.sqlite.db"><div></div></button></div></figure></div> <h3 id="step-3-running-compliance-explorer">Step 3: Running Compliance Explorer</h3> <p>Once ingestion is complete, run <code dir="auto">package.sql.ts</code> to load the data in the console or launch the interactive web UI:</p> <div class="expressive-code"><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">$</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">deno</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">run</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">-A</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">./package.sql.ts</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#7FDBCA;--1:#096E72">|</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#82AAFF;--1:#3B61B0">surveilr</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">shell</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#919F9F;--1:#5F636F"># Console interaction</span></div></div><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">$</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">surveilr</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">shell</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">./package.sql.ts</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#919F9F;--1:#5F636F"># Alternative console command</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="$ deno run -A ./package.sql.ts | surveilr shell # Console interaction$ surveilr shell ./package.sql.ts # Alternative console command"><div></div></button></div></figure></div> <p>To interact through the web, start the UI in watch mode:</p> <div class="expressive-code"><figure class="frame is-terminal not-content"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#82AAFF;--1:#3B61B0">$</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">../../std/surveilrctl.ts</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">dev</span></div></div></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="$ ../../std/surveilrctl.ts dev"><div></div></button></div></figure></div> <p>Navigate to <code dir="auto">http://localhost:9000/</code> to access the Compliance Explorer interface. Here, you can browse controls, query information, and explore compliance details.</p> <h2 id="working-with-cached-data">Working with Cached Data</h2> <p>After applying <code dir="auto">stateless.sql</code>, you no longer need the raw data files in <code dir="auto">ingest/</code>—all content is accessible via views or cached tables in <code dir="auto">resource-surveillance.sqlite.db</code>. This SQLite database is portable and can be renamed, archived, or used with reporting tools like DBeaver, DataGrip, or other SQLite-compatible software for further analysis.</p> <h2 id="why-use-compliance-explorer">Why Use Compliance Explorer?</h2> <p>Compliance Explorer simplifies complex compliance requirements by using an SQL-based approach that scales with your data needs. With Compliance Explorer, you can:</p> <ul> <li><strong>Easily query compliance controls</strong> across multiple regulatory frameworks.</li> <li><strong>Build reports</strong> based on cached compliance data.</li> <li><strong>Seamlessly integrate</strong> with the web UI for real-time interaction and insights.</li> </ul> <p>Compliance Explorer provides a robust, scalable solution for organizations needing a centralized view of compliance data across various standards, making it ideal for sectors that must comply with stringent information governance and data protection regulations.</p> <h2 id="conclusion">Conclusion</h2> <p>With Compliance Explorer, powered by <code dir="auto">surveilr</code>, your organization gains a flexible and efficient tool for navigating the complexities of data compliance and information controls. Try it today to see how SQL-based compliance management can transform your organization’s approach to data-driven decision-making.</p> <p>For more insights on SQL-based ETL/ELT processes and compliance management, explore our <a href="../../blog.html">surveilr blog</a>.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Compliance explorer </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Compliance management </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Etl for compliance </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Regulatory compliance </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Data governance </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Sql-based compliance tools </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/compliance-explorer/&title=Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Toolhttps://www.surveilr.com/blog/compliance-explorer/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/compliance-explorer/&title=Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 102150 | 2025-04-07 05:49:50.826994520 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTZCAWRH1XJ01K9VM15 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/rssd-excel-portability-sql-power/index.html | 55f637f1631745bcdf5a4166963d214d5ac6331a | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/rssd-excel-portability-sql-power/"},"headline":"RSSDs Deliver Portable, SQL-Powered Data Integration for Compliance","description":"Learn how RSSDs combine the flexibility of Excel with the power of SQL to simplify data tracking, management, and querying for regulatory and compliance needs.","image":"https://www.surveilr.com/_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zt237J.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-02-10T00:00:00.000Z","dateModified":"2024-02-10T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"RSSDs Deliver Portable, SQL-Powered Data Integration for Compliance","url":"https://www.surveilr.com/blog/rssd-excel-portability-sql-power/","description":"Learn how RSSDs combine the flexibility of Excel with the power of SQL to simplify data tracking, management, and querying for regulatory and compliance needs.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Learn how RSSDs combine the flexibility of Excel with the power of SQL to simplify data tracking, management, and querying for regulatory and compliance needs." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/rssd-excel-portability-sql-power/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/rssd-excel-portability-sql-power/"><meta property="og:type" content="website"><meta property="og:title" content="RSSDs Deliver Portable, SQL-Powered Data Integration for Compliance"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Learn how RSSDs combine the flexibility of Excel with the power of SQL to simplify data tracking, management, and querying for regulatory and compliance needs."><meta property="og:image" content="https://www.surveilr.com/_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zt237J.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/rssd-excel-portability-sql-power/"><meta name="twitter:title" content="RSSDs Deliver Portable, SQL-Powered Data Integration for Compliance"><meta name="twitter:description" content="Learn how RSSDs combine the flexibility of Excel with the power of SQL to simplify data tracking, management, and querying for regulatory and compliance needs."><meta name="twitter:image" content="https://www.surveilr.com/_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zt237J.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>RSSDs Deliver Portable, SQL-Powered Data Integration for Compliance</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="3e4d8e74-ce7d-4c1c-bea3-354a0d0460cc" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="3e4d8e74-ce7d-4c1c-bea3-354a0d0460cc"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Rssd Excel Portability Sql Power </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/rssd-excel-portability-sql-power/","name":"Rssd Excel Portability Sql Power"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/shahid-shah.B2DFcsvR_ZITVg0.avif" alt="Avatar Description" draggable="false" width="2818" height="2746" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Shahid N. Shah </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Feb 10, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 5 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> RSSDs: Portability of Excel, Power of SQL </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>In today’s data-driven world, the ability to track, manage, and analyze information is critical for organizations of all sizes. <strong>Surveilr</strong> delivers cutting-edge solutions through its <a href="../why-stateful-integration/index.html"><strong>stateful data integration</strong> process</a>, which ensures that every piece of data is consistently tracked, organized, and available for immediate querying.</p> <p>The engine behind all of this is a lightweight, yet powerful <strong>SQLite</strong> database we call the <strong>Resource Surveillance State Database (RSSD)</strong>.</p> <p>At its core, the <strong>RSSD</strong> is a <strong>SQLite database</strong> that serves as the backbone of surveilr’s stateful data operations. SQLite is a widely-used, embedded database engine that stores data in a <strong>single file</strong>—making it portable, fast, and extremely efficient for local data operations. The RSSD is the hub where all data integration activities occur, ensuring that information is continuously stored, tracked, and ready for retrieval whenever needed.</p> <h2 id="understanding-rssd-through-an-excel-analogy">Understanding RSSD Through an Excel Analogy</h2> <p>For those unfamiliar with databases, it may be easier to think of the <strong>Resource Surveillance State Database (RSSD)</strong> as something similar to <strong>Microsoft Excel</strong>—a tool most of us have used at some point. Here’s a breakdown of how the RSSD works, using an Excel analogy:</p> <h3 id="rssd-is-like-an-excel-workbook">RSSD is Like an Excel Workbook</h3> <p>Just like an Excel workbook is a <strong>single file</strong> that contains all of your data, an RSSD is also a <strong>single file</strong> that contains all of the data surveilr is managing. This single file can store everything from simple numbers to complex records that need to be tracked and queried.</p> <h3 id="tables-are-like-excel-worksheets">Tables are Like Excel Worksheets</h3> <p>In Excel, you organize data into <strong>worksheets</strong>. Similarly, in the RSSD, the data is organized into <strong>tables</strong>. Just as a worksheet holds rows and columns of data, a table in the RSSD holds <strong>rows of records and columns of fields</strong>. For example, you might have one table for customer data, another for transactions, and yet another for logs.</p> <h3 id="sql-is-like-excel-formulas">SQL is Like Excel Formulas</h3> <p>In Excel, you use <strong>formulas</strong> to manipulate your data. These formulas allow you to perform calculations, look up values, or summarize data across your worksheets. The RSSD uses <strong>SQL (Structured Query Language)</strong> instead of Excel formulas, but the purpose is similar—it’s a way to <strong>interact with and analyze the data</strong> in the tables.</p> <p>Just like in Excel, where you can create simple to complex formulas depending on your needs, the RSSD allows you to extract insights from your data using flexible SQL queries that work across different tables of information.</p> <h3 id="flexibility-and-power">Flexibility and Power</h3> <p>Just as Excel gives you the ability to manipulate, organize, and analyze your data in many different ways, the RSSD allows you to do all of this too—only it uses SQL, which is more powerful when working with large datasets. For example, while Excel might slow down with very large workbooks, the RSSD, thanks to SQLite, can handle <strong>millions of records</strong> without breaking a sweat.</p> <h3 id="portable-and-self-contained">Portable and Self-Contained</h3> <p>In the same way that you can take an Excel file and send it to someone else (and they’ll have access to all the worksheets and data), the RSSD is a <strong>self-contained</strong> file. This means you can move the entire database, complete with all its tables and data, simply by copying the RSSD file to another location. There’s no need for a complex setup or configuration—just open it and start working with the data.</p> <h2 id="how-rssd-works-as-a-sqlite-database">How RSSD Works as a SQLite Database</h2> <p>The <strong>Resource Surveillance State Database (RSSD)</strong> leverages <strong>SQLite</strong>, a fully-featured relational database that is known for being:</p> <ul> <li><strong>Lightweight</strong>: SQLite operates entirely within a single file. There is no need for a separate database server or complex configuration, which makes it ideal for edge-based data operations that need portability and ease of deployment.</li> <li><strong>Efficient</strong>: Even though it’s a single file, SQLite is capable of handling large volumes of data with fast read/write speeds. This efficiency is key to surveilr’s ability to <strong>track the state of data</strong> across different systems without significant performance overhead.</li> <li><strong>ACID-compliant</strong>: SQLite ensures that all transactions are <strong>atomic</strong>, <strong>consistent</strong>, <strong>isolated</strong>, and <strong>durable</strong>. This means that any operation—whether it’s inserting, updating, or deleting data—completes fully or not at all, ensuring the integrity of your data even during system failures.</li> <li><strong>Self-contained</strong>: All the logic, schema, and data reside within the RSSD file, making it easy to <strong>transport</strong> and <strong>integrate</strong> across systems. You can move the entire state of your data from one environment to another by copying a single file.</li> </ul> <h2 id="why-sqlite">Why SQLite?</h2> <ol> <li><strong>Local-First Processing</strong>: SQLite’s small footprint and self-contained nature make it an ideal choice for <strong>local-first</strong> and <strong>edge-based</strong> data operations. In surveilr, we process data locally before sending it to centralized locations, reducing latency and ensuring data security by minimizing unnecessary transfers.</li> <li><strong>SQL-Based Flexibility</strong>: SQLite is fully SQL-compliant, which means you can perform standard data operations like aggregations, queries, and joins on the RSSD. This empowers technical teams to run complex data processes with ease, extract meaningful insights, and ensure data consistency.</li> </ol> <p>By using SQLite for the RSSD, surveilr ensures that stateful operations are <strong>fast</strong>, <strong>reliable</strong>, and <strong>scalable</strong> without the need for heavy, server-based databases. It’s an ideal solution for organizations looking for flexibility and performance in a portable, easy-to-manage format.</p> <h2 id="why-rssd-makes-data-integration-easier-for-those-without-it-departments">Why RSSD makes Data Integration easier for those without IT departments</h2> <h3 id="no-server-setup-required">No Server Setup Required</h3> <p>One of the biggest advantages of using <strong>SQLite</strong> for the RSSD is that there’s no need for a dedicated database server. Everything happens locally within a single file. This simplifies setup, reduces costs, and minimizes dependencies on external infrastructure, which is especially beneficial for smaller organizations that may not have large IT departments.</p> <h3 id="fast-and-lightweight">Fast and Lightweight</h3> <p>Because the RSSD is built on <strong>SQLite</strong>, it’s designed to be <strong>fast and lightweight</strong>. This is critical for local-first operations, where data needs to be processed efficiently on edge devices or local machines before being synchronized with a central system. Despite being lightweight, the RSSD can handle a high volume of data with <strong>excellent performance</strong>.</p> <h3 id="sql-for-all-data-operations">SQL for All Data Operations</h3> <p>By standardizing all data operations with <strong>SQL</strong>, the RSSD makes it easy for non-technical users who are familiar with SQL (or even just comfortable with Excel formulas) to work with the data. SQL is a widely-known language that allows users to run <strong>queries</strong>, <strong>generate reports</strong>, and <strong>analyze data</strong> without needing to learn a new, proprietary system.</p> <h3 id="reliability-and-durability">Reliability and Durability</h3> <p>The RSSD ensures data consistency through its <strong>ACID-compliant</strong> transactions, meaning you can trust that your data is safe, even during system failures. Every change made to the RSSD is guaranteed to be completed fully or not at all, so you never end up with incomplete or corrupted data.</p> <h3 id="portable-and-easy-to-backup">Portable and Easy to Backup</h3> <p>Because the entire database is stored as a single file, <strong>backing up</strong> and <strong>restoring</strong> data is as simple as copying the RSSD file. This simplicity makes the RSSD an attractive solution for organizations that want a reliable, easy-to-manage database solution without the overhead of more complex systems.</p> <p>Whether you’re a technical professional or a non-technical user, the <strong>Resource Surveillance State Database (RSSD)</strong> offers an intuitive and efficient way to manage your data. By leveraging <strong>SQLite</strong> and simplifying operations through <strong>SQL queries</strong>, the RSSD ensures that data is stored, tracked, and accessible—without the complexity of managing a traditional server-based database.</p> <p>For non-technical users, it’s as easy to understand as working with an Excel workbook. For technical users, the flexibility and power of SQL make it a robust solution for handling complex data operations. The RSSD delivers the performance, reliability, and simplicity that modern organizations need to thrive in today’s data-centric landscape.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Stateful </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Stateless </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> RSSD </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/rssd-excel-portability-sql-power/&title=RSSDs: Portability of Excel, Power of SQL"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=RSSDs: Portability of Excel, Power of SQLhttps://www.surveilr.com/blog/rssd-excel-portability-sql-power/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/rssd-excel-portability-sql-power/&title=RSSDs: Portability of Excel, Power of SQL"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 93122 | 2025-04-07 05:49:50.780994862 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTZ0KD6CSCY5R1MG3S7 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/evidence-based-decision-making-pattern/index.html | be17b4686a5e0dbcda1fc6a23b533a45ca0b7344 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/evidence-based-decision-making-pattern/"},"headline":"Unified Evidence-Based Decision Making Platform for Business Leaders","description":"Surveilr simplifies evidence-based decisions by organizing data into a secure, queryable format, helping executives and analysts make informed choices.","image":"https://www.surveilr.com/_astro/evidence-based-decision-making-pattern.TKnVy63Z_1fl4Ng.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-02-10T00:00:00.000Z","dateModified":"2024-02-10T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Unified Evidence-Based Decision Making Platform for Business Leaders","url":"https://www.surveilr.com/blog/evidence-based-decision-making-pattern/","description":"Surveilr simplifies evidence-based decisions by organizing data into a secure, queryable format, helping executives and analysts make informed choices.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Surveilr simplifies evidence-based decisions by organizing data into a secure, queryable format, helping executives and analysts make informed choices." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="index.html"><link rel="alternate" hreflang="en" href="index.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/evidence-based-decision-making-pattern/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/evidence-based-decision-making-pattern/"><meta property="og:type" content="website"><meta property="og:title" content="Unified Evidence-Based Decision Making Platform for Business Leaders"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Surveilr simplifies evidence-based decisions by organizing data into a secure, queryable format, helping executives and analysts make informed choices."><meta property="og:image" content="https://www.surveilr.com/_astro/evidence-based-decision-making-pattern.TKnVy63Z_1fl4Ng.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/evidence-based-decision-making-pattern/"><meta name="twitter:title" content="Unified Evidence-Based Decision Making Platform for Business Leaders"><meta name="twitter:description" content="Surveilr simplifies evidence-based decisions by organizing data into a secure, queryable format, helping executives and analysts make informed choices."><meta name="twitter:image" content="https://www.surveilr.com/_astro/evidence-based-decision-making-pattern.TKnVy63Z_1fl4Ng.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../../sitemap-index.xml"><!-- Links for favicons --><link href="../../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Unified Evidence-Based Decision Making Platform for Business Leaders</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../../surveilr.com/index.html" aria-label="Brand"> <img src="../../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="index.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="7b9039e8-08ef-4fb0-8d5d-2b19aa5894da" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="7b9039e8-08ef-4fb0-8d5d-2b19aa5894da"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="index.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Evidence Based Decision Making Pattern </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/evidence-based-decision-making-pattern/","name":"Evidence Based Decision Making Pattern"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../../_astro/shahid-shah.B2DFcsvR_ZITVg0.avif" alt="Avatar Description" draggable="false" width="2818" height="2746" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Shahid N. Shah </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Feb 10, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 5 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> Evidence-Based Decision Making </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p><strong>Evidence-based decision making</strong> is the process of using data and factual evidence to guide important business decisions, ensuring that choices are grounded in reality rather than intuition or incomplete information. While this approach is critical for success, executives often struggle with gathering enough reliable evidence to make sound decisions. According to <strong>Harvard Business Review</strong>, many executives lack the data they need for decision making, which is often scattered across systems, incomplete, or difficult to access [<a href="https://hbr.org/2020/01/how-executives-can-make-better-decisions">HBR, 2020</a>].</p> <p>The challenges of evidence-based decision making are exacerbated by the lack of a unified approach to collecting <strong>human-generated</strong> and <strong>machine-generated</strong> evidence. Most businesses today rely on a patchwork of systems that store data in different formats, with no single platform capable of pulling everything together into a cohesive, queryable format. This is where <strong><code dir="auto">surveilr</code></strong> stands out.</p> <p>Unlike other tools that handle data exchanges but leave the data unorganized, <code dir="auto">surveilr</code> not only gathers data from multiple sources but also <strong>organizes it into a unified format</strong> that is instantly queryable. This means that the evidence collected—whether it’s from emails, databases, SaaS tools, log files, or industry-specific formats like HL7 or FHIR—can be queried and analyzed with ease using <strong>SQL-friendly tools</strong>. For business analysts and executives, this makes it much easier to extract insights, run reports, and make informed decisions based on the evidence at hand.</p> <p>Moreover, <code dir="auto">surveilr</code> can act as a complete <strong>evidence warehouse</strong>. It securely aggregates data behind firewalls, cleans and anonymizes it where necessary, and allows for the <strong>local storage of evidence</strong> on devices as small as laptops. At the same time, it can scale to support cloud-based evidence repositories, ensuring secure, queryable access to data across the organization.</p> <p>Other evidence-gathering tools on the market often fail to deliver this level of organization. They may facilitate the transfer of data between systems but do not prepare the data in a structured, <strong>uniformly queryable format</strong>. <strong><code dir="auto">surveilr</code></strong>, on the other hand, is designed specifically to handle this challenge, ensuring that evidence-based decision making becomes a smoother, more efficient process.</p> <p>In today’s fast-paced business environment, where executives need access to trustworthy data to make informed decisions, <strong><code dir="auto">surveilr</code></strong> delivers the unified, secure, and queryable platform that makes evidence-based decision making possible.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Pattern </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/evidence-based-decision-making-pattern/&title=Evidence-Based Decision Making"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=Evidence-Based Decision Makinghttps://www.surveilr.com/blog/evidence-based-decision-making-pattern/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/evidence-based-decision-making-pattern/&title=Evidence-Based Decision Making"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-core-vs-patterns.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> The surveilr Ecosystem: Core and Patterns </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 6, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../content-assembler/index.html" data-astro-prefetch> <div> <img src="../../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="../surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="index.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 85818 | 2025-04-07 05:49:49.324005676 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTZRZESJCECAF8M9FDD | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog/surveilr-core-vs-patterns.html | 23bec256d6d676f214db8ba07a74ef817b205958 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">[{"@context":"https://schema.org","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.surveilr.com/blog/surveilr-core-vs-patterns/"},"headline":"Surveilr Ecosystem delivers flexible compliance and security solutions","description":"Discover how Surveilr Core and Patterns enable adaptable, evidence-based workflows for compliance, security, and quality management across industries.","image":"https://www.surveilr.com/_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z2oTos5.webp","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-with-tagline.png"}},"datePublished":"2024-02-06T00:00:00.000Z","dateModified":"2024-02-06T00:00:00.000Z"},{"@context":"https://schema.org","@type":"WebPage","name":"Surveilr Ecosystem delivers flexible compliance and security solutions","url":"https://www.surveilr.com/blog/surveilr-core-vs-patterns/","description":"Discover how Surveilr Core and Patterns enable adaptable, evidence-based workflows for compliance, security, and quality management across industries.","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}]</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Discover how Surveilr Core and Patterns enable adaptable, evidence-based workflows for compliance, security, and quality management across industries." name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="surveilr-core-vs-patterns.html"><link rel="alternate" hreflang="en" href="surveilr-core-vs-patterns.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/surveilr-core-vs-patterns/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/surveilr-core-vs-patterns/"><meta property="og:type" content="website"><meta property="og:title" content="Surveilr Ecosystem delivers flexible compliance and security solutions"><meta property="og:site_name" content="surveilr"><meta property="og:description" content="Discover how Surveilr Core and Patterns enable adaptable, evidence-based workflows for compliance, security, and quality management across industries."><meta property="og:image" content="https://www.surveilr.com/_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z2oTos5.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/blog/surveilr-core-vs-patterns/"><meta name="twitter:title" content="Surveilr Ecosystem delivers flexible compliance and security solutions"><meta name="twitter:description" content="Discover how Surveilr Core and Patterns enable adaptable, evidence-based workflows for compliance, security, and quality management across industries."><meta name="twitter:image" content="https://www.surveilr.com/_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z2oTos5.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="../manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="../sitemap-index.xml"><!-- Links for favicons --><link href="../favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="../_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="../_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="../_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Surveilr Ecosystem delivers flexible compliance and security solutions</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="../_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="../_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} :root{--transition-cubic: cubic-bezier(.165, .84, .44, 1)}html{scroll-behavior:smooth}article h2,article h3,article h4,article h5,article h6{font-weight:700;margin-top:2.5rem;scroll-margin-top:3rem}h2{font-size:1.5rem;line-height:2rem}h3{font-size:1.25rem;line-height:1.75rem}h4{font-size:1.125rem;line-height:1.75rem}p{margin-top:1.5rem}ul{list-style:disc;padding-left:20px;margin:1rem 0}li{display:list-item;text-align:-webkit-match-parent;unicode-bidi:isolate}a{color:#b73d00}a:hover{color:#ae8a5e} </style><script type="module" src="../_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../../surveilr.com/index.html" aria-label="Brand"> <img src="../_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="../docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="../pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="../services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="../blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="../insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="surveilr-core-vs-patterns.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="../_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="8f316d96-0b81-49d3-b4f5-5441cfdc3a30" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="8f316d96-0b81-49d3-b4f5-5441cfdc3a30"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb has-ellipsis"> <button type="button" aria-label="Show more breadcrumbs" class="c-breadcrumbs__truncated-button"> … </button> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li><li class="c-breadcrumbs__crumb"> <a href="../blog.html" class="c-breadcrumbs__link" aria-current="false"> Blog </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="surveilr-core-vs-patterns.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Surveilr Core Vs Patterns </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/blog/","name":"Blog"}},{"@type":"ListItem","position":3,"item":{"@id":"/blog/surveilr-core-vs-patterns/","name":"Surveilr Core Vs Patterns"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-3xl px-4 pb-12 pt-6 sm:px-6 lg:px-8 lg:pt-10"> <div class="max-w-2xl"> <div class="mb-6 flex items-center justify-between"> <div class="flex w-full gap-x-5 sm:items-center sm:gap-x-3"> <div class="flex-shrink-0"> <img src="../_astro/shahid-shah.B2DFcsvR_ZITVg0.avif" alt="Shahid Shah" draggable="false" width="2818" height="2746" loading="lazy" decoding="async" class="size-10 rounded-full sm:h-14 sm:w-14"> </div> <div class="grow"> <div class="flex items-center justify-between gap-x-2"> <div> <!--Post metadata and author info--> <span class="font-bold text-neutral-700 dark:text-neutral-300"> Shahid N. Shah </span> <ul class="text-xs text-neutral-500"> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> Feb 6, 2024 </li> <li class="relative inline-block pe-6 before:absolute before:end-2 before:top-1/2 before:size-1 before:-translate-y-1/2 before:rounded-full before:bg-neutral-300 last:pe-0 last-of-type:before:hidden dark:text-neutral-400 dark:before:bg-neutral-600"> 4 min read </li> </ul> </div> </div> </div> </div> </div> <!--Blog post title--> <h1 class="mb-3 text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-3xl"> The surveilr Ecosystem: Core and Patterns </h1> <!--Blog post contents--> <div class="mb-5 space-y-5 md:mb-8 md:space-y-8"> <img src="../_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" width="1024" height="491" loading="lazy" decoding="async" class="w-full rounded-xl object-cover"> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>At the heart of <strong><code dir="auto">surveilr</code></strong> is the flexibility to adapt to a wide range of industries, disciplines, and use cases. This adaptability is enabled through a combination of the <strong><code dir="auto">surveilr</code> Core</strong> engine and a modular approach to <strong>Patterns</strong>.</p> <h2 id="surveilr-core"><code dir="auto">surveilr</code> Core</h2> <p><code dir="auto">surveilr</code> Core is the core engine, a single binary that handles the heavy lifting of collecting, aggregating, and processing evidence data. While incredibly powerful, <code dir="auto">surveilr</code> Core itself is <strong>agnostic to specific use cases</strong> and does not have built-in awareness of business needs. It’s a flexible tool designed to work with many different data sources and workflows.</p> <h2 id="surveilr-patterns"><code dir="auto">surveilr</code> Patterns</h2> <p>This flexibility comes to life through <strong><code dir="auto">surveilr</code> Patterns</strong>, which are <strong>web-based libraries</strong> of <strong>SQL Packages</strong> that can be mixed and matched to extend the functionality of <code dir="auto">surveilr</code> Core. These Patterns fall into several categories:</p> <ul> <li> <p><strong>Universal Patterns</strong>: Designed to apply across all industries, such as general compliance tracking, security monitoring, or operational auditing. These are foundational packages that can be useful in any organizational context.</p> </li> <li> <p><strong>Industry Patterns</strong>: Tailored to the needs of specific sectors, such as <strong>healthcare</strong>, which may require managing <strong>EHR data</strong> for HIPAA compliance, or <strong>finance</strong>, which might need specialized handling of <strong>ERP data</strong> to meet SOX standards. These packages provide industry-specific workflows and file formats.</p> </li> <li> <p><strong>Discipline Patterns</strong>: These focus on the needs of specific professional roles or functions, such as <strong>software engineers</strong>, <strong>QA teams</strong>, <strong>regulatory compliance officers</strong>, and <strong>cybersecurity professionals</strong>. For example, a Discipline Pattern for <strong>cybersecurity</strong> professionals might automate threat detection, security log aggregation, and incident reporting, while a Discipline Pattern for <strong>QA</strong> might focus on quality tracking and product lifecycle management.</p> </li> </ul> <h2 id="service-patterns">Service Patterns</h2> <p>In addition to Universal, Industry, and Discipline Patterns, <code dir="auto">surveilr</code> also offers <strong>Service Patterns</strong>, which provide a <strong>self-contained, highly opinionated application or service</strong> for specific use cases. A <strong>Service Pattern</strong> is a culmination of <strong>Universal</strong>, <strong>Industry</strong>, and <strong>Discipline</strong> Patterns, blended together to form a complete solution that can operate as a standalone service.</p> <p>For example, a <strong>Healthcare Security Compliance Service Pattern</strong> might combine <strong>Universal Patterns</strong> for security monitoring, an <strong>Industry Pattern</strong> for handling <strong>EHR data</strong>, and a <strong>Discipline Pattern</strong> designed for <strong>regulatory compliance</strong> officers. The result is a full-service application that can be deployed with minimal configuration, offering a focused solution that meets the needs of healthcare organizations looking to secure patient data and comply with regulatory standards.</p> <h2 id="composability-and-flexibility">Composability and Flexibility</h2> <p><code dir="auto">surveilr</code> Patterns are delivered as <strong>composable SQL Packages</strong>, allowing organizations to customize their use of <code dir="auto">surveilr</code> by selecting the appropriate Patterns for their needs. For example, a financial services company could combine a <strong>Universal Pattern</strong> for compliance reporting with an <strong>Industry Pattern</strong> specific to finance, and add a <strong>Discipline Pattern</strong> for software engineers to track system performance.</p> <h2 id="benefits-of-the-surveilr-core--patterns-strategy">Benefits of the <code dir="auto">surveilr</code> Core + Patterns Strategy</h2> <ul> <li> <p><strong>Flexibility</strong>: With the ability to choose from Universal, Industry, Discipline, and Service Patterns, organizations can customize <code dir="auto">surveilr</code> to meet their exact requirements without modifying the Core engine.</p> </li> <li> <p><strong>Efficiency</strong>: Service Patterns provide a ready-to-use, opinionated solution that is designed to be deployed quickly for specific applications, reducing the need for manual setup or configuration.</p> </li> <li> <p><strong>Scalability</strong>: As business needs evolve, new Patterns can be added or existing ones modified without disrupting existing workflows, making <code dir="auto">surveilr</code> scalable and adaptable over time.</p> </li> <li> <p><strong>Comprehensive Use Case Support</strong>: Whether an organization needs basic compliance tracking or a full-service application, <code dir="auto">surveilr</code> Patterns offer the flexibility to create complex solutions from individual components.</p> </li> </ul> <hr> <p>With the combination of <strong><code dir="auto">surveilr</code> Core</strong> and the modular <strong>Patterns</strong> approach—including <strong>Universal</strong>, <strong>Industry</strong>, <strong>Discipline</strong>, and <strong>Service Patterns</strong>—<code dir="auto">surveilr</code> enables organizations to confidently prove <strong>security</strong>, <strong>quality</strong>, and <strong>compliance</strong> with <strong>auditable</strong>, <strong>queryable</strong>, and <strong>machine-attestable evidence</strong> while scaling and adapting to specific needs.</p> </article> </div> <div class="mx-auto grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <!--Blog post tags--> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"> <span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Pattern </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Ecosystem </span><span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300"> Core </span> </div> <!--Bookmark and Share buttons--> <div class="flex items-center justify-end gap-x-1.5"> <button type="button" class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700" data-bookmark-button="bookmark-button"> <svg class="h-6 w-6 fill-none transition duration-300" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"></path></svg> </button> <script type="module">class o{constructor(t){this.dataAttrValue=t,this.bookmarkButton=document.querySelector(`[data-bookmark-button="${t}"]`)}static BOOKMARKS_KEY="bookmarks";bookmarkButton;getStoredBookmarks(){const t=localStorage.getItem(o.BOOKMARKS_KEY);return t?JSON.parse(t):[]}init(){this.bookmarkButton&&this.isStored()&&this.markAsStored(),this.bookmarkButton?.addEventListener("click",()=>this.toggleBookmark())}isStored(){return this.getStoredBookmarks().includes(window.location.pathname)}markAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.add("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-red-500 dark:fill-red-500");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-red-500 dark:text-red-500")}}unmarkAsStored(){if(this.bookmarkButton){this.bookmarkButton.classList.remove("bookmarked");let t=this.bookmarkButton.querySelector("svg");t&&t.setAttribute("class","h-6 w-6 fill-none");let e=t?.querySelector("path");e&&e.setAttribute("class","fill-current text-neutral-500 group-hover:text-red-400 dark:text-neutral-500 group-hover:dark:text-red-400")}}toggleBookmark(){let t=this.getStoredBookmarks();const e=t.indexOf(window.location.pathname);e!==-1?(t.splice(e,1),this.unmarkAsStored()):(t.push(window.location.pathname),this.markAsStored()),localStorage.setItem(o.BOOKMARKS_KEY,JSON.stringify(t))}}new o("bookmark-button").init();</script> <div class="mx-3 block h-4 border-e border-neutral-400 dark:border-neutral-500"></div> <div class="inline-flex"> <div class="hs-dropdown relative inline-flex [--auto-close:inside] [--placement:top-left]"> <button id="hs-dropup" type="button" class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"> <svg class="h-4 w-4 group-hover:text-neutral-700" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" class></path></svg> Share </button> <div class="hs-dropdown-menu duration z-10 hidden w-72 divide-y divide-neutral-200 rounded-lg bg-neutral-50 p-2 opacity-0 shadow-md transition-[opacity,margin] hs-dropdown-open:opacity-100 dark:divide-neutral-700 dark:border dark:border-neutral-700 dark:bg-neutral-800" aria-labelledby="hs-dropup"> <div class="py-2 first:pt-0 last:pb-0"> <a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.facebook.com/share.php?u=https://www.surveilr.com/blog/surveilr-core-vs-patterns/&title=The surveilr Ecosystem: Core and Patterns"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z" class></path></svg> Share on Facebook </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://twitter.com/home/?status=The surveilr Ecosystem: Core and Patternshttps://www.surveilr.com/blog/surveilr-core-vs-patterns/"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> Share on X </a><a class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 " href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.surveilr.com/blog/surveilr-core-vs-patterns/&title=The surveilr Ecosystem: Core and Patterns"> <svg class="size-4 flex-shrink-0 fill-current" viewBox="0 0 24 24" stroke="currentColor"><title></title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" class></path></svg> Share on LinkedIn </a> </div> <div class="py-2 first:pt-0 last:pb-0"> <button type="button" class="js-clipboard hover:text-dark focus-visible:ring-secondary group inline-flex w-full items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700" data-clipboard-success-text="Copied"> <svg class="js-clipboard-default h-4 w-4 transition group-hover:rotate-6" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> </svg> <svg class="js-clipboard-success hidden h-4 w-4 text-neutral-700 dark:text-neutral-300" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> <span class="js-clipboard-success-text">Copy link</span> </button> </div> </div> </div> <!--Import the necessary Dropdown and Clipboard plugins--> <!--https://preline.co/plugins/html/dropdown.html--> <!-- https://clipboardjs.com/ --> <script type="module" src="../_astro/SocialShare.astro_astro_type_script_index_0_lang.D-sz2NX-.js"></script> <script type="module" src="../_astro/SocialShare.astro_astro_type_script_index_1_lang.D_LzEBOw.js"></script> </div> </div> </div> </div> <div class="mt-12 flex items-center justify-center gap-x-2"> <h3 class="text-neutral-700 dark:text-neutral-300">Was this post helpful?</h3> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:border-yellow-500 hover:bg-yellow-500 hover:shadow-2xl hover:shadow-yellow-500 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-yellow-500 dark:hover:text-neutral-700 dark:hover:border-yellow-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:-translate-y-1 group-focus-visible:-translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z"></path></svg> Yes </button> <button type="button" class="group inline-flex items-center gap-x-2 rounded-lg border border-neutral-400 px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-400/30 dark:border-neutral-500 dark:text-neutral-300 dark:hover:bg-neutral-700/60 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-neutral-600"> <svg class="size-4 flex-shrink-0 transition duration-300 group-hover:translate-y-1 group-focus-visible:translate-y-1" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z"></path></svg> No </button> </div> </section> <section class="mx-auto max-w-3xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mb-10 max-w-2xl"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Related articles </h2> </div> <div class="grid grid-cols-2 gap-6"> <a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="direct-messaging-service-pattern/index.html" data-astro-prefetch> <div> <img src="../_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" width="778" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <div> <img src="../_astro/evidence-based-decision-making-pattern.TKnVy63Z_Z15z0qF.avif" alt="Man in black sweatpants using DEWALT circular saw and cutting a wood plank" draggable="false" width="2400" height="1600" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Evidence-Based Decision Making </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="power-of-sql-and-sql-views/index.html" data-astro-prefetch> <div> <img src="../_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1080" height="650" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 7, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="quality-management-pattern/index.html" data-astro-prefetch> <div> <img src="../_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" width="2131" height="1137" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Quality Management for Safety-Critical Industries </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 18, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="research-study-explorer-pattern/index.html" data-astro-prefetch> <div> <img src="../_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> How `surveilr` Transforms Diabetes Research Study Data Management </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Dec 5, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <div> <img src="../_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" width="677" height="192" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> RSSDs: Portability of Excel, Power of SQL </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="surveilr-integration-engine/index.html" data-astro-prefetch> <div> <img src="../_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" width="1080" height="500" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Sep 27, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="vendor-assessments/index.html" data-astro-prefetch> <div> <img src="../_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" width="5696" height="3856" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> May 22, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="why-stateful-integration/index.html" data-astro-prefetch> <div> <img src="../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Why Stateful Integration? </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Feb 10, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="content-assembler/index.html" data-astro-prefetch> <div> <img src="../_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 4, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="compliance-explorer/index.html" data-astro-prefetch> <div> <img src="../_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" width="1024" height="683" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Nov 15, 2024 </p> </div></a><a class="group block rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="sql-based-etl-elt/index.html" data-astro-prefetch> <div> <img src="../_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" width="1524" height="605" loading="lazy" decoding="async" class="aspect-video rounded-xl"> <!-- The title of the blog post --> <h3 class="mt-2 text-balance text-lg font-medium text-neutral-800 group-hover:text-orange-400 dark:text-neutral-300 dark:group-hover:text-neutral-50"> Modern Lightweight ETL with SQLite </h3> <!-- The formatted publication date of the blog post --> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Oct 8, 2024 </p> </div></a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="../_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="../services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="../blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="surveilr-core-vs-patterns.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 89210 | 2025-04-07 05:49:50.053000265 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTZ1ZKXJW9TWHA7DDCR | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/robots.txt | d2c7418ca7eaa027937e9e5aa5e9abd6e672c629 | User-agent: * Sitemap: https://www.surveilr.com/sitemap-index.xml | txt | 66 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJTZ91EJAHJY9MVA41W5 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/manifest.json | 8e0c176db66d85c7d28d448ecd0b07f075e4d5f4 | {"short_name":"survelir","name":"survelir","icons":[{"src":"/_astro/icon.yxznLHQU_2s2KTE.png","sizes":"192x192","type":"image/png","purpose":"any"},{"src":"/_astro/icon.yxznLHQU_Nqq6u.png","sizes":"512x512","type":"image/png","purpose":"any"},{"src":"/_astro/icon-maskable.C1A7b-dw_2sDrMl.png","sizes":"192x192","type":"image/png","purpose":"maskable"},{"src":"/_astro/icon-maskable.C1A7b-dw_1tD5bE.png","sizes":"512x512","type":"image/png","purpose":"maskable"}],"display":"minimal-ui","id":"/","start_url":"/","theme_color":"#FFEDD5","background_color":"#262626"} | json | 565 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJV09B8P7NSCP03DCA6C | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/insights.html | 4f791bd410d32f143426e4252a0bd667bf2fdfb7 | <!DOCTYPE html><!-- This is the main structure for the page. We set the language of the page to English and add classes for scrollbar and scroll behavior. --><html lang="en" class="scrollbar-hide lenis lenis-smooth scroll-pt-16 astro-ouamjn2i"> <head><!-- Adding metadata to the HTML document --><!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data --><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Insights | surveilr","url":"https://www.surveilr.com/insights/","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","publisher":{"@type":"Organization","name":"Surveilr","logo":{"@type":"ImageObject","url":"https://www.surveilr.com/assets/brand/surveilr-logo-without-tagline.png"}}}</script><!-- Define the character set, description, author, and viewport settings --><meta charset="utf-8"><meta content="Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence" name="description"><meta name="web_author" content="Shahid N. Shah"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link rel="canonical" href="insights.html"><link rel="alternate" hreflang="en" href="insights.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/insights/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/insights/"><meta property="og:type" content="website"><meta property="og:title" content="Insights | surveilr"><meta property="og:site_name" content="surveilr"><meta property="og:description"><meta property="og:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><meta content="1200" property="og:image:width"><meta content="600" property="og:image:height"><meta content="image/png" property="og:image:type"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta property="twitter:domain" content="https://www.surveilr.com/"><meta property="twitter:url" content="https://www.surveilr.com/insights/"><meta name="twitter:title" content="Insights | surveilr"><meta name="twitter:description"><meta name="twitter:image" content="https://www.surveilr.com/_astro/social.C618f-KT_Z1ba4v3.webp"><!-- Links to the webmanifest and sitemap --><link rel="manifest" href="manifest.json"><!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --><link rel="sitemap" href="sitemap-index.xml"><!-- Links for favicons --><link href="favicon.ico" rel="icon" sizes="any" type="image/x-icon"><link href="_astro/icon.Bc6rUfkK_1shs5g.svg" rel="icon" type="image/svg+xml" sizes="any"><meta name="mobile-web-app-capable" content="yes"><link href="_astro/icon.yxznLHQU_Z2n55ga.png" rel="apple-touch-icon"><link href="_astro/icon.yxznLHQU_Z2n55ga.png" rel="shortcut icon"><!-- Set theme color --><meta name="theme-color" content="#facc15"><!-- Google Tag Manager --><script type="module">(function(e,n,r,t,m){e[t]=e[t]||[],e[t].push({"gtm.start":new Date().getTime(),event:"gtm.js"});var g=n.getElementsByTagName(r)[0],a=n.createElement(r),s="";a.async=!0,a.src="https://www.googletagmanager.com/gtm.js?id="+m+s,g.parentNode.insertBefore(a,g)})(window,document,"script","dataLayer","GTM-53HB45F9");</script><!-- End Google Tag Manager --><!-- Define the title of the page --><title>Insights | surveilr</title><script> // Script to handle dark mode. It will check if the theme is stored in localStorage or if dark theme is preferred by system settings if ( localStorage.getItem("hs_theme") === "dark" || (!("hs_theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) ) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } </script><script type="module" src="_astro/MainLayout.astro_astro_type_script_index_0_lang.CJB9pIOu.js"></script><script type="application/ld+json"> [ { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Home", "url": "https://www.surveilr.com/" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Docs", "url": "https://www.surveilr.com/docs" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Patterns", "url": "https://www.surveilr.com/pattern" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Services", "url": "https://www.surveilr.com/services" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Blog", "url": "https://www.surveilr.com/blog" }, { "@context": "https://schema.org/", "@type": "SiteNavigationElement", "@id": "https://www.surveilr.com/", "name": "Contact", "url": "https://www.surveilr.com/contact" } ] </script><style>html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-scrolling iframe{pointer-events:none} </style> <link rel="stylesheet" href="_astro/index.x-iyR4LI.css"> <style>.c-breadcrumbs{--color-link-breadcrumbs: #b9b9b9;--size-font-breadcrumbs: 15px;--spacing-vertical-separator-breadcrumbs: 6px}.c-breadcrumbs .has-ellipsis{display:var(--display-ellipsis-breadcrumbs, none)}.c-breadcrumbs.is-truncated .has-ellipsis{--display-ellipsis-breadcrumbs: flex}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb{visibility:var(--visibility-truncated-breadcrumbs, hidden);position:var(--position-truncated-breadcrumbs, absolute)}.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:first-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb:last-of-type,.c-breadcrumbs.is-truncated .c-breadcrumbs__crumb.has-ellipsis{--visibility-truncated-breadcrumbs: visible;--position-truncated-breadcrumbs: relative}.c-breadcrumbs__truncated-button{background-color:transparent;border:none;padding:0;margin:0;cursor:pointer;color:var(--color-truncated-button, var(--color-link-breadcrumbs))}.c-breadcrumbs__crumbs{list-style-type:none;margin:0;padding:0;display:flex;flex-wrap:wrap}.c-breadcrumbs__crumbs:where(.has-no-separators){row-gap:var(--spacing-vertical-separator-breadcrumbs);-moz-column-gap:1rem;column-gap:1rem}.c-breadcrumbs__crumb{display:flex;align-items:center}.c-breadcrumbs__crumb:has(.c-breadcrumbs__separator) .c-breadcrumbs__separator{display:flex;align-items:center;justify-content:center;margin-inline:var(--spacing-vertical-separator-breadcrumbs);color:#d3d3d3}.c-breadcrumbs__crumb:has(svg,image) :where(svg,image){max-width:var(--size-font-breadcrumbs);max-height:var(--size-font-breadcrumbs)}.c-breadcrumbs__link,.c-breadcrumbs__truncated-button{font-size:var(--size-font-breadcrumbs);text-decoration:none;color:var(--color-link-breadcrumbs);line-height:1;transition:color .2s ease-in-out}@media (hover: hover){.c-breadcrumbs__link:hover,.c-breadcrumbs__truncated-button:hover{--color-link-breadcrumbs: #214EA2}}.c-breadcrumbs__link{line-height:normal!important}.c-breadcrumbs__link[aria-disabled=true]{pointer-events:none;cursor:default;color:#b9b9b9;text-decoration:none}.scrollbar-hide:where(.astro-ouamjn2i)::-webkit-scrollbar{display:none}.scrollbar-hide:where(.astro-ouamjn2i){-ms-overflow-style:none;scrollbar-width:none} </style><script type="module" src="_astro/page.CJRj5HRh.js"></script></head> <body class="bg-neutral-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-neutral-800 astro-ouamjn2i"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-53HB45F9" height="0" width="0" style="display:none;visibility:hidden" class="astro-ouamjn2i"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Setting up the main structure of the page. The Navbar is placed at the top, with a slot for the main content and FooterSection at the bottom. --> <div class="mx-auto max-w-screen-2xl px-4 sm:px-6 lg:px-8 astro-ouamjn2i"> <!-- Main header component --><header class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"> <!-- Navigation container --> <nav class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto" aria-label="Global"> <div class="flex items-center justify-between"> <!-- Brand logo --> <a class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="../surveilr.com/index.html" aria-label="Brand"> <img src="_astro/surveilr-logo-without-tagline.DVJj0veE_Z19EPPG.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async" class="h-auto w-24"> </a> <!-- Collapse toggle for smaller screens --> <div class="ml-auto mr-5 md:hidden"> <button type="button" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none" data-hs-collapse="#navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation" aria-label="Toggle navigation"> <svg class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" x2="21" y1="6" y2="6"></line> <line x1="3" x2="21" y1="12" y2="12"></line> <line x1="3" x2="21" y1="18" y2="18"></line> </svg> <svg class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <!-- ThemeIcon component specifically for smaller screens --> <span class="inline-block md:hidden"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> <!-- Contains navigation links --> <div id="navbar-collapse-with-animation" class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"> <!-- Navigation links container --> <div class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"> <!-- Navigation links and Authentication component --> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="home" href="../surveilr.com/index.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Home </a> <script type="module">document.addEventListener("DOMContentLoaded",function(){let t=window.location.pathname;t.split("/");let a;t==="/"?a="home":a=t.replace("/","");let e=document.getElementById(a);e&&(e.classList.remove("text-neutral-600","dark:text-neutral-400","hover:text-neutral-500","dark:hover:text-neutral-500"),e.classList.add("text-orange-400","dark:text-orange-300"),e.setAttribute("aria-current","page"))});</script><!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="docs" href="docs.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Docs </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="pattern" href="pattern.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Patterns </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="services" href="services.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Services </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="blog" href="blog.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Blog </a> <!-- Re-usable link component for navigation bar. Highlights the active link by comparing the current URL with the href of each link. We assign an ID matching the URL for easy reference in our script. If URL is '/' (home page), assign ID as 'home' --><a id="insights" href="insights.html" data-astro-prefetch class="rounded-lg text-base font-medium text-neutral-600 outline-none ring-zinc-500 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-500 dark:focus:outline-none md:py-3 md:text-sm 2xl:text-base"> Insights </a> <!-- Login Button --><!-- <LoginBtn /> --><!-- Login Modal --><div id="hs-toggle-between-modals-login-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign in </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Don't have an account yet? <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-register-modal"> Sign up here </button> </p> </div> <div class="mt-5"> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign in with Google </button> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- The container for the form --> <form> <!-- A grid layout for the form fields --> <div class="grid gap-y-4"> <!-- The email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="login-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="login-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="login-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- The password input field --> <div> <div class="flex items-center justify-between"> <label for="password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> <button class="rounded-lg text-sm font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1" data-hs-overlay="#hs-toggle-between-modals-recover-modal"> Forgot password? </button> </div> <div class="relative"> <input type="password" id="password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="login-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="login-password-error"> 8+ characters required </p> </div> <!-- The remember-me checkbox --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="remember-me" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="remember-me" class="text-sm text-neutral-800 dark:text-neutral-200">Remember me </label> </div> </div> <!-- The sign-in button --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign in</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Register Modal --> <!-- Root element of the registration modal with the id and styling --><div id="hs-toggle-between-modals-register-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <div class="mt-7 max-h-full overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Sign up </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Already have an account? <!-- Button to toggle login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <!-- The form for user registration --> <div class="mt-5"> <!-- Google signup button --> <button type="button" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm dark:text-neutral-400 font-medium text-neutral-600 shadow-sm transition duration-300 focus-visible:ring outline-none border border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-900 disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200"> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <svg class="h-auto w-4" width="46" height="47" viewBox="0 0 46 47" fill="none" > <path d="M46 24.0287C46 22.09 45.8533 20.68 45.5013 19.2112H23.4694V27.9356H36.4069C36.1429 30.1094 34.7347 33.37 31.5957 35.5731L31.5663 35.8669L38.5191 41.2719L38.9885 41.3306C43.4477 37.2181 46 31.1669 46 24.0287Z" fill="#4285F4"></path> <path d="M23.4694 47C29.8061 47 35.1161 44.9144 39.0179 41.3012L31.625 35.5437C29.6301 36.9244 26.9898 37.8937 23.4987 37.8937C17.2793 37.8937 12.0281 33.7812 10.1505 28.1412L9.88649 28.1706L2.61097 33.7812L2.52296 34.0456C6.36608 41.7125 14.287 47 23.4694 47Z" fill="#34A853"></path> <path d="M10.1212 28.1413C9.62245 26.6725 9.32908 25.1156 9.32908 23.5C9.32908 21.8844 9.62245 20.3275 10.0918 18.8588V18.5356L2.75765 12.8369L2.52296 12.9544C0.909439 16.1269 0 19.7106 0 23.5C0 27.2894 0.909439 30.8731 2.49362 34.0456L10.1212 28.1413Z" fill="#FBBC05"></path> <path d="M23.4694 9.07688C27.8699 9.07688 30.8622 10.9863 32.5344 12.5725L39.1645 6.11C35.0867 2.32063 29.8061 0 23.4694 0C14.287 0 6.36607 5.2875 2.49362 12.9544L10.0918 18.8588C11.9987 13.1894 17.25 9.07688 23.4694 9.07688Z" fill="#EB4335"></path> </svg> Sign up with Google </button> <!-- Dividing line with 'Or' text --> <div class="flex items-center py-3 text-xs uppercase text-neutral-400 before:me-6 before:flex-[1_1_0%] before:border-t before:border-neutral-200 after:ms-6 after:flex-[1_1_0%] after:border-t after:border-neutral-200 dark:text-neutral-500 dark:before:border-neutral-600 dark:after:border-neutral-600"> Or </div> <!-- Registration form --> <form> <div class="grid gap-y-4"> <!-- Email input field --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="register-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="register-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="register-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Password input field --> <div> <div class="flex items-center justify-between"> <label for="create-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Password</label> </div> <div class="relative"> <input type="password" id="create-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="register-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="register-password-error"> 8+ characters required </p> </div> <!-- Password confirmation input field --> <div> <div class="flex items-center justify-between"> <label for="confirm-password" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Confirm Password</label> </div> <div class="relative"> <input type="password" id="confirm-password" name="password" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="confirm-password-error"> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <p class="mt-2 hidden text-xs text-red-600" id="confirm-password-error"> Password does not match the password </p> </div> <!-- Checkbox with a label and a link for accepting the terms and conditions --> <!-- Container for the checkbox and its label --><div class="flex items-center"> <!-- Checkbox input --> <div class="flex"> <input id="terms-agree" name="remember-me" type="checkbox" class="pointer-events-none mt-0.5 shrink-0 rounded border-neutral-200 text-neutral-600 focus:ring-yellow-400 dark:border-neutral-700 dark:bg-neutral-800 dark:checked:border-yellow-400 dark:checked:bg-yellow-400 dark:focus:ring-offset-neutral-800"> </div> <!-- Label for the checkbox --> <div class="ms-3"> <label for="terms-agree" class="text-sm text-neutral-800 dark:text-neutral-200">I accept the <a class="font-medium text-orange-400 decoration-2 hover:underline dark:text-orange-400 dark:focus:outline-none" href="insights.html#">Terms and Conditions</a> </label> </div> </div> <!-- Submit button for the registration form --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Sign up</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Password Recovery Modal --> <!-- Root element of the modal with id and styling --><div id="hs-toggle-between-modals-recover-modal" class="hs-overlay absolute start-0 top-0 z-50 hidden h-full w-full hs-overlay-backdrop-open:bg-neutral-900/90"> <!-- Modal content container --> <div class="m-3 mt-0 opacity-0 transition-all ease-out hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 sm:mx-auto sm:w-full sm:max-w-lg"> <div class="mx-auto w-full max-w-md p-6"> <!-- Actual box for the modal elements --> <div class="mt-7 rounded-xl border border-neutral-200 bg-neutral-100 shadow-sm dark:border-neutral-700 dark:bg-neutral-800"> <div class="p-4 sm:p-7"> <div class="text-center"> <h2 class="block text-2xl font-bold text-neutral-800 dark:text-neutral-200"> Forgot password? </h2> <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400"> Remember your password? <!-- Button that, when clicked, opens the login modal --> <button class="rounded-lg p-1 font-medium text-orange-400 decoration-2 outline-none ring-zinc-500 hover:underline focus-visible:ring dark:text-orange-400 dark:ring-zinc-200 dark:focus:outline-none" data-hs-overlay="#hs-toggle-between-modals-login-modal"> Sign in here </button> </p> </div> <div class="mt-5"> <!-- The form for password recovery --> <form> <div class="grid gap-y-4"> <!-- Email input field imported from EmailInput component --> <!-- Container for the label, input, and validation message --><div> <!-- Label for the email input field --> <label for="recover-email" class="mb-2 block text-sm text-neutral-800 dark:text-neutral-200">Email address</label> <!-- Label for the email input field --> <div class="relative"> <!-- Email input field --> <input type="email" id="recover-email" name="email" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 focus:border-neutral-200 focus:outline-none focus:ring focus:ring-neutral-400 disabled:pointer-events-none disabled:opacity-50 dark:border-neutral-600 dark:bg-neutral-700/30 dark:text-neutral-300 dark:focus:ring-1" required aria-describedby="recover-email"> <!-- Hidden error icon --> <div class="pointer-events-none absolute inset-y-0 end-0 hidden pe-3"> <svg class="h-5 w-5 text-red-500" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path> </svg> </div> </div> <!-- Validation message which is hidden by default --> <p class="mt-2 hidden text-xs text-red-600" id="recover-email-error"> Please include a valid email address so we can get back to you </p> </div> <!-- Reset password button imported from AuthBtn component --> <!-- Styled submit button with dynamic title --><button type="submit" class="inline-flex w-full items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-sm font-bold text-neutral-700 focus-visible:ring outline-none transition duration-300 border border-transparent bg-yellow-400 dark:focus:outline-none hover:bg-yellow-500 2xl:text-base disabled:pointer-events-none disabled:opacity-50 ring-zinc-500 dark:ring-zinc-200">Reset password</button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- <LanguagePicker /> --> <!-- ThemeIcon component specifically for larger screens --> <span class="hidden md:inline-block"> <!-- Dark Theme Toggle Button --><!-- This button is shown when the light theme is active, and when clicked, it switches the theme to dark --><button type="button" aria-label="Dark Theme Toggle" class="hs-dark-mode group flex h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-200 hover:text-orange-400 hs-dark-mode-active:hidden dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="dark"> <!-- The SVG displayed shows an abstract icon that represents the moon (dark theme) --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg> <!-- Light Theme Toggle Button --> <!-- This button is hidden by default and only appears when the dark theme is active, when clicked, it switches to the light theme --> </button> <button type="button" aria-label="Light Theme Toggle" class="hs-dark-mode group hidden h-8 w-8 items-center justify-center rounded-full font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 hs-dark-mode-active:flex dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-orange-300 dark:focus:outline-none" data-hs-theme-click-value="light"> <!-- The SVG displayed shows a standard sun icon that stands for the light theme --> <svg class="h-4 w-4 flex-shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 8a2 2 0 1 0 4 4"></path><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg> </button> </span> </div> </div> </nav> </header> <!-- Theme Appearance script to manage light/dark modes --> <script> const HSThemeAppearance = { init() { const defaultTheme = "default"; let theme = localStorage.getItem("hs_theme") || defaultTheme; if (document.querySelector("html").classList.contains("dark")) return; this.setAppearance(theme); }, _resetStylesOnLoad() { const $resetStyles = document.createElement("style"); $resetStyles.innerText = `*{transition: unset !important;}`; $resetStyles.setAttribute("data-hs-appearance-onload-styles", ""); document.head.appendChild($resetStyles); return $resetStyles; }, setAppearance(theme, saveInStore = true, dispatchEvent = true) { const $resetStylesEl = this._resetStylesOnLoad(); if (saveInStore) { localStorage.setItem("hs_theme", theme); } if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } document.querySelector("html").classList.remove("dark"); document.querySelector("html").classList.remove("default"); document.querySelector("html").classList.remove("auto"); document .querySelector("html") .classList.add(this.getOriginalAppearance()); setTimeout(() => { $resetStylesEl.remove(); }); if (dispatchEvent) { window.dispatchEvent( new CustomEvent("on-hs-appearance-change", { detail: theme }) ); } }, getAppearance() { let theme = this.getOriginalAppearance(); if (theme === "auto") { theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default"; } return theme; }, getOriginalAppearance() { const defaultTheme = "default"; return localStorage.getItem("hs_theme") || defaultTheme; }, }; HSThemeAppearance.init(); window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", () => { if (HSThemeAppearance.getOriginalAppearance() === "auto") { HSThemeAppearance.setAppearance("auto", false); } }); window.addEventListener("load", () => { const $clickableThemes = document.querySelectorAll( "[data-hs-theme-click-value]" ); const $switchableThemes = document.querySelectorAll( "[data-hs-theme-switch]" ); $clickableThemes.forEach(($item) => { $item.addEventListener("click", () => HSThemeAppearance.setAppearance( $item.getAttribute("data-hs-theme-click-value"), true, $item ) ); }); $switchableThemes.forEach(($item) => { $item.addEventListener("change", (e) => { HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default"); }); $item.checked = HSThemeAppearance.getAppearance() === "dark"; }); window.addEventListener("on-hs-appearance-change", (e) => { $switchableThemes.forEach(($item) => { $item.checked = e.detail === "dark"; }); }); }); </script> <!--Import the necessary Collapse and Overlay plugins--> <!--https://preline.co/plugins/html/collapse.html--> <!--https://preline.co/plugins/html/overlay.html--> <script type="module" src="_astro/Navbar.astro_astro_type_script_index_0_lang.z5i368Bh.js"></script> <div class="breadcrumb-container z-30 relative w-full max-w-7xl my-8 md:my-10 ml-[32px] astro-ouamjn2i"> <astro-breadcrumbs data-main-bem-class="c-breadcrumbs" data-id="46d8a524-408b-4fc4-a78e-7e2ea346fed6" data-path-length="1" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="46d8a524-408b-4fc4-a78e-7e2ea346fed6"> <ol class="c-breadcrumbs__crumbs has-separators"> <li class="c-breadcrumbs__crumb"> <a href="../surveilr.com/index.html" class="c-breadcrumbs__link is-index" aria-current="false"> Home </a> <span class="c-breadcrumbs__separator" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="astro-ouamjn2i"> <polyline points="9 18 15 12 9 6" class="astro-ouamjn2i"></polyline> </svg> </span> </li> <li class="c-breadcrumbs__crumb"> <a href="insights.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Insights </a> </li> </ol> </nav> </astro-breadcrumbs> <script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"/insights/","name":"Insights"}}]}</script> <script type="module">class t extends HTMLElement{constructor(){super(),this.isManualToggle=!1,this.breadcrumbs=null,this.mainBemClass=null,this.totalWidth=0,this.resizeObserver=null,this.handleTruncatedButtonClick=()=>{this.breadcrumbs?.classList.remove("is-truncated"),this.isManualToggle=!0},this.mainBemClass=this.dataset.mainBemClass||null;const e=this.dataset.id;!("truncated"in this.dataset)||!e||(this.breadcrumbs=document.getElementById(e),this.initializeCrumbs(),this.setupResizeObserver())}initializeCrumbs(){this.breadcrumbs?.querySelectorAll(`.${this.mainBemClass}__crumb`)?.forEach(s=>{this.totalWidth+=s.offsetWidth})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{e.forEach(s=>{this.checkOverflow(s.target.clientWidth)})}),this.breadcrumbs&&this.resizeObserver.observe(this.breadcrumbs)}connectedCallback(){this.showHiddenCrumbs()}disconnectedCallback(){this.resizeObserver&&this.breadcrumbs&&(this.resizeObserver.unobserve(this.breadcrumbs),this.resizeObserver.disconnect())}toggleTruncated(e){this.breadcrumbs?.classList.toggle("is-truncated",e)}showHiddenCrumbs(){const e=this.breadcrumbs?.querySelector(`.${this.mainBemClass}__truncated-button`);e?.removeEventListener("click",this.handleTruncatedButtonClick),e?.addEventListener("click",this.handleTruncatedButtonClick.bind(this))}checkOverflow(e){const s=this.totalWidth>e&&!this.isManualToggle;this.toggleTruncated(s),s||(this.isManualToggle=!1)}}customElements.get("astro-breadcrumbs")||customElements.define("astro-breadcrumbs",t);</script> </div> <main class="astro-ouamjn2i"> <section class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <div class="mx-auto mb-10 max-w-2xl text-center lg:mb-14"> <h2 class="text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Insights </h2> <p class="mt-1 text-pretty text-neutral-600 dark:text-neutral-400"> Stay up-to-date with the latest trends and developments in the compliance industry with insights from our team of industry experts. </p> </div> <div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3"> <!-- The anchor tag is the root container for the "Insight" card. It links to the insight detail page. --><a class="group rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="insights/why-sqlite-for-rssd/index.html"> <!-- This is the container for the insight's cover image. --> <div class="relative overflow-hidden rounded-xl pt-[50%] sm:pt-[70%]"> <img src="_astro/sqlite-for-rssd.CE6PRJp4_14Fpbr.avif" alt="SQLite versatility" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="absolute start-0 top-0 size-full rounded-xl object-cover transition duration-500 ease-in-out group-hover:scale-105"> </div> <!-- This is the container for the insight's title and description. --> <div class="mt-7"> <!-- The title of the insight --> <h3 class="text-xl font-bold text-neutral-800 group-hover:text-neutral-600 dark:text-neutral-200 dark:group-hover:text-neutral-400"> Why SQLite for RSSD? </h3> <!-- The description of the insight --> <p class="mt-3 text-neutral-600 dark:text-neutral-400"> Discover why SQLite is perfect for RSSD, combining simplicity, scalability, and security for efficient data management in large-scale use cases </p> <!-- The "Read More" hyperlink going to the full insight. With an arrow icon --> <p class="mt-5 inline-flex items-center gap-x-1 font-medium text-orange-400 decoration-2 group-hover:underline dark:text-orange-300"> Read more <svg class="size-4 flex-shrink-0" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </p> </div> </a><!-- The anchor tag is the root container for the "Insight" card. It links to the insight detail page. --><a class="group rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="insights/advanced-polyglot-orchestration/index.html"> <!-- This is the container for the insight's cover image. --> <div class="relative overflow-hidden rounded-xl pt-[50%] sm:pt-[70%]"> <img src="_astro/advanced-polyglot-orchestration.DUq5BBKY_Z1bhFJh.avif" alt="Lightweight ETL" draggable="false" width="800" height="200" loading="lazy" decoding="async" class="absolute start-0 top-0 size-full rounded-xl object-cover transition duration-500 ease-in-out group-hover:scale-105"> </div> <!-- This is the container for the insight's title and description. --> <div class="mt-7"> <!-- The title of the insight --> <h3 class="text-xl font-bold text-neutral-800 group-hover:text-neutral-600 dark:text-neutral-200 dark:group-hover:text-neutral-400"> Orchestration with JavaScript and Python </h3> <!-- The description of the insight --> <p class="mt-3 text-neutral-600 dark:text-neutral-400"> Explore how to use surveilr RSSDs with TypeScript, JavaScript, Python, Rust, C/C++, Zig and Other Languages </p> <!-- The "Read More" hyperlink going to the full insight. With an arrow icon --> <p class="mt-5 inline-flex items-center gap-x-1 font-medium text-orange-400 decoration-2 group-hover:underline dark:text-orange-300"> Read more <svg class="size-4 flex-shrink-0" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </p> </div> </a><!-- The anchor tag is the root container for the "Insight" card. It links to the insight detail page. --><a class="group rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="insights/compliance-explorer/index.html"> <!-- This is the container for the insight's cover image. --> <div class="relative overflow-hidden rounded-xl pt-[50%] sm:pt-[70%]"> <img src="_astro/compliance-explorer-pattern.2o85tCgk_uOTMq.avif" alt="Compliance Explorer" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="absolute start-0 top-0 size-full rounded-xl object-cover transition duration-500 ease-in-out group-hover:scale-105"> </div> <!-- This is the container for the insight's title and description. --> <div class="mt-7"> <!-- The title of the insight --> <h3 class="text-xl font-bold text-neutral-800 group-hover:text-neutral-600 dark:text-neutral-200 dark:group-hover:text-neutral-400"> Surveilr Compliance Explorer Pattern – Streamlining Compliance with SQL Scripts </h3> <!-- The description of the insight --> <p class="mt-3 text-neutral-600 dark:text-neutral-400"> Discover Surveilr's Compliance Explorer Pattern – a powerful tool for managing compliance data with SQL-based automation. Ideal for organizations looking to centralize compliance evidence, monitor resources, and simplify data analysis across platforms </p> <!-- The "Read More" hyperlink going to the full insight. With an arrow icon --> <p class="mt-5 inline-flex items-center gap-x-1 font-medium text-orange-400 decoration-2 group-hover:underline dark:text-orange-300"> Read more <svg class="size-4 flex-shrink-0" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m9 18 6-6-6-6" class></path></svg> </p> </div> </a> </div> </section> </main> </div> <footer class="w-full bg-neutral-300 dark:bg-neutral-900"> <div class="mx-auto w-full max-w-[85rem] px-4 py-10 sm:px-6 lg:px-16 lg:pt-20 2xl:max-w-screen-2xl"> <div class="grid grid-cols-2 gap-6 md:grid-cols-4 lg:grid-cols-5"> <div class="col-span-full lg:col-span-1"> <!-- Brand Logo --> <img src="_astro/surveilr-logo-with-tagline.DhfmVTrk_ZOYF0D.webp" alt="surveilr logo" width="264" height="66" loading="lazy" decoding="async"> </div> <!-- An array of links for Pattern and Company sections --> <div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Ecosystem </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="blog/surveilr-core-vs-patterns.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Core vs. Patterns </a> </li><li> <a href="https://compliantinsecurity.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Compliant Insecurity </a> </li><li> <a href="https://sql-aide.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> SQL Aide </a> </li><li> <a href="services.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Professional Services </a> </li> </ul> </div><div class="col-span-1"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Organization </h3> <ul class="mt-3 grid space-y-3"> <li> <a href="https://www.netspective.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Netspective </a> </li><li> <a href="https://www.opsfolio.com" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> About Opsfolio </a> </li><li> <a href="blog.html" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Blog </a> </li><li> <a href="https://discord.gg/fYHv3zzB" class="inline-flex gap-x-2 rounded-lg text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-500 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:text-neutral-300 dark:focus:outline-none"> Discord </a> </li> </ul> </div> <div class="col-span-2"> <h3 class="font-bold text-neutral-800 dark:text-neutral-200"> Stay up to date </h3> <form> <div class="mt-4 flex flex-col items-center gap-2 rounded-lg bg-neutral-200 p-2 dark:bg-neutral-800 sm:flex-row sm:gap-3"> <div class="w-full"> <label for="footer-input" class="sr-only">Search</label> <input type="text" id="footer-input" name="footer-input" class="block w-full rounded-lg border-transparent bg-neutral-100 px-4 py-3 text-sm text-neutral-600 focus:border-orange-400 focus:ring-orange-400 disabled:pointer-events-none disabled:opacity-50 dark:border-transparent dark:bg-neutral-700 dark:text-gray-300 dark:placeholder:text-neutral-300" placeholder="Enter your email"> </div> <a class="inline-flex w-full items-center justify-center gap-x-2 whitespace-nowrap rounded-lg border border-transparent bg-orange-400 p-3 text-sm font-bold text-neutral-50 outline-none ring-zinc-500 transition duration-300 hover:bg-orange-500 focus-visible:ring disabled:pointer-events-none disabled:opacity-50 dark:ring-zinc-200 dark:focus:outline-none dark:focus:ring-1 sm:w-auto" href="insights.html#"> Subscribe </a> </div> <p class="mt-3 text-sm text-neutral-600 dark:text-neutral-400"> Stay updated with the latest tools and exclusive deals. </p> </form> </div> </div> <div class="mt-9 grid gap-y-2 sm:mt-12 sm:flex sm:items-center sm:justify-between sm:gap-y-0"> <div class="flex items-center justify-between"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> © <span id="current-year"></span> Netspective Communications LLC. Crafted by <a class="rounded-lg font-medium underline underline-offset-2 outline-none ring-zinc-500 transition duration-300 hover:text-neutral-700 hover:decoration-dashed focus:outline-none focus-visible:ring dark:ring-zinc-200 dark:hover:text-neutral-300" href="https://shahidshah.com" target="_blank" rel="noopener noreferrer">Shahid N. Shah</a>. <span> 🕰️ Publication created Apr 7 2025, 4:45 AM.</span> </p> </div> <!-- Social Brands --> <div> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://www.linkedin.com/company/netspective-communications-llc" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>LinkedIn</title><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://twitter.com/netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Twitter</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://github.com/surveilr" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://plus.google.com/+Netspective" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Google</title><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" class></path></svg> </a> <a class="inline-flex h-10 w-10 items-center justify-center gap-x-2 rounded-lg border border-transparent text-sm font-bold text-neutral-700 outline-none ring-zinc-500 hover:bg-neutral-500/10 focus:outline-none focus-visible:ring focus-visible:ring-zinc-500 dark:ring-zinc-200 dark:hover:bg-neutral-50/10" href="https://discord.gg/fYHv3zzB" target="_blank" rel="noopener noreferrer"> <svg class="h-4 w-4 flex-shrink-0 fill-current text-neutral-700 dark:text-neutral-400" viewBox="0 0 24 24" fill="currentColor"><title>Discord</title><path d="M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z" class></path></svg> </a> </div> </div> <script type="module">const e=new Date().getFullYear(),t=document.getElementById("current-year");t.innerText=e.toString();</script> </div> </footer> </body> </html> | html | 62533 | 2025-04-07 05:49:49.699002893 UTC | 2025-04-07 05:49:51 | UNKNOWN | |||||||||
01JR7CRJV0395M90TJB216K5TX | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/pradeep-narayanan.DRyfIcLY_ZF4Jr3.avif | - | avif | 1114 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV09S660JRVQK9S3XQ3 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif | - | avif | 3308 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV0DSMAXFMFXNSET442 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/compliance-explorer-pattern.2o85tCgk_uOTMq.avif | - | avif | 11956 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV0QW7WJRY5SD02QAZV | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/sqlite-for-rssd.CE6PRJp4_14Fpbr.avif | - | avif | 22772 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV0K65BCAF6R38CTWR7 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/research-study-explorer-pattern-ss-4.CC8jC-eH_HnpfP.avif | - | avif | 29432 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV0ECTF11NJSSR839DS | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/compliance-explorer-pattern-ss-3.DiO7uket_Z1DkYmV.avif | - | avif | 45887 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV0S5FCW9X0VT009H2Q | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/direct-message-ss-2.-NkgDban_24UsnL.avif | - | avif | 25987 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV0JDMGHSC0EG40NJR9 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/lectio-pattern-ss-2.zJD0Yndi_6rvN.avif | - | avif | 18531 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1RSJTPBM3B8Y0V3RP | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif | - | avif | 15068 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1S51MR8F7HD2ZT43N | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/lectio-pattern-ss-1.qKsXv9u-_Z1ly0mY.avif | - | avif | 17598 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1PAYP3WQ7BRMCZE8X | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/fleetfolio-screenshot-1.BvMYEE66_ZFm5dn.avif | - | avif | 23979 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1DQH5VGS3PRCK737C | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/qualityfolio-service.C9b0xh7M_Z1EuDqP.avif | - | avif | 39781 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1SQCHYDCJMNRG926V | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/api-permission.nOsF-Y0d_MX80f.webp | - | webp | 32002 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1B89DX9EF0VSMJFYF | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif | - | avif | 29516 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1AHHAM9KZDYPC3B65 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/direct-message-pattern.DGfgjnh7_1BHOKB.avif | - | avif | 30452 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV10D8E356WV2EQ979D | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/custom-professional-service.BUExLA9c_1qarqa.avif | - | avif | 44888 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1K92V96APH813RWWS | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/code-block.CG06ApEY_Z5vlod.avif | - | avif | 50585 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1WVD5AQDQERY7WQHJ | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/why-stateful-integration.TtFEGayC_jPkqR.avif | - | avif | 9824 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV17DQ4ZR3VB8SWY8YR | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/person-working.5CrUjSfj_WOT1P.avif | - | avif | 32767 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1BZATV69YQT891BKC | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/ajay-kumaran.CJDSQGQJ_Z1kBgPT.avif | - | avif | 10608 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV1XM5C36V1E932RJY5 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/print.BL8QyxEA.css | - | css | 4023 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV2DNZ236W2DHF2GG0V | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/blueprint-2.DSItIwt1_1sl0AH.avif | - | avif | 34358 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV24RCWZRAGDSC0EDKE | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/quality-folio.BI_YY2zZ_1bR8P.avif | - | avif | 18700 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV2EMZ1J11308ZZJRNG | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/features-image.DAEsWM5S_1EpTNU.avif | - | avif | 46730 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV288BYKZ421068AK1B | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/index.BcY-adz4.css | - | css | 66944 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN | ||||||||||
01JR7CRJV2HMRJHYE6GYVAXRH5 | 01JR7CRJSKD3QA3ZXFBWN5QZQJ | 01JR7CRJSM2GJMXSTX4RZ8RV6C | 01JR7CRJSNH5VET82WMAN9G4JQ | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/_astro/applications.BRzGGOGU_ZdQtXj.webp | - | webp | 19928 | 2025-04-07 04:48:31 UTC | 2025-04-07 05:49:51 | UNKNOWN |