uniform_resource (table) Content
01JR05MVJ7W8FMND43PY3Q2M95 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/control.md | 02fe39964903868bd276674684d1a5b7c32f73b4 | --- site-quality-control-id: 1 name: HTML Meta Tags fii: FII-SQE-SEO-HMT-0001 --- HTML meta tags are snippets of text placed in the <head> section of an HTML document to provide metadata about the web page. They help browsers, search engines, and social media platforms understand the pages content and purpose. These tags improve search engine optimization (SEO), enhance social media sharing, and aid in accessibility. | md | 422 | 2025-04-04 10:08:26.675651101 UTC | { "frontMatter": "---\nsite-quality-control-id: 1\nname: HTML Meta Tags\nfii: FII-SQE-SEO-HMT-0001\n---\n", "body": "\nHTML meta tags are snippets of text placed in the <head> section of an HTML\ndocument to provide metadata about the web page. They help browsers, search\nengines, and social media platforms understand the pages content and purpose.\nThese tags improve search engine optimization (SEO), enhance social media\nsharing, and aid in accessibility.\n", "attrs": { "site-quality-control-id": 1, "name": "HTML Meta Tags", "fii": "FII-SQE-SEO-HMT-0001" } } | { "site-quality-control-id": 1, "name": "HTML Meta Tags", "fii": "FII-SQE-SEO-HMT-0001" } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ77SRH95EKA6N6W3JY | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-author.md | 97ed1c9c68ac49488719705ac45739c337162b1d | --- name: Meta Author site-quality-control-id: 1 description: HTML meta tags must include the author's name for authorship. property-name: author impact: Missing author can reduce trust in the content and affect SEO. suggested-solution: Specify the author's name to improve trust and SEO for the page. --- Specify the author's name, especially for blogs or opinion pieces, to attribute the content properly. This is generally used for transparency and may improve trust, especially for personal or professional publications. | md | 526 | 2025-04-04 10:08:26.675651101 UTC | { "frontMatter": "---\nname: Meta Author\nsite-quality-control-id: 1\ndescription: HTML meta tags must include the author's name for authorship.\nproperty-name: author\nimpact: Missing author can reduce trust in the content and affect SEO.\nsuggested-solution: Specify the author's name to improve trust and SEO for the page.\n---\n", "body": "\nSpecify the author's name, especially for blogs or opinion pieces, to attribute\nthe content properly. This is generally used for transparency and may improve\ntrust, especially for personal or professional publications.\n", "attrs": { "name": "Meta Author", "site-quality-control-id": 1, "description": "HTML meta tags must include the author's name for authorship.", "property-name": "author", "impact": "Missing author can reduce trust in the content and affect SEO.", "suggested-solution": "Specify the author's name to improve trust and SEO for the page." } } | { "name": "Meta Author", "site-quality-control-id": 1, "description": "HTML meta tags must include the author's name for authorship.", "property-name": "author", "impact": "Missing author can reduce trust in the content and affect SEO.", "suggested-solution": "Specify the author's name to improve trust and SEO for the page." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ8MQ9CDQ5RRTRCHYCS | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-http-equiv.md | c242b3ff340d57d4c77b87784b1ae640cf368076 | --- name: Meta Http-Equiv site-quality-control-id: 1 description: HTML meta tags must include http-equiv to define HTTP headers. property-name: http-equiv impact: Missing http-equiv meta tags can lead to improper HTTP header settings. suggested-solution: Include http-equiv meta tags to define Content-Type, browser compatibility, and security headers effectively. --- Use http-equiv to set HTTP headers in HTML, such as Content-Type, X-UA-Compatible, and Content-Security-Policy. The most common use is setting the Content-Type as "text/html; charset=UTF-8". This can also control browser compatibility and security. | md | 619 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Http-Equiv\nsite-quality-control-id: 1\ndescription: HTML meta tags must include http-equiv to define HTTP headers.\nproperty-name: http-equiv\nimpact: Missing http-equiv meta tags can lead to improper HTTP header settings.\nsuggested-solution: Include http-equiv meta tags to define Content-Type, browser compatibility, and security headers effectively.\n---\n", "body": "\nUse http-equiv to set HTTP headers in HTML, such as Content-Type,\nX-UA-Compatible, and Content-Security-Policy. The most common use is setting the\nContent-Type as \"text/html; charset=UTF-8\". This can also control browser\ncompatibility and security.\n", "attrs": { "name": "Meta Http-Equiv", "site-quality-control-id": 1, "description": "HTML meta tags must include http-equiv to define HTTP headers.", "property-name": "http-equiv", "impact": "Missing http-equiv meta tags can lead to improper HTTP header settings.", "suggested-solution": "Include http-equiv meta tags to define Content-Type, browser compatibility, and security headers effectively." } } | { "name": "Meta Http-Equiv", "site-quality-control-id": 1, "description": "HTML meta tags must include http-equiv to define HTTP headers.", "property-name": "http-equiv", "impact": "Missing http-equiv meta tags can lead to improper HTTP header settings.", "suggested-solution": "Include http-equiv meta tags to define Content-Type, browser compatibility, and security headers effectively." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ86NG6NR88X160T07D | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-robots.md | fcb5aa6dd59c0c929093b5b845404862c357abba | --- name: Meta Robots site-quality-control-id: 1 description: HTML meta tags must include robots directive for search engines. property-name: robots impact: Missing robots tag can result in unwanted pages being indexed by search engines. suggested-solution: Add a robots meta tag to control which pages are indexed by search engines. --- The robots tag helps control page indexing with directives like "index, follow" or "noindex, nofollow". Common settings include "noindex" to prevent indexing or "nofollow" to disallow link following, controlling how search engines interact with the page. | md | 594 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Robots\nsite-quality-control-id: 1\ndescription: HTML meta tags must include robots directive for search engines.\nproperty-name: robots\nimpact: Missing robots tag can result in unwanted pages being indexed by search engines.\nsuggested-solution: Add a robots meta tag to control which pages are indexed by search engines.\n---\n", "body": "\nThe robots tag helps control page indexing with directives like \"index, follow\"\nor \"noindex, nofollow\". Common settings include \"noindex\" to prevent indexing or\n\"nofollow\" to disallow link following, controlling how search engines interact\nwith the page.\n", "attrs": { "name": "Meta Robots", "site-quality-control-id": 1, "description": "HTML meta tags must include robots directive for search engines.", "property-name": "robots", "impact": "Missing robots tag can result in unwanted pages being indexed by search engines.", "suggested-solution": "Add a robots meta tag to control which pages are indexed by search engines." } } | { "name": "Meta Robots", "site-quality-control-id": 1, "description": "HTML meta tags must include robots directive for search engines.", "property-name": "robots", "impact": "Missing robots tag can result in unwanted pages being indexed by search engines.", "suggested-solution": "Add a robots meta tag to control which pages are indexed by search engines." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ80827RHGRRQBASF59 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-generator.md | 1a18a3892335b05ca2738c26213023fccb6e779b | --- name: Meta Generator site-quality-control-id: 1 description: HTML meta tags must include a generator tag specifying the CMS. property-name: generator impact: Missing generator can lead to confusion about the site's platform. suggested-solution: Include a generator tag specifying the CMS used (e.g., WordPress, Drupal). --- The generator tag specifies the software or CMS used to create the page (e.g., "WordPress 5.8", "Drupal 9"). This helps with support and troubleshooting, though it can sometimes pose a security risk if outdated versions are disclosed. | md | 564 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Generator\nsite-quality-control-id: 1\ndescription: HTML meta tags must include a generator tag specifying the CMS.\nproperty-name: generator\nimpact: Missing generator can lead to confusion about the site's platform.\nsuggested-solution: Include a generator tag specifying the CMS used (e.g., WordPress, Drupal).\n---\n", "body": "\nThe generator tag specifies the software or CMS used to create the page (e.g.,\n\"WordPress 5.8\", \"Drupal 9\"). This helps with support and troubleshooting,\nthough it can sometimes pose a security risk if outdated versions are disclosed.\n", "attrs": { "name": "Meta Generator", "site-quality-control-id": 1, "description": "HTML meta tags must include a generator tag specifying the CMS.", "property-name": "generator", "impact": "Missing generator can lead to confusion about the site's platform.", "suggested-solution": "Include a generator tag specifying the CMS used (e.g., WordPress, Drupal)." } } | { "name": "Meta Generator", "site-quality-control-id": 1, "description": "HTML meta tags must include a generator tag specifying the CMS.", "property-name": "generator", "impact": "Missing generator can lead to confusion about the site's platform.", "suggested-solution": "Include a generator tag specifying the CMS used (e.g., WordPress, Drupal)." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ89VFR8B9YBY1336J7 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-content.md | 5fc46e706f8cb4140dda01601ec5690ec05df941 | --- name: Meta Content site-quality-control-id: 1 description: HTML meta tags must include content for description, keywords, etc. property-name: content impact: Missing content can reduce search engine visibility and mislead users. suggested-solution: Ensure that every meta tag includes appropriate content (e.g., description, keywords) relevant to the page. --- Each <meta> tag with a name attribute (like description or keywords) should include relevant content.For example, the description content should provide a summary of the page in about 150 characters, while keywords should be specific to the content. | md | 616 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Content\nsite-quality-control-id: 1\ndescription: HTML meta tags must include content for description, keywords, etc.\nproperty-name: content\nimpact: Missing content can reduce search engine visibility and mislead users.\nsuggested-solution: Ensure that every meta tag includes appropriate content (e.g., description, keywords) relevant to the page.\n---\n", "body": "\nEach <meta> tag with a name attribute (like description or keywords) should\ninclude relevant content.For example, the description content should provide a\nsummary of the page in about 150 characters, while keywords should be specific\nto the content.\n", "attrs": { "name": "Meta Content", "site-quality-control-id": 1, "description": "HTML meta tags must include content for description, keywords, etc.", "property-name": "content", "impact": "Missing content can reduce search engine visibility and mislead users.", "suggested-solution": "Ensure that every meta tag includes appropriate content (e.g., description, keywords) relevant to the page." } } | { "name": "Meta Content", "site-quality-control-id": 1, "description": "HTML meta tags must include content for description, keywords, etc.", "property-name": "content", "impact": "Missing content can reduce search engine visibility and mislead users.", "suggested-solution": "Ensure that every meta tag includes appropriate content (e.g., description, keywords) relevant to the page." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ9FJZW3VMS6XJJWBZE | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-keywords.md | 6833cbcf498dcf2264356aeaaa0166958e5d4a30 | --- name: Meta Keywords site-quality-control-id: 1 description: HTML meta tags must include relevant keywords. property-name: keywords impact: Missing keywords may affect search engine optimization (SEO). suggested-solution: Include relevant keywords in the meta tag to improve SEO and discoverability. --- List relevant keywords in a comma-separated format to highlight key topics of the page. Although not heavily used by search engines, it can provide extra context in some cases. Include specific terms relevant to the page’s content, ideally around 5-10 keywords. | md | 572 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Keywords\nsite-quality-control-id: 1\ndescription: HTML meta tags must include relevant keywords.\nproperty-name: keywords\nimpact: Missing keywords may affect search engine optimization (SEO).\nsuggested-solution: Include relevant keywords in the meta tag to improve SEO and discoverability.\n---\n", "body": "\nList relevant keywords in a comma-separated format to highlight key topics of\nthe page. Although not heavily used by search engines, it can provide extra\ncontext in some cases. Include specific terms relevant to the page’s content,\nideally around 5-10 keywords.\n", "attrs": { "name": "Meta Keywords", "site-quality-control-id": 1, "description": "HTML meta tags must include relevant keywords.", "property-name": "keywords", "impact": "Missing keywords may affect search engine optimization (SEO).", "suggested-solution": "Include relevant keywords in the meta tag to improve SEO and discoverability." } } | { "name": "Meta Keywords", "site-quality-control-id": 1, "description": "HTML meta tags must include relevant keywords.", "property-name": "keywords", "impact": "Missing keywords may affect search engine optimization (SEO).", "suggested-solution": "Include relevant keywords in the meta tag to improve SEO and discoverability." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ93R9SMX3E98JBQNGF | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-charset.md | fc14c1db897bb6cc6d30604da55427f454b5301b | --- name: Meta Charset site-quality-control-id: 1 description: HTML meta tags must include the charset specification. property-name: charset impact: Missing charset can cause incorrect rendering of text, especially for non-Latin languages. suggested-solution: Specify the charset, such as UTF-8, to ensure proper character encoding and text display. --- Define the character encoding using "UTF-8" to support various languages and symbols, ensuring proper rendering of text across devices. The charset tag should be placed within the <head> section and ideally be one of the first tags to load for consistent encoding. | md | 620 | 2025-04-04 10:08:26.675651101 UTC | { "frontMatter": "---\nname: Meta Charset\nsite-quality-control-id: 1\ndescription: HTML meta tags must include the charset specification.\nproperty-name: charset\nimpact: Missing charset can cause incorrect rendering of text, especially for non-Latin languages.\nsuggested-solution: Specify the charset, such as UTF-8, to ensure proper character encoding and text display.\n---\n", "body": "\nDefine the character encoding using \"UTF-8\" to support various languages and\nsymbols, ensuring proper rendering of text across devices. The charset tag\nshould be placed within the <head> section and ideally be one of the first tags\nto load for consistent encoding.\n", "attrs": { "name": "Meta Charset", "site-quality-control-id": 1, "description": "HTML meta tags must include the charset specification.", "property-name": "charset", "impact": "Missing charset can cause incorrect rendering of text, especially for non-Latin languages.", "suggested-solution": "Specify the charset, such as UTF-8, to ensure proper character encoding and text display." } } | { "name": "Meta Charset", "site-quality-control-id": 1, "description": "HTML meta tags must include the charset specification.", "property-name": "charset", "impact": "Missing charset can cause incorrect rendering of text, especially for non-Latin languages.", "suggested-solution": "Specify the charset, such as UTF-8, to ensure proper character encoding and text display." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ9H9EAK0S2MSQETABH | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-description.md | 3a09307837f5e9c5f393821a21787283a62b93a2 | --- name: Meta Description site-quality-control-id: 1 description: HTML meta tags must include a description tag for SEO. property-name: description impact: Missing description can impact search engine rankings and user click-through rates. suggested-solution: Add a concise description of the page (70-160 characters) to improve SEO and user engagement. --- The description tag should provide a concise, compelling summary of the page within 70-160 characters. This is often displayed as a snippet in search results, so make it informative and engaging to encourage clicks. | md | 576 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Description\nsite-quality-control-id: 1\ndescription: HTML meta tags must include a description tag for SEO.\nproperty-name: description\nimpact: Missing description can impact search engine rankings and user click-through rates.\nsuggested-solution: Add a concise description of the page (70-160 characters) to improve SEO and user engagement.\n---\n", "body": "\nThe description tag should provide a concise, compelling summary of the page\nwithin 70-160 characters. This is often displayed as a snippet in search\nresults, so make it informative and engaging to encourage clicks.\n", "attrs": { "name": "Meta Description", "site-quality-control-id": 1, "description": "HTML meta tags must include a description tag for SEO.", "property-name": "description", "impact": "Missing description can impact search engine rankings and user click-through rates.", "suggested-solution": "Add a concise description of the page (70-160 characters) to improve SEO and user engagement." } } | { "name": "Meta Description", "site-quality-control-id": 1, "description": "HTML meta tags must include a description tag for SEO.", "property-name": "description", "impact": "Missing description can impact search engine rankings and user click-through rates.", "suggested-solution": "Add a concise description of the page (70-160 characters) to improve SEO and user engagement." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJ9ZSE17X8RTBDNTCPM | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-viewport.md | b14b515b2648605b99bb1bc538b65b1d3668c239 | --- name: Meta Viewport site-quality-control-id: 1 description: HTML meta tags must include a viewport specification for mobile. property-name: viewport impact: Missing viewport tag can cause the website to appear incorrectly on mobile devices. suggested-solution: Add the viewport meta tag to ensure the site is properly displayed on mobile devices. --- The viewport tag ensures proper scaling on mobile devices. A common setup is "width=device-width, initial-scale=1.0", allowing the content to fit within the device screen. This is essential for responsive design, enabling the website to adapt to varying screen sizes. | md | 624 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Viewport\nsite-quality-control-id: 1\ndescription: HTML meta tags must include a viewport specification for mobile.\nproperty-name: viewport\nimpact: Missing viewport tag can cause the website to appear incorrectly on mobile devices.\nsuggested-solution: Add the viewport meta tag to ensure the site is properly displayed on mobile devices.\n---\n", "body": "\nThe viewport tag ensures proper scaling on mobile devices. A common setup is\n\"width=device-width, initial-scale=1.0\", allowing the content to fit within the\ndevice screen. This is essential for responsive design, enabling the website to\nadapt to varying screen sizes.\n", "attrs": { "name": "Meta Viewport", "site-quality-control-id": 1, "description": "HTML meta tags must include a viewport specification for mobile.", "property-name": "viewport", "impact": "Missing viewport tag can cause the website to appear incorrectly on mobile devices.", "suggested-solution": "Add the viewport meta tag to ensure the site is properly displayed on mobile devices." } } | { "name": "Meta Viewport", "site-quality-control-id": 1, "description": "HTML meta tags must include a viewport specification for mobile.", "property-name": "viewport", "impact": "Missing viewport tag can cause the website to appear incorrectly on mobile devices.", "suggested-solution": "Add the viewport meta tag to ensure the site is properly displayed on mobile devices." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJAJ72SE84FV7JB5D3S | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-title.md | b5fdc3256adcf33755e07a65cd9a9016256dc6fb | --- name: Meta Title site-quality-control-id: 1 description: The title tag, if used, is generally intended to provide additional metadata about the title rather than set the primary title itself. property-name: title impact: If the title is missing, it typically has no direct impact, as <meta name="title"> is rarely recognized for SEO or social sharing. suggested-solution: Ensure that every meta tag includes a name attribute for proper metadata interpretation. --- The <title> tag is the standard way to define the primary title of the page. If using <meta name="title">, it should complement, not replace, the primary title. Avoid using <meta name="title"> as the main title, as it is not widely supported and does not affect SEO or social media visibility. | md | 764 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: Meta Title\nsite-quality-control-id: 1\ndescription: The title tag, if used, is generally intended to provide additional metadata about the title rather than set the primary title itself.\nproperty-name: title\nimpact: If the title is missing, it typically has no direct impact, as <meta name=\"title\"> is rarely recognized for SEO or social sharing.\nsuggested-solution: Ensure that every meta tag includes a name attribute for proper metadata interpretation.\n---\n", "body": "\nThe <title> tag is the standard way to define the primary title of the page. If\nusing <meta name=\"title\">, it should complement, not replace, the primary title.\nAvoid using <meta name=\"title\"> as the main title, as it is not widely supported\nand does not affect SEO or social media visibility.\n", "attrs": { "name": "Meta Title", "site-quality-control-id": 1, "description": "The title tag, if used, is generally intended to provide additional metadata about the title rather than set the primary title itself.", "property-name": "title", "impact": "If the title is missing, it typically has no direct impact, as <meta name=\"title\"> is rarely recognized for SEO or social sharing.", "suggested-solution": "Ensure that every meta tag includes a name attribute for proper metadata interpretation." } } | { "name": "Meta Title", "site-quality-control-id": 1, "description": "The title tag, if used, is generally intended to provide additional metadata about the title rather than set the primary title itself.", "property-name": "title", "impact": "If the title is missing, it typically has no direct impact, as <meta name=\"title\"> is rarely recognized for SEO or social sharing.", "suggested-solution": "Ensure that every meta tag includes a name attribute for proper metadata interpretation." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJA7C70Q8WX5QM3MT1H | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/html-meta-tags/policies/meta-application-name.md | b91352319472313354ad3533908f87c57f65638c | --- name: Meta Application Name site-quality-control-id: 1 description: HTML meta tags must include an application-name for web apps. property-name: application-name impact: Missing application name may impact the app-like behavior of the website on mobile devices. suggested-solution: Include the application name meta tag to optimize the site for web app usage on mobile devices. --- The application-name tag is especially useful for mobile web apps, providing the name displayed when the app is added to the home screen. This tag enhances branding for web applications accessed through mobile devices. | md | 606 | 2025-04-04 10:08:26.675651101 UTC | { "frontMatter": "---\nname: Meta Application Name\nsite-quality-control-id: 1\ndescription: HTML meta tags must include an application-name for web apps.\nproperty-name: application-name\nimpact: Missing application name may impact the app-like behavior of the website on mobile devices.\nsuggested-solution: Include the application name meta tag to optimize the site for web app usage on mobile devices.\n---\n", "body": "\nThe application-name tag is especially useful for mobile web apps, providing the\nname displayed when the app is added to the home screen. This tag enhances\nbranding for web applications accessed through mobile devices.\n", "attrs": { "name": "Meta Application Name", "site-quality-control-id": 1, "description": "HTML meta tags must include an application-name for web apps.", "property-name": "application-name", "impact": "Missing application name may impact the app-like behavior of the website on mobile devices.", "suggested-solution": "Include the application name meta tag to optimize the site for web app usage on mobile devices." } } | { "name": "Meta Application Name", "site-quality-control-id": 1, "description": "HTML meta tags must include an application-name for web apps.", "property-name": "application-name", "impact": "Missing application name may impact the app-like behavior of the website on mobile devices.", "suggested-solution": "Include the application name meta tag to optimize the site for web app usage on mobile devices." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJAFGD2ZGSX77AQJHCZ | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/twitter-card-meta-data/control.md | 398f2a4ec89f4750c7f2db1a92675301881e8349 | --- site-quality-control-id: 3 name: Twitter Card Metadata fii: FII-SQE-SEO-TCM-0001 --- Twitter Card metadata enables web pages to display rich content when shared on Twitter. By adding specific meta tags, you can control how your content appears on Twitter, improving engagement and click-through rates. | md | 307 | 2025-04-04 10:08:26.677651099 UTC | { "frontMatter": "---\nsite-quality-control-id: 3\nname: Twitter Card Metadata\nfii: FII-SQE-SEO-TCM-0001\n---\n", "body": "\nTwitter Card metadata enables web pages to display rich content when shared on\nTwitter. By adding specific meta tags, you can control how your content appears\non Twitter, improving engagement and click-through rates.\n", "attrs": { "site-quality-control-id": 3, "name": "Twitter Card Metadata", "fii": "FII-SQE-SEO-TCM-0001" } } | { "site-quality-control-id": 3, "name": "Twitter Card Metadata", "fii": "FII-SQE-SEO-TCM-0001" } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJA6C0MBXEZF1EVQQ8E | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/twitter-card-meta-data/policies/twitter-title.md | a0aa7ae0faeb09a0640545a0ed7cb5e9abe5e38c | --- name: Twitter Title site-quality-control-id: 3 description: Twitter metadata must include a title for sharing. property-name: twitter:title impact: Missing title can result in a poor social preview and lower engagement. suggested-solution: Add an appropriate title for better engagement when shared on Twitter. --- The Twitter title is important for creating a preview when the content is shared on Twitter. It should be descriptive, engaging, and between 70-100 characters. Ensure the title aligns with the content and encourages users to click. | md | 552 | 2025-04-04 10:08:26.677651099 UTC | { "frontMatter": "---\nname: Twitter Title\nsite-quality-control-id: 3\ndescription: Twitter metadata must include a title for sharing.\nproperty-name: twitter:title\nimpact: Missing title can result in a poor social preview and lower engagement.\nsuggested-solution: Add an appropriate title for better engagement when shared on Twitter.\n---\n", "body": "\nThe Twitter title is important for creating a preview when the content is shared\non Twitter. It should be descriptive, engaging, and between 70-100 characters.\nEnsure the title aligns with the content and encourages users to click.\n", "attrs": { "name": "Twitter Title", "site-quality-control-id": 3, "description": "Twitter metadata must include a title for sharing.", "property-name": "twitter:title", "impact": "Missing title can result in a poor social preview and lower engagement.", "suggested-solution": "Add an appropriate title for better engagement when shared on Twitter." } } | { "name": "Twitter Title", "site-quality-control-id": 3, "description": "Twitter metadata must include a title for sharing.", "property-name": "twitter:title", "impact": "Missing title can result in a poor social preview and lower engagement.", "suggested-solution": "Add an appropriate title for better engagement when shared on Twitter." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJBM53YWCC72QP0BKKE | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/twitter-card-meta-data/policies/twitter-description.md | 443b3ccf0e5d6f0ea1c38fa02708a15b26d6d997 | --- name: Twitter Description site-quality-control-id: 3 description: Twitter Card metadata should provide a description for context. property-name: twitter:description impact: Missing description may reduce engagement by providing less context on Twitter. suggested-solution: Include a brief and meaningful description to improve user engagement on Twitter. --- The description should offer context within 70-200 characters, giving a summary that attracts interest without overwhelming the user. | md | 498 | 2025-04-04 10:08:26.677651099 UTC | { "frontMatter": "---\nname: Twitter Description\nsite-quality-control-id: 3\ndescription: Twitter Card metadata should provide a description for context.\nproperty-name: twitter:description\nimpact: Missing description may reduce engagement by providing less context on Twitter.\nsuggested-solution: Include a brief and meaningful description to improve user engagement on Twitter.\n---\n", "body": "\nThe description should offer context within 70-200 characters, giving a summary\nthat attracts interest without overwhelming the user.\n", "attrs": { "name": "Twitter Description", "site-quality-control-id": 3, "description": "Twitter Card metadata should provide a description for context.", "property-name": "twitter:description", "impact": "Missing description may reduce engagement by providing less context on Twitter.", "suggested-solution": "Include a brief and meaningful description to improve user engagement on Twitter." } } | { "name": "Twitter Description", "site-quality-control-id": 3, "description": "Twitter Card metadata should provide a description for context.", "property-name": "twitter:description", "impact": "Missing description may reduce engagement by providing less context on Twitter.", "suggested-solution": "Include a brief and meaningful description to improve user engagement on Twitter." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJBE9DBW23XKXQ3TFD9 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/twitter-card-meta-data/policies/twitter-image.md | 8ad6f5cb287052172b40f8caf712e077e2c08cb9 | --- name: Twitter Image site-quality-control-id: 3 description: Twitter metadata must include an image URL for sharing. property-name: twitter:image impact: Missing image can result in poor content visibility on Twitter. suggested-solution: Include a relevant image URL for better visibility and engagement on Twitter. --- The Twitter image is crucial for enhancing content visibility on Twitter. It should be a high-resolution image, ideally 1200x675 pixels, and under 5MB in size. The image should be relevant to the content and visually appealing. | md | 552 | 2025-04-04 10:08:26.677651099 UTC | { "frontMatter": "---\nname: Twitter Image\nsite-quality-control-id: 3\ndescription: Twitter metadata must include an image URL for sharing.\nproperty-name: twitter:image\nimpact: Missing image can result in poor content visibility on Twitter.\nsuggested-solution: Include a relevant image URL for better visibility and engagement on Twitter.\n---\n", "body": "\nThe Twitter image is crucial for enhancing content visibility on Twitter. It\nshould be a high-resolution image, ideally 1200x675 pixels, and under 5MB in\nsize. The image should be relevant to the content and visually appealing.\n", "attrs": { "name": "Twitter Image", "site-quality-control-id": 3, "description": "Twitter metadata must include an image URL for sharing.", "property-name": "twitter:image", "impact": "Missing image can result in poor content visibility on Twitter.", "suggested-solution": "Include a relevant image URL for better visibility and engagement on Twitter." } } | { "name": "Twitter Image", "site-quality-control-id": 3, "description": "Twitter metadata must include an image URL for sharing.", "property-name": "twitter:image", "impact": "Missing image can result in poor content visibility on Twitter.", "suggested-solution": "Include a relevant image URL for better visibility and engagement on Twitter." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJB1S0GQKGPHH9WKSFP | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/twitter-card-meta-data/policies/twitter-card-type.md | 020ecf4c1e5a381e480b8bfe55e5e92bfb33c824 | --- name: Twitter Card Type site-quality-control-id: 3 description: Twitter metadata must include a card type. property-name: twitter:card impact: Missing card type can result in improper content display on Twitter. suggested-solution: Ensure that a correct Twitter card type is defined, such as "summary" or "summary_large_image". --- The Twitter card type defines how the content is displayed on Twitter. Common card types include "summary" (for basic text and images), "summary_large_image" (for larger images), and "player" (for embedded media). Specifying the correct card type ensures that the content displays optimally. | md | 629 | 2025-04-04 10:08:26.677651099 UTC | { "frontMatter": "---\nname: Twitter Card Type\nsite-quality-control-id: 3\ndescription: Twitter metadata must include a card type.\nproperty-name: twitter:card\nimpact: Missing card type can result in improper content display on Twitter.\nsuggested-solution: Ensure that a correct Twitter card type is defined, such as \"summary\" or \"summary_large_image\".\n---\n", "body": "\nThe Twitter card type defines how the content is displayed on Twitter. Common\ncard types include \"summary\" (for basic text and images), \"summary_large_image\"\n(for larger images), and \"player\" (for embedded media). Specifying the correct\ncard type ensures that the content displays optimally.\n", "attrs": { "name": "Twitter Card Type", "site-quality-control-id": 3, "description": "Twitter metadata must include a card type.", "property-name": "twitter:card", "impact": "Missing card type can result in improper content display on Twitter.", "suggested-solution": "Ensure that a correct Twitter card type is defined, such as \"summary\" or \"summary_large_image\"." } } | { "name": "Twitter Card Type", "site-quality-control-id": 3, "description": "Twitter metadata must include a card type.", "property-name": "twitter:card", "impact": "Missing card type can result in improper content display on Twitter.", "suggested-solution": "Ensure that a correct Twitter card type is defined, such as \"summary\" or \"summary_large_image\"." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJBTY0KW5R265WXNKMQ | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/control.md | ae9b668276713a9fba01e59bc74381cd0dd81a6d | --- site-quality-control-id: 2 name: Open Graph Metadata fii: FII-SQE-SEO-OGM-0001 --- Open Graph metadata is a set of HTML meta tags used to control how web page content appears when shared on social media platforms. Developed by Facebook, the Open Graph protocol enables web pages to become "rich" objects, providing specific data points like title, description, and images, which enhance link previews and improve engagement. Placed within the <head> section, Open Graph tags provide consistency across platforms and ensure that shared links appear professional and informative. | md | 583 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nsite-quality-control-id: 2\nname: Open Graph Metadata\nfii: FII-SQE-SEO-OGM-0001\n---\n", "body": "\nOpen Graph metadata is a set of HTML meta tags used to control how web page\ncontent appears when shared on social media platforms. Developed by Facebook,\nthe Open Graph protocol enables web pages to become \"rich\" objects, providing\nspecific data points like title, description, and images, which enhance link\npreviews and improve engagement. Placed within the <head> section, Open Graph\ntags provide consistency across platforms and ensure that shared links appear\nprofessional and informative.\n", "attrs": { "site-quality-control-id": 2, "name": "Open Graph Metadata", "fii": "FII-SQE-SEO-OGM-0001" } } | { "site-quality-control-id": 2, "name": "Open Graph Metadata", "fii": "FII-SQE-SEO-OGM-0001" } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJCSGY4D9M0450C88VQ | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-image.md | 3c6578f6c1d73fd621630478e931083ac7ddc342 | --- name: OG Image site-quality-control-id: 2 description: Open Graph metadata must include an image URL. property-name: og:image impact: Missing image can result in content without an image, which reduces engagement. suggested-solution: Provide a valid image URL for better engagement on social platforms. --- The OG image provides a visual representation for the shared content. It should be a high-quality image relevant to the content, ideally with a minimum resolution of 1200x630 pixels and a 1.91:1 aspect ratio. JPEG or PNG formats are preferred, and the file size should be under 5MB for optimal loading. This image will appear in the link preview, attracting user attention and enhancing engagement. | md | 711 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG Image\nsite-quality-control-id: 2\ndescription: Open Graph metadata must include an image URL.\nproperty-name: og:image\nimpact: Missing image can result in content without an image, which reduces engagement.\nsuggested-solution: Provide a valid image URL for better engagement on social platforms.\n---\n", "body": "\nThe OG image provides a visual representation for the shared content. It should\nbe a high-quality image relevant to the content, ideally with a minimum\nresolution of 1200x630 pixels and a 1.91:1 aspect ratio. JPEG or PNG formats are\npreferred, and the file size should be under 5MB for optimal loading. This image\nwill appear in the link preview, attracting user attention and enhancing\nengagement.\n", "attrs": { "name": "OG Image", "site-quality-control-id": 2, "description": "Open Graph metadata must include an image URL.", "property-name": "og:image", "impact": "Missing image can result in content without an image, which reduces engagement.", "suggested-solution": "Provide a valid image URL for better engagement on social platforms." } } | { "name": "OG Image", "site-quality-control-id": 2, "description": "Open Graph metadata must include an image URL.", "property-name": "og:image", "impact": "Missing image can result in content without an image, which reduces engagement.", "suggested-solution": "Provide a valid image URL for better engagement on social platforms." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJC6TRYCNVKVYD85F0T | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-url.md | cdd3f6c157fd95cb8fb1cb40bf0070a2dad5338c | --- name: OG URL site-quality-control-id: 2 description: Open Graph metadata must include a URL for the content. property-name: og:url impact: Missing URL may cause issues with sharing the page correctly on social platforms. suggested-solution: Ensure that the URL in the Open Graph metadata points to the correct page or content. --- The OG URL specifies the link to the content, which is critical for proper page redirection and tracking. This URL should be the canonical URL of the content page, without unnecessary query parameters or fragments. It ensures that all shares lead back to a single URL, which helps with SEO and consistent social shares. | md | 656 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG URL\nsite-quality-control-id: 2\ndescription: Open Graph metadata must include a URL for the content.\nproperty-name: og:url\nimpact: Missing URL may cause issues with sharing the page correctly on social platforms.\nsuggested-solution: Ensure that the URL in the Open Graph metadata points to the correct page or content.\n---\n", "body": "\nThe OG URL specifies the link to the content, which is critical for proper page\nredirection and tracking. This URL should be the canonical URL of the content\npage, without unnecessary query parameters or fragments. It ensures that all\nshares lead back to a single URL, which helps with SEO and consistent social\nshares.\n", "attrs": { "name": "OG URL", "site-quality-control-id": 2, "description": "Open Graph metadata must include a URL for the content.", "property-name": "og:url", "impact": "Missing URL may cause issues with sharing the page correctly on social platforms.", "suggested-solution": "Ensure that the URL in the Open Graph metadata points to the correct page or content." } } | { "name": "OG URL", "site-quality-control-id": 2, "description": "Open Graph metadata must include a URL for the content.", "property-name": "og:url", "impact": "Missing URL may cause issues with sharing the page correctly on social platforms.", "suggested-solution": "Ensure that the URL in the Open Graph metadata points to the correct page or content." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJC53VYP2Q9FJQCNC1J | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-type.md | e6a6d2b8e7d310e573c976932f3e5ddf0a5831fb | --- name: OG Type site-quality-control-id: 2 description: Open Graph metadata must include a type for the content. property-name: og:type impact: Missing type can lead to improper rendering of the page in social media previews. suggested-solution: Specify the correct content type (e.g., website or article) in the Open Graph metadata tag. --- The OG type defines the nature of the content (e.g., "website" for a homepage or "article" for blog posts). Common types include "article" (for news articles, blogs), "website" (for general pages), "product" (for e-commerce products), and "video" (for media). Correct specification of type ensures optimal rendering on social platforms and helps them categorize content correctly. | md | 726 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG Type\nsite-quality-control-id: 2\ndescription: Open Graph metadata must include a type for the content.\nproperty-name: og:type\nimpact: Missing type can lead to improper rendering of the page in social media previews.\nsuggested-solution: Specify the correct content type (e.g., website or article) in the Open Graph metadata tag.\n---\n", "body": "\nThe OG type defines the nature of the content (e.g., \"website\" for a homepage or\n\"article\" for blog posts). Common types include \"article\" (for news articles,\nblogs), \"website\" (for general pages), \"product\" (for e-commerce products), and\n\"video\" (for media). Correct specification of type ensures optimal rendering on\nsocial platforms and helps them categorize content correctly.\n", "attrs": { "name": "OG Type", "site-quality-control-id": 2, "description": "Open Graph metadata must include a type for the content.", "property-name": "og:type", "impact": "Missing type can lead to improper rendering of the page in social media previews.", "suggested-solution": "Specify the correct content type (e.g., website or article) in the Open Graph metadata tag." } } | { "name": "OG Type", "site-quality-control-id": 2, "description": "Open Graph metadata must include a type for the content.", "property-name": "og:type", "impact": "Missing type can lead to improper rendering of the page in social media previews.", "suggested-solution": "Specify the correct content type (e.g., website or article) in the Open Graph metadata tag." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJC1P13T5ZYZZ7A5D3A | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-site-name.md | 71c8f5c95e10cd3ffc9054d92aa087f75f8d151f | --- name: OG Site Name site-quality-control-id: 2 description: Open Graph metadata must include the site name. property-name: og:site_name impact: Missing site name could impact site identity and recognition on social platforms. suggested-solution: Ensure that the Open Graph metadata includes your website's name for better brand recognition. --- The OG site name provides context on the origin of the content, helping build brand recognition on social platforms. It should match the website's brand or name, adding authority and trust to the shared content. Users are more likely to engage with recognizable and trusted sources, making this a crucial tag for brand consistency. | md | 681 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG Site Name\nsite-quality-control-id: 2\ndescription: Open Graph metadata must include the site name.\nproperty-name: og:site_name\nimpact: Missing site name could impact site identity and recognition on social platforms.\nsuggested-solution: Ensure that the Open Graph metadata includes your website's name for better brand recognition.\n---\n", "body": "\nThe OG site name provides context on the origin of the content, helping build\nbrand recognition on social platforms. It should match the website's brand or\nname, adding authority and trust to the shared content. Users are more likely to\nengage with recognizable and trusted sources, making this a crucial tag for\nbrand consistency.\n", "attrs": { "name": "OG Site Name", "site-quality-control-id": 2, "description": "Open Graph metadata must include the site name.", "property-name": "og:site_name", "impact": "Missing site name could impact site identity and recognition on social platforms.", "suggested-solution": "Ensure that the Open Graph metadata includes your website's name for better brand recognition." } } | { "name": "OG Site Name", "site-quality-control-id": 2, "description": "Open Graph metadata must include the site name.", "property-name": "og:site_name", "impact": "Missing site name could impact site identity and recognition on social platforms.", "suggested-solution": "Ensure that the Open Graph metadata includes your website's name for better brand recognition." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJDRRCPB94B9AYW6ZS6 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-locale.md | 3d52966ab5d67eaf0c1640afc6ac32d1c7cd382b | --- name: OG Locale site-quality-control-id: 2 description: Open Graph metadata must specify the locale. property-name: og:locale impact: Missing locale may affect the targeting of localized audiences. suggested-solution: Specify the appropriate locale in the Open Graph metadata for regional targeting. --- The OG locale tag defines the regional language of the content in the format language-region (e.g., en_US for U.S. English, es_ES for Spain Spanish). This helps social platforms target the correct audience by language and location, enhancing relevance. Specify the locale to ensure the page appears correctly to users from different regions. | md | 651 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG Locale\nsite-quality-control-id: 2\ndescription: Open Graph metadata must specify the locale.\nproperty-name: og:locale\nimpact: Missing locale may affect the targeting of localized audiences.\nsuggested-solution: Specify the appropriate locale in the Open Graph metadata for regional targeting.\n---\n", "body": "\nThe OG locale tag defines the regional language of the content in the format\nlanguage-region (e.g., en_US for U.S. English, es_ES for Spain Spanish). This\nhelps social platforms target the correct audience by language and location,\nenhancing relevance. Specify the locale to ensure the page appears correctly to\nusers from different regions.\n", "attrs": { "name": "OG Locale", "site-quality-control-id": 2, "description": "Open Graph metadata must specify the locale.", "property-name": "og:locale", "impact": "Missing locale may affect the targeting of localized audiences.", "suggested-solution": "Specify the appropriate locale in the Open Graph metadata for regional targeting." } } | { "name": "OG Locale", "site-quality-control-id": 2, "description": "Open Graph metadata must specify the locale.", "property-name": "og:locale", "impact": "Missing locale may affect the targeting of localized audiences.", "suggested-solution": "Specify the appropriate locale in the Open Graph metadata for regional targeting." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJD3PTVM80C1QZRXRYW | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-description.md | 9ddb573f859b07fd2671f9e709d2fa3788358486 | --- name: OG Description site-quality-control-id: 2 description: Open Graph metadata must include a description for context. property-name: og:description impact: Missing description can lead to unclear social media previews, decreasing user engagement. suggested-solution: Add a brief and relevant description in the Open Graph metadata tag for better content --- The OG description provides a brief, compelling summary of the content, aiming to attract viewers. The ideal length is between 70-200 characters, providing essential details to help users decide whether to engage with the content. Avoid generic language and focus on unique value propositions or key points from the page to maximize clicks and shares. | md | 718 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG Description\nsite-quality-control-id: 2\ndescription: Open Graph metadata must include a description for context.\nproperty-name: og:description\nimpact: Missing description can lead to unclear social media previews, decreasing user engagement.\nsuggested-solution: Add a brief and relevant description in the Open Graph metadata tag for better content\n---\n", "body": "\nThe OG description provides a brief, compelling summary of the content, aiming\nto attract viewers. The ideal length is between 70-200 characters, providing\nessential details to help users decide whether to engage with the content. Avoid\ngeneric language and focus on unique value propositions or key points from the\npage to maximize clicks and shares.\n", "attrs": { "name": "OG Description", "site-quality-control-id": 2, "description": "Open Graph metadata must include a description for context.", "property-name": "og:description", "impact": "Missing description can lead to unclear social media previews, decreasing user engagement.", "suggested-solution": "Add a brief and relevant description in the Open Graph metadata tag for better content" } } | { "name": "OG Description", "site-quality-control-id": 2, "description": "Open Graph metadata must include a description for context.", "property-name": "og:description", "impact": "Missing description can lead to unclear social media previews, decreasing user engagement.", "suggested-solution": "Add a brief and relevant description in the Open Graph metadata tag for better content" } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJDK6GAJ6GHT29HW567 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-updated-time.md | 3e006c4495ced46a562acce5c0955cd58da139dd | --- name: OG Updated Time site-quality-control-id: 2 description: Open Graph metadata should include the last updated time. property-name: og:updated_time impact: Missing updated time may reduce trust and freshness perception on social media. suggested-solution: Include the updated time in ISO 8601 format to signal content freshness. --- The OG updated time signals the freshness of the content to users, often displayed as "last updated" on social platforms. It should follow the ISO 8601 format (e.g., 2024-11-01T10:00:00Z), indicating the date and time the content was last modified. This helps users understand if the information is current and relevant, which can increase trust and engagement. | md | 703 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG Updated Time\nsite-quality-control-id: 2\ndescription: Open Graph metadata should include the last updated time.\nproperty-name: og:updated_time\nimpact: Missing updated time may reduce trust and freshness perception on social media.\nsuggested-solution: Include the updated time in ISO 8601 format to signal content freshness.\n---\n", "body": "\nThe OG updated time signals the freshness of the content to users, often\ndisplayed as \"last updated\" on social platforms. It should follow the ISO 8601\nformat (e.g., 2024-11-01T10:00:00Z), indicating the date and time the content\nwas last modified. This helps users understand if the information is current and\nrelevant, which can increase trust and engagement.\n", "attrs": { "name": "OG Updated Time", "site-quality-control-id": 2, "description": "Open Graph metadata should include the last updated time.", "property-name": "og:updated_time", "impact": "Missing updated time may reduce trust and freshness perception on social media.", "suggested-solution": "Include the updated time in ISO 8601 format to signal content freshness." } } | { "name": "OG Updated Time", "site-quality-control-id": 2, "description": "Open Graph metadata should include the last updated time.", "property-name": "og:updated_time", "impact": "Missing updated time may reduce trust and freshness perception on social media.", "suggested-solution": "Include the updated time in ISO 8601 format to signal content freshness." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJD7DDV8MTDMBB1GQN5 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/site-quality-controls/open-graph-meta-data/policies/og-title.md | df5b41f91e94131e0f734e2367e249179ea9c6b8 | --- name: OG Title site-quality-control-id: 2 description: Open Graph metadata must include a title for social sharing. property-name: og:title impact: Missing title can affect the site's appearance in social media previews. suggested-solution: Add a meaningful title to the Open Graph metadata tag to ensure a proper social media preview. --- The OG title is crucial for social sharing, as it serves as the headline when the content is shared on social platforms. It should be descriptive, concise, and attention-grabbing to encourage user engagement. Optimal length is between 30-60 characters. Avoid generic titles and make it unique and specific to the content. If the content changes, consider updating the title to reflect the most current context. | md | 756 | 2025-04-04 10:08:26.676651100 UTC | { "frontMatter": "---\nname: OG Title\nsite-quality-control-id: 2\ndescription: Open Graph metadata must include a title for social sharing.\nproperty-name: og:title\nimpact: Missing title can affect the site's appearance in social media previews.\nsuggested-solution: Add a meaningful title to the Open Graph metadata tag to ensure a proper social media preview.\n---\n", "body": "\nThe OG title is crucial for social sharing, as it serves as the headline when\nthe content is shared on social platforms. It should be descriptive, concise,\nand attention-grabbing to encourage user engagement. Optimal length is between\n30-60 characters. Avoid generic titles and make it unique and specific to the\ncontent. If the content changes, consider updating the title to reflect the most\ncurrent context.\n", "attrs": { "name": "OG Title", "site-quality-control-id": 2, "description": "Open Graph metadata must include a title for social sharing.", "property-name": "og:title", "impact": "Missing title can affect the site's appearance in social media previews.", "suggested-solution": "Add a meaningful title to the Open Graph metadata tag to ensure a proper social media preview." } } | { "name": "OG Title", "site-quality-control-id": 2, "description": "Open Graph metadata must include a title for social sharing.", "property-name": "og:title", "impact": "Missing title can affect the site's appearance in social media previews.", "suggested-solution": "Add a meaningful title to the Open Graph metadata tag to ensure a proper social media preview." } | 2025-04-04 10:30:48 | UNKNOWN | |||||||
01JR05MVJEPSJMEJJ43Q1NVBH1 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern.html | 252e1fb19449bb6480dd15f64a5e9b13d1649920 | <!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":"Patterns | surveilr","url":"https://www.surveilr.com/pattern/","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="pattern.html"><link rel="alternate" hreflang="en" href="pattern.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/pattern/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/"><meta property="og:type" content="website"><meta property="og:title" content="Patterns | 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/"><meta name="twitter:title" content="Patterns | 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>Patterns | 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.C1i_5bqm.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="pattern.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="27c56896-3b8c-4873-8a42-3a2acce11f49" data-path-length="1" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="27c56896-3b8c-4873-8a42-3a2acce11f49"> <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="pattern.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> 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":"/pattern/","name":"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"> <div 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="mb-4 flex items-center justify-between gap-8 sm:mb-8 md:mb-12"> <div class="flex items-center gap-12"> <h1 class="text-balance text-2xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Patterns </h1> <p class="hidden max-w-screen-sm text-pretty text-neutral-600 dark:text-neutral-400 md:block"> At the heart of surveilr is the flexibility to adapt to a wide range of industries, disciplines, and use cases. This adaptability is enabled through a combination of the surveilr Core engine and a modular approach to Patterns. </p> </div> <!-- 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="pattern.html#testimonials"> Customer Stories <!-- Display the arrow based on the 'noArrow' property --> </a> <!-- Styled hyperlink --><a class="inline-flex items-center justify-center gap-x-2 rounded-lg px-4 py-3 text-center text-sm font-medium text-neutral-600 shadow-sm outline-none ring-zinc-500 focus-visible:ring transition duration-300 border border-neutral-200 bg-neutral-300 hover:bg-neutral-400/50 hover:text-neutral-600 active:text-neutral-700 disabled:pointer-events-none disabled:opacity-50 2xl:text-base ring-zinc-500 dark:border-neutral-700 dark:bg-zinc-700 dark:text-neutral-300 dark:ring-zinc-200 dark:hover:bg-zinc-600 dark:focus:outline-none" href="https://github.com/surveilr/www.surveilr.com/tree/main/lib"> GitHub Code for Public Patterns </a> </div> <!--Displaying patterns in alternating styles. Alternative product gets different card styling.--> <!--Maps through all product entries and displays them with either CardSmall or CardWide based on their position.--> <section class="grid grid-cols-1 gap-4 sm:grid-cols-3 md:gap-6 xl:gap-8"> <!-- A clickable card that leads to the details of the pattern--><a href="pattern/fhir-explorer/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-xl shadow-lg outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:h-80"> <!-- The pattern's main image --> <img src="_astro/fhir-explorer-pattern-ss-1.gAtRbOmV_Z1VPBzY.avif" alt="FHIR Explorer" draggable="false" width="927" height="739" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- An overlay gradient that sits on top of the pattern image--> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- The pattern's subtitle and the anchor SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">HL7 FHIR Content Aggregator and Explorer <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg> </span> </a><!-- The anchor tag is the main container for the pattern card. When clicked, this leads to the details of the pattern. --><a href="pattern/content-assembler/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-lg shadow-xl outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:col-span-2 md:h-80"> <!-- The pattern's main image --> <img src="_astro/content-assembler-pattern.BdjZyCUW_Z1VVjrm.avif" alt="Content Assembler Pattern Workflow" draggable="false" width="6325" height="4781" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- This container includes a gradient overlay over the pattern's image --> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- This container includes pattern's subtitle and an SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">Content curation, assembly, and distribution platform <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg></span> </a><!-- The anchor tag is the main container for the pattern card. When clicked, this leads to the details of the pattern. --><a href="pattern/lectio/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-lg shadow-xl outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:col-span-2 md:h-80"> <!-- The pattern's main image --> <img src="_astro/lectio-pattern.g9zmiR7c_XE2Uk.avif" alt="Mockup boxes of a tap bolts and nuts set" draggable="false" width="2412" height="1056" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- This container includes a gradient overlay over the pattern's image --> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- This container includes pattern's subtitle and an SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">Team-based reading assignment and content collaboration solution <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg></span> </a><!-- A clickable card that leads to the details of the pattern--><a href="pattern/osquery/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-xl shadow-lg outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:h-80"> <!-- The pattern's main image --> <img src="_astro/osquery-pattern.CJYgu4S2_ZDP31U.avif" alt="osQuery Integration Pattern" draggable="false" width="1251" height="768" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- An overlay gradient that sits on top of the pattern image--> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- The pattern's subtitle and the anchor SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">Surface surveilr RSSD tables via osQuery <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg> </span> </a><!-- A clickable card that leads to the details of the pattern--><a href="pattern/direct-messaging-service/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-xl shadow-lg outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:h-80"> <!-- The pattern's main image --> <img src="_astro/direct-message-pattern.DGfgjnh7_1BHOKB.avif" alt="Direct Secure Messaging Service" draggable="false" width="1339" height="640" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- An overlay gradient that sits on top of the pattern image--> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- The pattern's subtitle and the anchor SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">Trusted and protected health information exchange is backed by the Direct Standard® <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg> </span> </a><!-- The anchor tag is the main container for the pattern card. When clicked, this leads to the details of the pattern. --><a href="pattern/research-study-explorer/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-lg shadow-xl outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:col-span-2 md:h-80"> <!-- The pattern's main image --> <img src="_astro/research-study-explorer-pattern-ss-3.COiKnkLK_1KbJOM.avif" alt="Diabetes Research Hub Workflow" draggable="false" width="1863" height="639" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- This container includes a gradient overlay over the pattern's image --> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- This container includes pattern's subtitle and an SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">A seamless integration for converting study files and generating metrics, visual insights for diabetes research. <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg></span> </a><!-- The anchor tag is the main container for the pattern card. When clicked, this leads to the details of the pattern. --><a href="pattern/qualityfolio/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-lg shadow-xl outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:col-span-2 md:h-80"> <!-- The pattern's main image --> <img src="_astro/qualityfolio-service.C9b0xh7M_Z1EuDqP.avif" alt="Qualityfolio" draggable="false" width="1881" height="943" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- This container includes a gradient overlay over the pattern's image --> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- This container includes pattern's subtitle and an SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">Unified Test and Quality Management System <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg></span> </a><!-- A clickable card that leads to the details of the pattern--><a href="pattern/compliance-explorer/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-xl shadow-lg outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:h-80"> <!-- The pattern's main image --> <img src="_astro/compliance-explorer-pattern-ss-1.CgPz0X02_Z1uMJDo.avif" alt="Compliance Explorer" draggable="false" width="1255" height="656" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- An overlay gradient that sits on top of the pattern image--> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- The pattern's subtitle and the anchor SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">Web-based user interface that lists and displays SCF controls Aggregator and Explorer <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg> </span> </a><!-- A clickable card that leads to the details of the pattern--><a href="pattern/fleetfolio/index.html" data-astro-prefetch class="group relative flex h-48 items-end overflow-hidden rounded-xl shadow-lg outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none md:h-80"> <!-- The pattern's main image --> <img src="_astro/fleetfolio-screenshot-1.BvMYEE66_ZFm5dn.avif" alt="Fleetfolio" draggable="false" width="997" height="625" loading="lazy" decoding="async" class="absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110"> <!-- An overlay gradient that sits on top of the pattern image--> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-800 via-transparent to-transparent opacity-50"></div> <!-- The pattern's subtitle and the anchor SVG icon--> <span class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg">Continuous Asset and Identity Intelligence for Enhanced Security <svg class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5" height="24" viewBox="0 0 24 24" width="24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" class></path></svg> </span> </a> </section> </div> <section class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <!-- Grid --> <div class="lg:grid lg:grid-cols-12 lg:items-center lg:gap-16"> <div class="lg:col-span-7"> <img src="_astro/features-image-med.ddOnJwCH_23BqUL.webp" alt="Mockup of floating boxes" width="606" height="397" loading="lazy" decoding="async" class="rounded-xl"> </div> <div class="mt-5 sm:mt-10 lg:col-span-5 lg:mt-0"> <div class="space-y-6 sm:space-y-8"> <div class="space-y-2 md:space-y-4"> <h2 class="text-balance text-3xl font-bold text-neutral-800 dark:text-neutral-200 lg:text-4xl"> Why use surveilr patterns? </h2> <p class="text-pretty text-neutral-600 dark:text-neutral-400"> Don't rely on humans for evidence, use surveilr patterns to help acquire, collect, integrate, and query evidence in a secure warehouse. </p> </div> <ul class="space-y-2 sm:space-y-4"> <li class="flex space-x-3"> <svg fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mt-0.5 h-6 w-6 text-orange-400 dark:text-orange-300 flex-none"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg> <span class="text-pretty text-base font-medium text-neutral-600 dark:text-neutral-400"> Robust and reliable solutions that securely run in your environment. </span> </li><li class="flex space-x-3"> <svg fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mt-0.5 h-6 w-6 text-orange-400 dark:text-orange-300 flex-none"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg> <span class="text-pretty text-base font-medium text-neutral-600 dark:text-neutral-400"> Innovative solutions tailored to modern compliance needs. </span> </li><li class="flex space-x-3"> <svg fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mt-0.5 h-6 w-6 text-orange-400 dark:text-orange-300 flex-none"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg> <span class="text-pretty text-base font-medium text-neutral-600 dark:text-neutral-400"> Customer support dedicated to your project's success. </span> </li> </ul> </div> </div> </div> </section> <!-- Main div that wraps the testimonials section --><section class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full" id="testimonials"> <!-- Title of the testimonials section --> <div class="mb-6 w-3/4 max-w-2xl sm:mb-10 md:mb-16 lg:w-1/2"> <h2 class="text-balance text-2xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-3xl lg:text-4xl"> What Our Customers Say </h2> </div> <div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3"> <!-- Looping through each testimonial data and rendering it --> <div class="flex h-auto"> <div class="flex flex-col rounded-xl bg-neutral-50 dark:bg-neutral-700"> <div class="flex-auto p-4 md:p-6"> <!-- Testimonial content --> <p class="text-pretty text-base italic text-neutral-600 dark:text-neutral-300 md:text-lg"> "Since implementing surveilr and its FHIR Explorer Pattern, we’ve drastically reduced the time it takes to audit our healthcare data. The ability to query and explore FHIR files without needing a technical team has been a game-changer for us. We can now ensure compliance and data accuracy with minimal effort." </p> </div> <div class="rounded-b-xl bg-neutral-300/30 p-4 dark:bg-neutral-900/30 md:px-7"> <div class="flex items-center"> <div class="flex-shrink-0"> <img class="size-8 rounded-full sm:h-[2.875rem] sm:w-[2.875rem]" src="https://images.unsplash.com/photo-1544005313-94ddf0286df2?q=80&w=1376&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D8&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80" alt="Image Description" loading="lazy"> </div> <div class="ms-3 grow"> <p class="text-sm font-bold text-neutral-800 dark:text-neutral-200 sm:text-base"> Dr. Emily Harper </p> <p class="text-xs text-neutral-600 dark:text-neutral-400"> Chief Medical Information Officer | Medisync Health Systems </p> </div> </div> </div> </div> </div><div class="flex h-auto"> <div class="flex flex-col rounded-xl bg-neutral-50 dark:bg-neutral-700"> <div class="flex-auto p-4 md:p-6"> <!-- Testimonial content --> <p class="text-pretty text-base italic text-neutral-600 dark:text-neutral-300 md:text-lg"> "As a financial services company, maintaining regulatory compliance across multiple systems was a major challenge. With surveilr, we now have a streamlined solution that provides automated compliance reports, auditable evidence, and real-time insights, all while minimizing our need for IT support." </p> </div> <div class="rounded-b-xl bg-neutral-300/30 p-4 dark:bg-neutral-900/30 md:px-7"> <div class="flex items-center"> <div class="flex-shrink-0"> <img class="size-8 rounded-full sm:h-[2.875rem] sm:w-[2.875rem]" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?q=80&w=1374&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80" alt="Image Description" loading="lazy"> </div> <div class="ms-3 grow"> <p class="text-sm font-bold text-neutral-800 dark:text-neutral-200 sm:text-base"> James Chen </p> <p class="text-xs text-neutral-600 dark:text-neutral-400"> Compliance Director | Argent Financial Solutions </p> </div> </div> </div> </div> </div><div class="flex h-auto"> <div class="flex flex-col rounded-xl bg-neutral-50 dark:bg-neutral-700"> <div class="flex-auto p-4 md:p-6"> <!-- Testimonial content --> <p class="text-pretty text-base italic text-neutral-600 dark:text-neutral-300 md:text-lg"> "Our cybersecurity team has benefited immensely from using surveilr to monitor and audit our security logs. The automatic generation of machine-attestable evidence has not only improved our compliance efforts but also helped us quickly respond to incidents with confidence." </p> </div> <div class="rounded-b-xl bg-neutral-300/30 p-4 dark:bg-neutral-900/30 md:px-7"> <div class="flex items-center"> <div class="flex-shrink-0"> <img class="size-8 rounded-full sm:h-[2.875rem] sm:w-[2.875rem]" src="https://images.unsplash.com/photo-1474176857210-7287d38d27c6?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D8&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80" alt="Image Description" loading="lazy"> </div> <div class="ms-3 grow"> <p class="text-sm font-bold text-neutral-800 dark:text-neutral-200 sm:text-base"> Richard Kim </p> <p class="text-xs text-neutral-600 dark:text-neutral-400"> Chief Information Security Officer | NetSecure Technologies </p> </div> </div> </div> </div> </div> </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="pattern.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 4 2025, 7:58 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 | 79215 | 2025-04-04 10:30:46.830728460 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJEK5R2746C28WVSWS6 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/assets/brand/dms-favicon.ico | - | ico | 15406 | 2025-04-04 08:01:48 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJEZSJ6G0PB40N5W35P | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/assets/brand/linkedin-explorer-favicon.ico | - | ico | 32988 | 2025-04-04 10:10:43 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJEP86ECZX6GDD7SW0S | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/assets/brand/favicon.ico | - | ico | 2258 | 2025-04-04 10:10:42 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJEDDA6JGAZ608W1316 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/assets/brand/fhir-fav.ico | - | ico | 15406 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJEYCTC2TG5TRE28A8G | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/assets/brand/site-quality-favicon.ico | - | ico | 1150 | 2025-04-04 10:10:42 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJENEQ6EWXH7F8NPYP2 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/assets/brand/qf-favicon.ico | - | ico | 15406 | 2025-04-04 08:01:48 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJEB5P3DQ294AAX9BKB | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/assets/brand/scf-favicon.ico | - | ico | 1150 | 2025-04-04 08:01:48 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJE7330MJCMBKGCQQVX | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/blog.html | b7cd345aa830b75eae0af538e75cc6e9f2f159f2 | <!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":"Blog | surveilr","url":"https://www.surveilr.com/blog/","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="blog.html"><link rel="alternate" hreflang="en" href="blog.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/blog/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/blog/"><meta property="og:type" content="website"><meta property="og:title" content="Blog | 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/blog/"><meta name="twitter:title" content="Blog | 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>Blog | 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.C1i_5bqm.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="blog.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="b3dc6dcc-5127-40ad-a177-c8d11cddc8af" data-path-length="1" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="b3dc6dcc-5127-40ad-a177-c8d11cddc8af"> <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="blog.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Blog </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"}}]}</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] space-y-8 px-4 pt-16 sm:px-6 lg:px-8 2xl:max-w-full"> <!--Page header--> <div class="mx-auto max-w-3xl text-left sm:text-center"> <h1 class="block text-balance text-4xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:text-5xl lg:text-6xl"> Stay up-to-date on the latest news and releases </h1> <p class="mt-4 text-pretty text-lg text-neutral-600 dark:text-neutral-400"> Explore the latest news, tips, and insights from surveilr to enhance your security and compliance projects. From pattern spotlights to project management strategies, our blog is your go-to resource. </p> </div> </section> <section class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <!--Blog posts grid--> <div class="grid gap-6 lg:grid-cols-2"> <!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/compliance-explorer/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/sql-for-compliance.R6ct7kQN_ZRbzh2.avif" alt="Harnessing SQL for Compliance" draggable="false" loading="eager" width="1024" height="683" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Ajay Kumaran </h4> <p class="text-xs text-neutral-50/[.8]"> Nov 15, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Harnessing SQL for Compliance: Building a Powerful Compliance Explorer Tool </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> 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. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/content-assembler/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/content-assembler.Bv3C7Riz_Z1ytLij.avif" alt="`surveilr` based data analysis and web UI" draggable="false" loading="eager" width="1024" height="1024" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Geo V L </h4> <p class="text-xs text-neutral-50/[.8]"> Nov 4, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Maximizing Curated Content with Surveilr’s Content Assembler Pattern </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> 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. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/sql-based-etl-elt/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Lightweight ETL" draggable="false" loading="eager" width="1524" height="605" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Shahid N. Shah </h4> <p class="text-xs text-neutral-50/[.8]"> Oct 8, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Modern Lightweight ETL with SQLite </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> Explore how to use SQLite and SQL views for an efficient ELT process, unifying remote patient monitoring data for seamless analysis and reporting. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/direct-messaging-service-pattern/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/secure-health-data-exchange.CLZ3b6ma_1LGAce.avif" alt="Secure health data exchange" draggable="false" loading="eager" width="778" height="500" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Ditty Bijil </h4> <p class="text-xs text-neutral-50/[.8]"> Oct 7, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> How surveilr Transforms Secure Health Data Exchange in Clinical Workflows </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> `surveilr` automates Direct Secure Messaging for HISPs, ensuring regulatory compliance, data integrity, and seamless integration with healthcare IT systems. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/power-of-sql-and-sql-views/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/power-of-sql-and-sql-views.D9V6AARL_26Yjuf.avif" alt="`surveilr` based data analysis and web UI" draggable="false" loading="eager" width="1080" height="650" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Pradeep Narayanan </h4> <p class="text-xs text-neutral-50/[.8]"> Oct 7, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Unlocking surveilr's Full Potential the Smart Way: The Power of SQL and SQL views capabilities </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> Discover how SQL views enhance surveilr's data integration, simplifying complex queries while ensuring security and compliance for regulated sectors. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/surveilr-integration-engine/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/surveilr-integration-engine.D4-bfeLm_Z199LXF.avif" alt="surveilr based integration" draggable="false" loading="eager" width="1080" height="500" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Pradeep Narayanan </h4> <p class="text-xs text-neutral-50/[.8]"> Sep 27, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> surveilr: A Local-First, Edge-based SQL-Centric Integration Engine </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> Discover how surveilr’s local-first, edge-based architecture enhances data integration and compliance for healthcare and regulated sectors. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/vendor-assessments/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/algorithm-infographics-laptop-screen-online-business-1639886-pxhere.com.Vh5Nlz8I_ZkG5rS.avif" alt="Algorithm Infographics" draggable="false" loading="eager" width="5696" height="3856" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Shahid N. Shah </h4> <p class="text-xs text-neutral-50/[.8]"> May 22, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Vendor Assessment and Corporate Compliance Evidence Warehouse </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> Streamline vendor assessments and ensure compliance with surveilr's secure evidence management, protecting sensitive data while verifying policy adherence. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/quality-management-pattern/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/quality-management-pattern.DfE3CvUC_ZwIeYr.avif" alt="Side view worker wearing gloves" draggable="false" loading="eager" width="2131" height="1137" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Shahid N. Shah </h4> <p class="text-xs text-neutral-50/[.8]"> Feb 18, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Quality Management for Safety-Critical Industries </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> `surveilr` ensures compliance in safety-critical industries by streamlining data audits and verifying adherence to quality protocols. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/evidence-based-decision-making-pattern/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <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" loading="eager" width="2400" height="1600" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Shahid N. Shah </h4> <p class="text-xs text-neutral-50/[.8]"> Feb 10, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Evidence-Based Decision Making </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> Surveilr simplifies evidence-based decisions by organizing data into a secure, queryable format, helping executives and analysts make informed choices. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/rssd-excel-portability-sql-power/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/rssd-excel-portability-sql-power.C8PJdDrC_Zm9zzy.avif" alt="RSSD" draggable="false" loading="eager" width="677" height="192" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Shahid N. Shah </h4> <p class="text-xs text-neutral-50/[.8]"> Feb 10, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> RSSDs: Portability of Excel, Power of SQL </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> 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. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/why-stateful-integration/index.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/why-stateful-integration.TtFEGayC_jPkqR.avif" alt="Stateful vs. Stateless" draggable="false" loading="eager" width="1524" height="605" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Shahid N. Shah </h4> <p class="text-xs text-neutral-50/[.8]"> Feb 10, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> Why Stateful Integration? </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> Discover how Surveilr's stateful integration and SQL interface help non-technical teams manage, query, and track data effortlessly while ensuring compliance. </p> </div> </div> </a><!-- The following anchor tag is the main container for the card. It's a link to the blog post detailed page. The data-astro-prefetch is an Astro specific Dynamic HTML feature, which automatically prefetches the linked page to speed up navigation. --><a class="group relative block rounded-xl outline-none ring-zinc-500 transition duration-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none" href="blog/surveilr-core-vs-patterns.html" data-astro-prefetch> <!-- The container for the blog post's cover image. Uses astro:assets' Image for image source --> <div class="relative h-[350px] w-full flex-shrink-0 overflow-hidden rounded-xl before:absolute before:inset-x-0 before:z-[1] before:size-full before:bg-gradient-to-t before:from-neutral-900/[.7]"> <img src="_astro/surveilr-core-vs-patterns-abstract.DrceFwNF_Z1ALO2G.avif" alt="Top view mechanical tools arrangement" draggable="false" loading="eager" width="1024" height="491" decoding="async" class="absolute start-0 top-0 size-full object-cover transition duration-500 group-hover:scale-110"> </div> <!-- The container for the blog author's avatar and associated metadata (author name and publication date) --> <div class="absolute inset-x-0 top-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <div class="flex items-center"> <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-[46px] rounded-full border-2 border-neutral-50"> </div> <div class="ms-2.5 sm:ms-4"> <h4 class="font-bold text-neutral-50"> Shahid N. Shah </h4> <p class="text-xs text-neutral-50/[.8]"> Feb 6, 2024 </p> </div> </div> </div> </div> <!-- The container for the blog post's title and description --> <div class="absolute inset-x-0 bottom-0 z-10"> <div class="flex h-full flex-col p-4 sm:p-6"> <h3 class="text-balance text-lg font-bold text-neutral-50 group-hover:text-neutral-50/[.8] sm:text-3xl"> The surveilr Ecosystem: Core and Patterns </h3> <p class="mt-2 text-pretty text-neutral-50/[.8]"> Discover how Surveilr Core and Patterns enable adaptable, evidence-based workflows for compliance, security, and quality management across industries. </p> </div> </div> </a> </div> </section> <section class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <!-- Root container, which is divided into 2 grid column layout for larger screens --><div class="grid gap-8 sm:grid-cols-2 sm:items-center"> <!-- Container for the blog post's cover image --> <div class="sm:order-2"> <div class="relative rounded-lg pt-[50%] sm:pt-[100%]"> <img src="_astro/research-explorer.CKy9kAYJ_1n6z5o.avif" alt="Diabetes research data exchange" draggable="false" loading="eager" width="1024" height="1024" decoding="async" class="absolute start-0 top-0 size-full rounded-xl object-cover"> </div> </div> <!-- Container for the blog post's heading, author avatar, author's role, and read more button --> <div class="sm:order-1"> <!-- Blog title which is also a hyperlink to the blog detail page --> <h2 class="text-balance text-2xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:text-3xl lg:text-4xl lg:leading-tight xl:text-5xl xl:leading-tight"> <a class="outline-none ring-zinc-500 transition duration-300 hover:text-orange-400 focus-visible:ring dark:text-neutral-300 dark:ring-zinc-200 dark:hover:text-neutral-50 dark:focus:outline-none" href="blog/research-study-explorer-pattern/index.html"> How `surveilr` Transforms Diabetes Research Study Data Management </a> </h2> <!-- Container for the author's avatar and metadata --> <div class="mt-6 flex items-center sm:mt-10"> <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="ms-3 sm:ms-4"> <p class="font-bold text-neutral-800 dark:text-neutral-200 sm:mb-1"> Anitha Varghese </p> <p class="text-xs text-neutral-500"> </p> </div> </div> <!-- Read More button which is a link to the blog post detailed page --> <div 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="blog/research-study-explorer-pattern/index.html"> Read More <!-- 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> </div> </div> </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="blog.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 4 2025, 7:58 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 | 87728 | 2025-04-04 10:30:47.586727624 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJEMGAYECEPF559QQZP | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/lib/pattern/fhir-explorer/package.sql | - | sql | 144069 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJFK6RRZ5QXY9QT8CKJ | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/lib/pattern/osquery/package.sql | - | sql | 3274 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJF8A50SPD87QA7VB8T | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/lib/pattern/research-study-explorer/package.sql | - | sql | 320369 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJF3DHV8DCXV4WKXT25 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/lib/pattern/direct-messaging-service/package.sql | - | sql | 171482 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJF01CZ9PCE9R8NDP1C | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/lib/pattern/compliance-explorer/package.sql | - | sql | 121047 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJFXTGE1NQ2K12FD7HJ | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/lib/service/fleetfolio/package.sql | - | sql | 182470 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJFXG61E3Z08ZPVYYPF | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/lib/service/qualityfolio/package.sql | - | sql | 220267 | 2025-04-04 08:01:48 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJFK4APY4X9QXTKCJBB | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/insights/why-sqlite-for-rssd/index.html | b1f0670ed2418f27445455c73400eba3fc4e90d4 | <!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","inLanguage":"en-US","@id":"https://surveilr.com","url":"https://surveilr.com","name":"surveilr","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","isPartOf":{"@type":"WebSite","url":"https://surveilr.com","name":"surveilr","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence"}}</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/insights/why-sqlite-for-rssd/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/insights/why-sqlite-for-rssd/"><meta property="og:type" content="website"><meta property="og:title" content="Why SQLite for RSSD? | 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/why-sqlite-for-rssd/"><meta name="twitter:title" content="Why SQLite for RSSD? | 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>Why SQLite for RSSD? | 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>: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}#toc li{display:flex;align-items:center;opacity:.8;transition:all .3s var(--transition-cubic);border-bottom:1px solid #d1c8c8;padding-bottom:3px}#toc li.selected{opacity:1}#toc li svg{width:0;height:0;transition:height .4s var(--transition-cubic),width .4s var(--transition-cubic)}#toc li.selected svg{width:1.25rem;height:1.25rem;margin-right:.3rem} .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.C1i_5bqm.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="61e45e31-e11c-4676-a536-f46a2eedaced" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="61e45e31-e11c-4676-a536-f46a2eedaced"> <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="../../insights.html" class="c-breadcrumbs__link" aria-current="false"> Insights </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 Sqlite For Rssd </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"}},{"@type":"ListItem","position":3,"item":{"@id":"/insights/why-sqlite-for-rssd/","name":"Why Sqlite For Rssd"}}]}</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="py-6 sm:py-8 lg:py-12"> <div class="mx-auto max-w-screen-xl px-4 md:px-8"> <div class="grid gap-8 md:grid-cols-12 lg:gap-12"> <!-- Table of Contents --> <div class="md:col-span-3"> <div id="pin" class="space-y-4 hidden md:block"> <div class="h-px w-full overflow-hidden bg-neutral-300 dark:bg-neutral-700"> <div id="progress" class="h-px w-full bg-gradient-to-r from-orange-400/30 to-orange-400"></div> </div> <p class="text-pretty text-sm font-light text-neutral-500 mt-0">Table of Contents:</p> <div id="toc"> <ul class="space-y-2 text-pretty text-base text-neutral-700 transition duration-300 dark:text-neutral-400"> <!-- Your dynamically generated ToC will go here --> </ul> </div> </div> </div> <!-- Main Content --> <div class="md:col-span-9"> <!-- Adjust the height of the image --> <div class="h-48 overflow-hidden rounded-lg shadow-lg md:h-64 lg:h-72"> <img src="../../_astro/sqlite-for-rssd.CE6PRJp4_14Fpbr.avif" alt="SQLite versatility" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div id="progress-mobile" class="fixed left-0 top-0 h-2 w-full bg-gradient-to-r from-orange-400/30 to-orange-400 md:hidden"></div> <div class="md:pt-8"> <h1 class="mb-4 text-balance text-center text-2xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-3xl md:mb-6 md:text-left"> Why SQLite for RSSD? </h1> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>At the heart of RSSD (Resource Surveillance & Integration Engine) is the need for a database that can efficiently handle vast and complex data while maintaining ease of use. For this, we chose SQLite, a powerful yet lightweight SQL engine. SQLite excels in small applications but can also scale up to large-scale use cases—making it the perfect choice for RSSD. Let’s explore why SQLite is ideal for this system.</p> <h3 id="1-the-simplicity-of-an-excel-file">1. <strong>The Simplicity of an Excel File</strong></h3> <p>One of the key reasons we chose SQLite is its simplicity. Like Excel, which is widely known for its ease of use in handling structured data, SQLite can store, manipulate, and analyze data without the need for complex infrastructure. It operates as a self-contained file-based system, meaning no additional software or server setup is required.<br> SQLite databases are portable, acting as standalone files. This characteristic makes them ideal for scenarios where data portability is critical, such as environments that require frequent sharing or auditing of data. The ability to download a SQLite database and open it with standard tools mirrors the ease of working with Excel, but it delivers the powerful querying capabilities of SQL—hence the tagline, <em>“Portability of Excel, Power of SQL.”</em> More on this topic can be found in our detailed <a href="../../blog/rssd-excel-portability-sql-power/index.html">post</a>.</p> <h3 id="2-as-portable-as-a-zip-file">2. <strong>As Portable as a ZIP File</strong></h3> <p>SQLite databases are also as simple to transfer as a ZIP file. With no complicated server dependencies or configuration files, SQLite allows users to create, manipulate, and exchange a database just like any other file. This portability is especially valuable in environments like compliance or cybersecurity, where data may need to be shared across various organizations or devices, securely and quickly.<br> Moreover, the file-based architecture of SQLite removes the need for a separate process to manage the database. Transferring a 10GB SQLite file between teams can be as simple as copying a ZIP file onto a USB drive or securely sharing it through cloud storage—no setup required. In environments like regulatory science or healthcare, where sensitive data frequently moves between systems, this simplicity lowers both operational friction and risks.</p> <h3 id="3-complexity-on-par-with-full-sql-databases">3. <strong>Complexity on Par with Full SQL Databases</strong></h3> <p>Despite its simplicity, SQLite is a full SQL database engine that can handle advanced transactions, joins, indexing, and more. This makes SQLite suitable even for complex data management tasks in environments that involve sophisticated querying, merging, and analysis of large datasets.<br> Unlike traditional relational database systems (e.g., PostgreSQL or MySQL), which often require dedicated infrastructure and extensive setup, SQLite’s design keeps it lightweight while still offering powerful features like atomic transactions, foreign keys, and robust indexing strategies. This balance makes it ideal for systems like RSSD that need both high performance and low overhead, capable of managing millions of records without breaking a sweat. As demonstrated by Wafris’ migration from Redis to SQLite, SQLite is more than capable of handling even high-traffic environments under heavy data load<sup><a href="index.html#user-content-fn-1" id="user-content-fnref-1" data-footnote-ref="" aria-describedby="footnote-label">1</a></sup>.<br> In fact, SQLite has been used in a variety of large-scale applications, including popular web browsers and even aircraft flight software, showing that it’s not limited to small, lightweight applications but can scale efficiently in demanding, high-performance environments.</p> <h3 id="4-merging-data-from-multiple-sources">4. <strong>Merging Data from Multiple Sources</strong></h3> <p>One of the core strengths of RSSD is its ability to merge and integrate data from various sources. Whether the data comes from emails, product lifecycle management tools like GitHub, or structured files such as JSON, Excel, or CSV, SQLite makes it easy to combine all of this content into a single, queryable database.<br> For example, SQLite’s flexible handling of data types and its SQL-centric design allow RSSD to combine data from multiple sources into a standardized format. This is particularly useful for industries like healthcare, where data comes from various standards like HL7, FHIR, or EHR systems.<br> SQLite’s design also allows it to support <em>virtual tables</em>, a feature that extends the database engine’s ability to handle non-relational data sources and integrate them into SQL queries seamlessly. This opens the door for handling data from virtually any source without complex ETL processes.</p> <h3 id="5-scalability-and-performance">5. <strong>Scalability and Performance</strong></h3> <p>Although SQLite is frequently associated with smaller-scale projects, its performance is highly competitive in larger systems as well. It can handle databases up to terabytes in size and manages transactions with high efficiency. One key aspect of SQLite’s scalability lies in its ability to operate without a network layer. For systems deployed in environments with limited or intermittent connectivity, this feature drastically reduces latency compared to traditional client-server models. As a result, SQLite avoids the bottlenecks of network IO, allowing faster data access and operations, which is crucial in high-demand environments such as cybersecurity, where real-time decision-making is vital<sup><a href="index.html#user-content-fn-1" id="user-content-fnref-1-2" data-footnote-ref="" aria-describedby="footnote-label">1</a></sup>.<br> Furthermore, SQLite’s <strong>zero-administration</strong> model makes it ideal for large-scale use cases where database management resources are limited. By operating without a dedicated database administrator (DBA), SQLite removes the need for extensive maintenance, automatic recovery, or tuning, unlike traditional RDBMS setups. This translates into lower operational costs and reduced complexity for organizations that handle substantial amounts of data.</p> <h3 id="6-security-and-data-integrity">6. <strong>Security and Data Integrity</strong></h3> <p>Another critical advantage of SQLite in RSSD is its focus on security. SQLite allows data to be encrypted at the file level, offering an additional layer of security for sensitive information. Furthermore, its transactional integrity ensures that even under crash conditions, data is preserved and remains consistent—essential for sectors like regulatory science or healthcare, where data integrity is paramount.</p> <h3 id="7-a-universal-data-tool-for-evidence-based-decision-making">7. <strong>A Universal Data Tool for Evidence-Based Decision Making</strong></h3> <p>In the end, SQLite offers RSSD a unique combination of simplicity, portability, and performance. By using SQLite, RSSD acts as a <strong>universal data aggregator</strong>, pulling evidence from various systems and ensuring that this data is queryable using SQL-friendly tools. For industries where evidence-based decision-making is critical—like cybersecurity, healthcare, and regulatory science—SQLite provides a unified platform for data storage, analysis, and compliance. Whether it’s merging large datasets or managing complex queries, SQLite’s flexibility ensures that the RSSD system remains both scalable and secure.</p> <h3 id="bibliography">Bibliography</h3> <section data-footnotes="" class="footnotes"><h2 class="sr-only" id="footnote-label">Footnotes</h2> <ol> <li id="user-content-fn-1"> <p>Michael Buckbee, “Rearchitecting: Redis to SQLite,” AuditBoard, published September 2023, 2024, <a href="https://wafris.org/blog/rearchitecting-for-sqlite">https://wafris.org/blog/rearchitecting-for-sqlite</a> <a href="index.html#user-content-fnref-1" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a> <a href="index.html#user-content-fnref-1-2" data-footnote-backref="" aria-label="Back to reference 1-2" class="data-footnote-backref">↩<sup>2</sup></a></p> </li> </ol> </section> </article> </div> </div> </div> </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="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 4 2025, 7:58 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" src="../../_astro/_...slug_.astro_astro_type_script_index_0_lang.CKLJBlmu.js"></script> <script type="module">const l=()=>{const o=document.querySelector("article");if(!o)return;const e=o.offsetHeight,t=o.offsetTop,s=window.scrollY||document.documentElement.scrollTop;if(e&&t&&s){const r=(s-t)/(e-window.innerHeight)*100,n=document.getElementById("progress"),c=document.getElementById("progress-mobile");n&&c&&(n.style.width=`${r}%`,c.style.width=`${r}%`)}};document.addEventListener("DOMContentLoaded",o=>{window.onscroll=l;const e=document.getElementById("progress"),t=document.getElementById("progress-mobile");e&&t&&(e.style.width="0%",t.style.width="0%")});</script> | html | 69279 | 2025-04-04 10:30:46.799728494 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJHS994TGNS2CE958ST | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/insights/advanced-polyglot-orchestration/index.html | c3857982f6d9f37b073c5d47335ee01f7987afc1 | <!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","inLanguage":"en-US","@id":"https://surveilr.com","url":"https://surveilr.com","name":"surveilr","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","isPartOf":{"@type":"WebSite","url":"https://surveilr.com","name":"surveilr","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence"}}</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/insights/advanced-polyglot-orchestration/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/insights/advanced-polyglot-orchestration/"><meta property="og:type" content="website"><meta property="og:title" content="Orchestration with JavaScript and Python | 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/advanced-polyglot-orchestration/"><meta name="twitter:title" content="Orchestration with JavaScript and Python | 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>Orchestration with JavaScript and Python | 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>: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}#toc li{display:flex;align-items:center;opacity:.8;transition:all .3s var(--transition-cubic);border-bottom:1px solid #d1c8c8;padding-bottom:3px}#toc li.selected{opacity:1}#toc li svg{width:0;height:0;transition:height .4s var(--transition-cubic),width .4s var(--transition-cubic)}#toc li.selected svg{width:1.25rem;height:1.25rem;margin-right:.3rem} .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.C1i_5bqm.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="798fd211-6317-4e43-8524-a880d772e35d" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="798fd211-6317-4e43-8524-a880d772e35d"> <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="../../insights.html" class="c-breadcrumbs__link" aria-current="false"> Insights </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"> Advanced Polyglot Orchestration </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"}},{"@type":"ListItem","position":3,"item":{"@id":"/insights/advanced-polyglot-orchestration/","name":"Advanced Polyglot Orchestration"}}]}</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="py-6 sm:py-8 lg:py-12"> <div class="mx-auto max-w-screen-xl px-4 md:px-8"> <div class="grid gap-8 md:grid-cols-12 lg:gap-12"> <!-- Table of Contents --> <div class="md:col-span-3"> <div id="pin" class="space-y-4 hidden md:block"> <div class="h-px w-full overflow-hidden bg-neutral-300 dark:bg-neutral-700"> <div id="progress" class="h-px w-full bg-gradient-to-r from-orange-400/30 to-orange-400"></div> </div> <p class="text-pretty text-sm font-light text-neutral-500 mt-0">Table of Contents:</p> <div id="toc"> <ul class="space-y-2 text-pretty text-base text-neutral-700 transition duration-300 dark:text-neutral-400"> <!-- Your dynamically generated ToC will go here --> </ul> </div> </div> </div> <!-- Main Content --> <div class="md:col-span-9"> <!-- Adjust the height of the image --> <div class="h-48 overflow-hidden rounded-lg shadow-lg md:h-64 lg:h-72"> <img src="../../_astro/advanced-polyglot-orchestration.DUq5BBKY_Z1bhFJh.avif" alt="Lightweight ETL" draggable="false" width="800" height="200" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div id="progress-mobile" class="fixed left-0 top-0 h-2 w-full bg-gradient-to-r from-orange-400/30 to-orange-400 md:hidden"></div> <div class="md:pt-8"> <h1 class="mb-4 text-balance text-center text-2xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-3xl md:mb-6 md:text-left"> Orchestration with JavaScript and Python </h1> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p>The <strong>Resource Surveillance & Integration Engine</strong>, known as <code dir="auto">surveilr</code>, offers extensive built-in capabilities for ingestion, ETL, ELT, and other integration tasks. Many of these tasks can be orchestrated declaratively within <strong>SQL</strong> using the SQLite ecosystem alongside the extension functions and virtual tables provided by <code dir="auto">surveilr</code>. By leveraging the versatility of SQLite, <code dir="auto">surveilr</code> can handle a range of transformations, integrations, and data workflows, all from within the database itself.</p> <p>However, there are scenarios where more complex orchestration is needed—tasks that require imperative programming, advanced logic, or capabilities beyond what <code dir="auto">surveilr</code> provides out of the box. In such cases, languages like <strong>TypeScript</strong> and <strong>JavaScript</strong> (using <strong>Deno</strong> or <strong>NodeJS</strong>), <strong>Python</strong>, and many others that support SQLite integration come to the rescue. The <a href="../../docs/core/concepts/resource-surveillance.html"><strong>Resource Surveillance State Database (RSSD)</strong></a>, which is an opinionated <strong>SQLite</strong> database, provides a strong foundation for multi-modal ingestion and transformation, making it ideal for advanced orchestration using external languages and tools.</p> <p>In this blog post, we will explore advanced orchestration strategies using various languages to complement <code dir="auto">surveilr</code>. We will provide examples from a compliance and evidence-gathering perspective, using <a href="../../docs/core/concepts/uniform-resource.html"><code dir="auto">uniform_resource</code></a> and related tables to demonstrate how to manage resources, track provenance, and execute sophisticated integration workflows. One of the key strengths of the <a href="../../docs/core/concepts/resource-surveillance.html">RSSD</a> format is that it is fully portable across different language ecosystems, which allows developers to use the tools and languages best suited for their specific orchestration needs.</p> <h2 id="orchestration-with-declarative-sql-in-surveilr">Orchestration with Declarative SQL in <code dir="auto">surveilr</code></h2> <p>Before diving into advanced orchestration techniques, it is important to understand the power of <strong>declarative SQL</strong> within <code dir="auto">surveilr</code>. The <a href="../../docs/core/concepts/uniform-resource.html"><strong><code dir="auto">uniform_resource</code></strong></a> table and the constellation of <a href="../../docs/core/concepts/uniform-resource.html#related-tables">related tables</a> provide a robust framework for resource ingestion and metadata tracking. By utilizing SQL and built-in virtual tables, many integration workflows can be managed with ease.</p> <p>For example, consider a compliance use case where a set of <a href="../../docs/core/cli/ingest-commands/files.html">files must be ingested</a>, tracked, and audited:</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">INSERT INTO</span><span style="--0:#D6DEEB;--1:#403F53"> uniform_resource (uniform_resource_id, device_id, ingest_session_id, uri, content_digest, nature, size_bytes, created_at)</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">VALUES</span><span style="--0:#D6DEEB;--1:#403F53"> (</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">UR12345</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">,</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">DEVICE6789</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">,</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">SESSION001</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">,</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">/data/finance/report.pdf</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">,</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">sha256:abcd1234...</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">,</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">document</span><span style="--0:#D9F5DD;--1:#111111">'</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">204800</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">CURRENT_TIMESTAMP</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="INSERT INTO uniform_resource (uniform_resource_id, device_id, ingest_session_id, uri, content_digest, nature, size_bytes, created_at)VALUES ( 'UR12345', 'DEVICE6789', 'SESSION001', '/data/finance/report.pdf', 'sha256:abcd1234...', 'document', 204800, CURRENT_TIMESTAMP);"><div></div></button></div></figure></div> <p>In this example, a new <a href="../../docs/core/concepts/resource/index.html">resource</a> is ingested and registered with all relevant metadata, including <a href="../../docs/standard-library/rssd-schema/device.html"><strong>device</strong></a>, <a href="https://www.surveilr.com/insights/advanced-polyglot-orchestration/docs/standard-library/rssd-schema/ur_ingest_session/"><strong>ingestion session</strong></a>, <strong>content digest</strong> for data integrity, and <strong>URI</strong> for identification. With <code dir="auto">surveilr</code>’s built-in capabilities, this can be automated for bulk ingestion using declarative SQL commands and virtual tables.</p> <h2 id="the-need-for-advanced-orchestration">The Need for Advanced Orchestration</h2> <p>While declarative SQL can handle many integration tasks, there are situations that demand more <strong>complex orchestration</strong>. Examples include:</p> <ul> <li><strong>Conditional Logic and Error Handling</strong>: Declarative SQL can struggle with advanced branching logic or error handling that might be required in some workflows.</li> <li><strong>External API Integrations</strong>: Integrating with third-party services often requires REST API calls, authentication, and handling dynamic response data.</li> <li><strong>Complex Data Transformations</strong>: Some transformations, especially those involving external data sources, may be more suited to procedural programming.</li> <li><strong>Evidence Gathering and Compliance</strong>: In a compliance context, workflows often need dynamic checks, branching, and the ability to communicate with external systems to gather and verify evidence.</li> </ul> <p>In these cases, the power of <strong>imperative programming</strong> becomes essential. This is where languages like <strong>TypeScript</strong>, <strong>JavaScript</strong>, <strong>Python</strong>, and others play a crucial role.</p> <h2 id="typescript-and-javascript-for-orchestration">TypeScript and JavaScript for Orchestration</h2> <p>Languages like TypeScript and JavaScript, running on <strong>Deno</strong> or <strong>NodeJS</strong>, provide rich libraries and tools for advanced orchestration, making them ideal for expanding the capabilities of <code dir="auto">surveilr</code>.</p> <p>Consider a scenario where we want to orchestrate a compliance check for a set of resources ingested into the <a href="../../docs/standard-library/rssd-schema/uniform_resource.html"><strong><code dir="auto">uniform_resource</code></strong></a> table. This compliance check involves verifying that each resource has been properly signed off and validated against an external system.</p> <p>Here is an example using TypeScript and NodeJS:</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:#C792EA;--1:#8844AE">import</span><span style="--0:#D6DEEB;--1:#403F53"> sqlite3 </span><span style="--0:#C792EA;--1:#8844AE">from</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">sqlite3</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">;</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">import</span><span style="--0:#D6DEEB;--1:#403F53"> axios </span><span style="--0:#C792EA;--1:#8844AE">from</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">axios</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">;</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">const </span><span style="--0:#82AAFF;--1:#3B61B0">db</span><span style="--0:#C792EA;--1:#8844AE"> = </span><span style="--0:#7FDBCA;--1:#096E72">new</span><span style="--0:#C792EA;--1:#8844AE"> </span><span style="--0:#D6DEEB;--1:#403F53">sqlite3</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#82AAFF;--1:#3B61B0">Database</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">rssd.db</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">);</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5D6376">// Fetch all resources that need compliance verification</span></div></div><div class="ec-line"><div class="code"><span style="--0:#D6DEEB;--1:#403F53">db</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#82AAFF;--1:#3B61B0">all</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#ECC48D;--1:#3B61B0">SELECT uniform_resource_id, uri, content_digest FROM uniform_resource WHERE nature = 'document' AND verified IS NULL</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#D6DEEB;--1:#403F53">, </span><span style="--0:#C792EA;--1:#8844AE">async</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#D9F5DD;--1:#111111">(</span><span style="--1:#403F53"><span style="--0:#D7DBE0">err</span><span style="--0:#D6DEEB">, </span><span style="--0:#D7DBE0">rows</span></span><span style="--0:#D9F5DD;--1:#111111">)</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#C792EA;--1:#8844AE">=></span><span style="--0:#D6DEEB;--1:#403F53"> {</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">if</span><span style="--0:#D6DEEB;--1:#403F53"> (err) </span><span style="--0:#C792EA;--1:#8844AE">throw</span><span style="--0:#D6DEEB;--1:#403F53"> err;</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">for</span><span style="--0:#D6DEEB;--1:#403F53"> (</span><span style="--0:#C792EA;--1:#8844AE">const </span><span style="--0:#82AAFF;--1:#3B61B0">row</span><span style="--0:#C792EA;--1:#8844AE"> </span><span style="--0:#7FDBCA;--1:#096E72">of</span><span style="--0:#D6DEEB;--1:#403F53"> rows) {</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">try</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">// Simulate an external API call to verify the resource</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">const </span><span style="--0:#82AAFF;--1:#3B61B0">response</span><span style="--0:#C792EA;--1:#8844AE"> = await </span><span style="--0:#D6DEEB;--1:#403F53">axios</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#82AAFF;--1:#3B61B0">post</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">https://compliance-check.example.com/verify</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#C792EA;--1:#8844AE">, {</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#C792EA;--1:#8844AE"> </span></span><span style="--0:#C792EA;--1:#8844AE">uri: </span><span style="--0:#D6DEEB;--1:#403F53">row</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#7FDBCA;--1:#096E72">uri</span><span style="--0:#C792EA;--1:#8844AE">,</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#C792EA;--1:#8844AE"> </span></span><span style="--0:#C792EA;--1:#8844AE">digest: </span><span style="--0:#D6DEEB;--1:#403F53">row</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#7FDBCA;--1:#096E72">content_digest</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#C792EA;--1:#8844AE"> </span></span><span style="--0:#C792EA;--1:#8844AE">}</span><span style="--0:#D6DEEB;--1:#403F53">);</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">if</span><span style="--0:#D6DEEB;--1:#403F53"> (response</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#FAF39F;--1:#111111">data</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#7FDBCA;--1:#096E72">verified</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">db</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#82AAFF;--1:#3B61B0">run</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#ECC48D;--1:#3B61B0">UPDATE uniform_resource SET verified = 1 WHERE uniform_resource_id = ?</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#D6DEEB;--1:#403F53">, row</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#7FDBCA;--1:#096E72">uniform_resource_id</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">console</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#82AAFF;--1:#3B61B0">log</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#ECC48D;--1:#3B61B0">Resource </span><span style="--0:#E2817F;--1:#B23834">${</span><span style="--0:#D6DEEB;--1:#403F53">row</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#7FDBCA;--1:#096E72">uniform_resource_id</span><span style="--0:#E2817F;--1:#B23834">}</span><span style="--0:#ECC48D;--1:#3B61B0"> verified successfully.</span><span style="--0:#D6DEEB;--1:#403F53">`</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">} </span><span style="--0:#C792EA;--1:#8844AE">else</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">console</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#82AAFF;--1:#3B61B0">error</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#ECC48D;--1:#3B61B0">Verification failed for resource </span><span style="--0:#E2817F;--1:#B23834">${</span><span style="--0:#D6DEEB;--1:#403F53">row</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#7FDBCA;--1:#096E72">uniform_resource_id</span><span style="--0:#E2817F;--1:#B23834">}</span><span style="--0:#D6DEEB;--1:#403F53">`</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">}</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">} </span><span style="--0:#C792EA;--1:#8844AE">catch</span><span style="--0:#D6DEEB;--1:#403F53"> (apiError) {</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">console</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#82AAFF;--1:#3B61B0">error</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#ECC48D;--1:#3B61B0">Error verifying resource </span><span style="--0:#E2817F;--1:#B23834">${</span><span style="--0:#D6DEEB;--1:#403F53">row</span><span style="--0:#C792EA;--1:#8844AE">.</span><span style="--0:#7FDBCA;--1:#096E72">uniform_resource_id</span><span style="--0:#E2817F;--1:#B23834">}</span><span style="--0:#ECC48D;--1:#3B61B0">:</span><span style="--0:#D6DEEB;--1:#403F53">`</span><span style="--0:#D6DEEB;--1:#403F53">, apiError);</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">}</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">}</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="import sqlite3 from 'sqlite3';import axios from 'axios';const db = new sqlite3.Database('rssd.db');// Fetch all resources that need compliance verificationdb.all(`SELECT uniform_resource_id, uri, content_digest FROM uniform_resource WHERE nature = 'document' AND verified IS NULL`, async (err, rows) => { if (err) throw err; for (const row of rows) { try { // Simulate an external API call to verify the resource const response = await axios.post('https://compliance-check.example.com/verify', { uri: row.uri, digest: row.content_digest }); if (response.data.verified) { db.run(`UPDATE uniform_resource SET verified = 1 WHERE uniform_resource_id = ?`, row.uniform_resource_id); console.log(`Resource ${row.uniform_resource_id} verified successfully.`); } else { console.error(`Verification failed for resource ${row.uniform_resource_id}`); } } catch (apiError) { console.error(`Error verifying resource ${row.uniform_resource_id}:`, apiError); } }});"><div></div></button></div></figure></div> <p>In this example, we are using TypeScript to orchestrate a <strong>verification workflow</strong> that involves an external compliance API. Each resource is verified, and the <a href="../../docs/standard-library/rssd-schema/uniform_resource.html"><strong><code dir="auto">uniform_resource</code></strong></a> table is updated accordingly. The combination of <strong>NodeJS</strong> for asynchronous operations and <strong>SQLite</strong> for data persistence makes this type of orchestration both powerful and flexible.</p> <h2 id="python-for-advanced-integration-workflows">Python for Advanced Integration Workflows</h2> <p><strong>Python</strong> is another great choice for advanced orchestration, particularly due to its extensive ecosystem of libraries for data processing, compliance, and orchestration. Python’s <strong>sqlite3</strong> module allows seamless interaction with the <a href="../../docs/core/concepts/resource-surveillance.html">RSSD</a> database, and its rich set of packages like <strong>requests</strong> and <strong>pandas</strong> allows for powerful data integration capabilities.</p> <p>Consider a scenario where we need to orchestrate an <strong>ETL process</strong> that reads resource data, transforms it, and exports it for further analysis. Here’s an example using Python:</p> <div class="expressive-code"><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="python"><code><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">import</span><span style="--0:#D6DEEB;--1:#403F53"> sqlite3</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">import</span><span style="--0:#D6DEEB;--1:#403F53"> requests</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">import</span><span style="--0:#D6DEEB;--1:#403F53"> pandas </span><span style="--0:#C792EA;--1:#8844AE">as</span><span style="--0:#D6DEEB;--1:#403F53"> pd</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5F636F"># Connect to the RSSD SQLite database</span></div></div><div class="ec-line"><div class="code"><span style="--0:#D6DEEB;--1:#403F53">db_connection </span><span style="--0:#C792EA;--1:#8844AE">=</span><span style="--0:#D6DEEB;--1:#403F53"> sqlite3.</span><span style="--0:#B2CCD6;--1:#096E72">connect</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">rssd.db</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">)</span></div></div><div class="ec-line"><div class="code"><span style="--0:#D6DEEB;--1:#403F53">cursor </span><span style="--0:#C792EA;--1:#8844AE">=</span><span style="--0:#D6DEEB;--1:#403F53"> db_connection.</span><span style="--0:#B2CCD6;--1:#096E72">cursor</span><span style="--0:#D6DEEB;--1:#403F53">()</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5F636F"># Extract resources that need transformation</span></div></div><div class="ec-line"><div class="code"><span style="--0:#D6DEEB;--1:#403F53">cursor.</span><span style="--0:#B2CCD6;--1:#096E72">execute</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#ECC48D;--1:#984E4D">SELECT uniform_resource_id, uri, content FROM uniform_resource WHERE nature = 'log' AND transformed IS NULL</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#D6DEEB;--1:#403F53">)</span></div></div><div class="ec-line"><div class="code"><span style="--0:#D6DEEB;--1:#403F53">resources </span><span style="--0:#C792EA;--1:#8844AE">=</span><span style="--0:#D6DEEB;--1:#403F53"> cursor.</span><span style="--0:#B2CCD6;--1:#096E72">fetchall</span><span style="--0:#D6DEEB;--1:#403F53">()</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5F636F"># Transform each resource and send to external compliance system</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C792EA;--1:#8844AE">for</span><span style="--0:#D6DEEB;--1:#403F53"> resource </span><span style="--0:#C792EA;--1:#8844AE">in</span><span style="--0:#D6DEEB;--1:#403F53"> resources:</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">resource_id, uri, content </span><span style="--0:#C792EA;--1:#8844AE">=</span><span style="--0:#D6DEEB;--1:#403F53"> resource</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#919F9F;--1:#5F636F"># Perform some transformation</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">transformed_content </span><span style="--0:#C792EA;--1:#8844AE">=</span><span style="--0:#D6DEEB;--1:#403F53"> content.</span><span style="--0:#B2CCD6;--1:#096E72">decode</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">utf-8</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D6DEEB;--1:#403F53">).</span><span style="--0:#B2CCD6;--1:#096E72">upper</span><span style="--0:#D6DEEB;--1:#403F53">() </span><span style="--0:#919F9F;--1:#5F636F"># Example transformation: converting to uppercase</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#919F9F;--1:#5F636F"># Send the transformed content to an external system</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">response </span><span style="--0:#C792EA;--1:#8844AE">=</span><span style="--0:#D6DEEB;--1:#403F53"> requests.</span><span style="--0:#B2CCD6;--1:#096E72">post</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">https://api.external-system.com/ingest</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#D9F5DD;--1:#111111">,</span><span style="--0:#82AAFF;--1:#3B61B0"> </span><span style="--0:#D7DBE0;--1:#403F53">json</span><span style="--0:#C792EA;--1:#8844AE">=</span><span style="--0:#82AAFF;--1:#3B61B0">{</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">uri</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#82AAFF;--1:#3B61B0">: uri, </span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#ECC48D;--1:#984E4D">content</span><span style="--0:#D9F5DD;--1:#111111">'</span><span style="--0:#82AAFF;--1:#3B61B0">: transformed_content}</span><span style="--0:#D6DEEB;--1:#403F53">)</span></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C792EA;--1:#8844AE">if</span><span style="--0:#D6DEEB;--1:#403F53"> response.status_code </span><span style="--0:#C792EA;--1:#8844AE">==</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#F78C6C;--1:#AA0982">200</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:#5F636F"># Update the resource as transformed</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">cursor.</span><span style="--0:#B2CCD6;--1:#096E72">execute</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#ECC48D;--1:#984E4D">UPDATE uniform_resource SET transformed = 1 WHERE uniform_resource_id = ?</span><span style="--0:#D9F5DD;--1:#111111">"</span><span style="--0:#D9F5DD;--1:#111111">,</span><span style="--0:#82AAFF;--1:#3B61B0"> (resource_id,)</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">db_connection.</span><span style="--0:#B2CCD6;--1:#096E72">commit</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">print</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#C792EA;--1:#8844AE">f</span><span style="--0:#ECC48D;--1:#984E4D">"Resource </span><span style="--0:#82AAFF;--1:#3B61B0">{resource_id}</span><span style="--0:#ECC48D;--1:#984E4D"> transformed and ingested successfully."</span><span style="--0:#D6DEEB;--1:#403F53">)</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></div></div><div class="ec-line"><div class="code"><span class="indent"> </span><span style="--0:#C5E478;--1:#3B61B0">print</span><span style="--0:#D6DEEB;--1:#403F53">(</span><span style="--0:#C792EA;--1:#8844AE">f</span><span style="--0:#ECC48D;--1:#984E4D">"Failed to ingest transformed content for resource </span><span style="--0:#82AAFF;--1:#3B61B0">{resource_id}</span><span style="--0:#ECC48D;--1:#984E4D">."</span><span style="--0:#D6DEEB;--1:#403F53">)</span></div></div><div class="ec-line"><div class="code"> </div></div><div class="ec-line"><div class="code"><span style="--0:#919F9F;--1:#5F636F"># Close the connection</span></div></div><div class="ec-line"><div class="code"><span style="--0:#D6DEEB;--1:#403F53">db_connection.</span><span style="--0:#B2CCD6;--1:#096E72">close</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="import sqlite3import requestsimport pandas as pd# Connect to the RSSD SQLite databasedb_connection = sqlite3.connect('rssd.db')cursor = db_connection.cursor()# Extract resources that need transformationcursor.execute("SELECT uniform_resource_id, uri, content FROM uniform_resource WHERE nature = 'log' AND transformed IS NULL")resources = cursor.fetchall()# Transform each resource and send to external compliance systemfor resource in resources: resource_id, uri, content = resource # Perform some transformation transformed_content = content.decode('utf-8').upper() # Example transformation: converting to uppercase # Send the transformed content to an external system response = requests.post('https://api.external-system.com/ingest', json={'uri': uri, 'content': transformed_content}) if response.status_code == 200: # Update the resource as transformed cursor.execute("UPDATE uniform_resource SET transformed = 1 WHERE uniform_resource_id = ?", (resource_id,)) db_connection.commit() print(f"Resource {resource_id} transformed and ingested successfully.") else: print(f"Failed to ingest transformed content for resource {resource_id}.")# Close the connectiondb_connection.close()"><div></div></button></div></figure></div> <p>In this Python script, we extract logs from the <a href="../../docs/standard-library/rssd-schema/uniform_resource.html"><strong><code dir="auto">uniform_resource</code></strong></a> table, perform a transformation, and send the transformed content to an external system for further processing. Python’s versatility and simplicity make it an excellent choice for such ETL tasks, especially when combined with <strong>SQLite</strong> for local persistence.</p> <h2 id="multi-language-integration-for-compliance-and-evidence-gathering">Multi-Language Integration for Compliance and Evidence Gathering</h2> <p>When dealing with compliance and evidence gathering, there is often a need to combine different tools and languages to meet complex requirements. The <a href="../../docs/core/concepts/resource-surveillance.html"><strong>RSSD</strong></a> format, being an SQLite database, makes this integration seamless across ecosystems.</p> <p>For instance, an <strong>evidence-gathering workflow</strong> could start with data ingestion using SQL and <code dir="auto">surveilr</code>, followed by resource transformation and validation using <strong>Python</strong>, and finally, advanced reporting and data visualization using <strong>JavaScript</strong> with frameworks like <strong>D3.js</strong> or <strong>Chart.js</strong>.</p> <p>Consider the following scenario:</p> <ul> <li><strong>Ingestion and Tracking</strong>: Use <code dir="auto">surveilr</code> to ingest documents into the <a href="../../docs/standard-library/rssd-schema/uniform_resource.html"><code dir="auto">uniform_resource</code></a> table, capturing metadata like the <a href="https://www.surveilr.com/insights/advanced-polyglot-orchestration/docs/standard-library/rssd-schema/ur_ingest_session/">ingestion session</a>, <a href="../../docs/standard-library/rssd-schema/device.html">device</a>, and content hash for integrity.</li> <li><strong>Validation with Python</strong>: Validate document signatures against a compliance database using Python scripts, updating the <a href="../../docs/core/concepts/resource-surveillance.html">RSSD</a> database with the results.</li> <li><strong>Advanced Reporting</strong>: Use a JavaScript-based web application to generate compliance reports, visualizing resource status from the <a href="../../docs/core/concepts/resource-surveillance.html"><code dir="auto">uniform_resource</code></a> table using D3.js for an intuitive graphical representation.</li> </ul> <p>This <strong>multi-language approach</strong> allows you to leverage the strengths of each language, providing a highly flexible and scalable solution for orchestration in compliance and cybersecurity environments.</p> <h2 id="conclusion">Conclusion</h2> <p>The <strong>Resource Surveillance & Integration Engine (<code dir="auto">surveilr</code>)</strong> is powerful on its own, allowing you to orchestrate many tasks using declarative SQL and built-in SQLite extensions. However, advanced orchestration often requires additional capabilities—complex logic, integrations, or transformations that benefit from imperative programming.</p> <p>With the <a href="../../docs/core/concepts/resource-surveillance.html"><strong>Resource Surveillance State Database (RSSD)</strong></a> format being fully portable across different language ecosystems, you can choose the right language and tool for the job, whether it’s <strong>TypeScript</strong> for API orchestration, <strong>Python</strong> for data transformation, or <strong>JavaScript</strong> for visualization and reporting.</p> <p>The <a href="../../docs/standard-library/rssd-schema/uniform_resource.html"><strong><code dir="auto">uniform_resource</code></strong></a> table, with its constellation of related tables, forms the core of resource management, compliance, and evidence tracking. Using languages like <strong>TypeScript</strong>, <strong>JavaScript</strong>, <strong>Python</strong>, and others to orchestrate workflows around <a href="../../docs/core/concepts/resource-surveillance.html">RSSD</a> databases can empower you to handle even the most complex compliance and integration challenges.</p> <p>Do you have use cases that require advanced orchestration? We’d love to hear how you integrate <strong><code dir="auto">surveilr</code></strong> with your favorite programming languages to create powerful, compliance-focused workflows.</p> </article> </div> </div> </div> </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="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 4 2025, 7:58 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" src="../../_astro/_...slug_.astro_astro_type_script_index_0_lang.CKLJBlmu.js"></script> <script type="module">const l=()=>{const o=document.querySelector("article");if(!o)return;const e=o.offsetHeight,t=o.offsetTop,s=window.scrollY||document.documentElement.scrollTop;if(e&&t&&s){const r=(s-t)/(e-window.innerHeight)*100,n=document.getElementById("progress"),c=document.getElementById("progress-mobile");n&&c&&(n.style.width=`${r}%`,c.style.width=`${r}%`)}};document.addEventListener("DOMContentLoaded",o=>{window.onscroll=l;const e=document.getElementById("progress"),t=document.getElementById("progress-mobile");e&&t&&(e.style.width="0%",t.style.width="0%")});</script> | html | 98303 | 2025-04-04 10:30:47.779727411 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJHJ1GPJ6AYYWSCBE9T | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/insights/compliance-explorer/index.html | 589e9d8b903029e7c5c55709c85d03037be88314 | <!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","inLanguage":"en-US","@id":"https://surveilr.com","url":"https://surveilr.com","name":"surveilr","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence","isPartOf":{"@type":"WebSite","url":"https://surveilr.com","name":"surveilr","description":"Prove Security, Quality, and Compliance with Auditable, Queryable, and Machine-Attestable Evidence"}}</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/insights/compliance-explorer/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/insights/compliance-explorer/"><meta property="og:type" content="website"><meta property="og:title" content="Surveilr Compliance Explorer Pattern – Streamlining Compliance with SQL Scripts | 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/compliance-explorer/"><meta name="twitter:title" content="Surveilr Compliance Explorer Pattern – Streamlining Compliance with SQL Scripts | 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>Surveilr Compliance Explorer Pattern – Streamlining Compliance with SQL Scripts | 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>: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}#toc li{display:flex;align-items:center;opacity:.8;transition:all .3s var(--transition-cubic);border-bottom:1px solid #d1c8c8;padding-bottom:3px}#toc li.selected{opacity:1}#toc li svg{width:0;height:0;transition:height .4s var(--transition-cubic),width .4s var(--transition-cubic)}#toc li.selected svg{width:1.25rem;height:1.25rem;margin-right:.3rem} .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.C1i_5bqm.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="a380010d-f8db-42e6-8fed-54b6a8762f02" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="a380010d-f8db-42e6-8fed-54b6a8762f02"> <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="../../insights.html" class="c-breadcrumbs__link" aria-current="false"> Insights </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":"/insights/","name":"Insights"}},{"@type":"ListItem","position":3,"item":{"@id":"/insights/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="py-6 sm:py-8 lg:py-12"> <div class="mx-auto max-w-screen-xl px-4 md:px-8"> <div class="grid gap-8 md:grid-cols-12 lg:gap-12"> <!-- Table of Contents --> <div class="md:col-span-3"> <div id="pin" class="space-y-4 hidden md:block"> <div class="h-px w-full overflow-hidden bg-neutral-300 dark:bg-neutral-700"> <div id="progress" class="h-px w-full bg-gradient-to-r from-orange-400/30 to-orange-400"></div> </div> <p class="text-pretty text-sm font-light text-neutral-500 mt-0">Table of Contents:</p> <div id="toc"> <ul class="space-y-2 text-pretty text-base text-neutral-700 transition duration-300 dark:text-neutral-400"> <!-- Your dynamically generated ToC will go here --> </ul> </div> </div> </div> <!-- Main Content --> <div class="md:col-span-9"> <!-- Adjust the height of the image --> <div class="h-48 overflow-hidden rounded-lg shadow-lg md:h-64 lg:h-72"> <img src="../../_astro/compliance-explorer-pattern.2o85tCgk_uOTMq.avif" alt="Compliance Explorer" draggable="false" width="1024" height="1024" loading="lazy" decoding="async" class="h-full w-full object-cover object-center"> </div> <div id="progress-mobile" class="fixed left-0 top-0 h-2 w-full bg-gradient-to-r from-orange-400/30 to-orange-400 md:hidden"></div> <div class="md:pt-8"> <h1 class="mb-4 text-balance text-center text-2xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-3xl md:mb-6 md:text-left"> Surveilr Compliance Explorer Pattern – Streamlining Compliance with SQL Scripts </h1> <article class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"> <p><strong>Surveilr Compliance Explorer Pattern – Streamlining Compliance with SQL Scripts</strong></p> <p>The Surveilr Compliance Explorer Pattern is an innovative solution for organizations managing information controls, which are essential security, compliance, and operational measures aimed at reducing risk in information systems and data handling. Designed with flexibility in mind, this pattern leverages SQL scripts to help users extract, present, and cache compliance data effectively. Here’s how it works and how you can get started.</p> <h3 id="key-components-of-the-surveilr-compliance-explorer-pattern">Key Components of the Surveilr Compliance Explorer Pattern</h3> <ol> <li> <p><strong>Stateless SQL Script (<code dir="auto">stateless.sql</code>):</strong> This script is designed to create database views that define how control data is extracted from structured files like <code dir="auto">uniform_resource.csv</code>. These views make it easy to retrieve and display specific compliance data on demand without needing to re-ingest the data each time.</p> </li> <li> <p><strong>Stateful SQL Script (<code dir="auto">stateful.sql</code>):</strong> For users who need to cache data for quicker access, the <code dir="auto">stateful.sql</code> script creates tables that store data extracted by the views. This approach allows compliance and audit teams to access the latest data without running the same extractions repeatedly.</p> </li> <li> <p><strong>Package SQL Script (<code dir="auto">package.sql.ts</code>):</strong> Acting as the primary entry point, this script loads necessary database objects and Web UI content, providing users with a simplified experience in managing and visualizing data. This central script is crucial for setting up the user interface and accessing the Surveilr database.</p> </li> </ol> <h3 id="how-to-use-the-compliance-explorer-pattern">How to Use the Compliance Explorer Pattern</h3> <p>Surveilr’s flexibility extends to a variety of platforms, so you can run this pattern on almost any device without needing the Surveilr repository itself. Here’s a step-by-step guide to getting started:</p> <ol> <li> <p><strong>Prepare a Working Directory:</strong> First, set up a folder for your compliance data:</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 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">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</span></div></div><div class="ec-line"><div class="code"><span style="--0:#C5E478;--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-explorercd /tmp/compliance-explorer"><div></div></button></div></figure></div> </li> <li> <p><strong>Prepare Control Files:</strong> Place control data CSV files (e.g., <code dir="auto">SCF_2024.2.csv</code>) in an <code dir="auto">ingest</code> folder inside your directory:</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">compliance-explorer</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">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">├──</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">SCF_2024.2.csv</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">package.sql.ts</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">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> </li> <li> <p><strong>Download and Ingest Data with Surveilr:</strong> Download the Surveilr binary to your working directory and use it to ingest the control files, creating an SQLite database (<code dir="auto">resource-surveillance.sqlite.db</code>) that serves as your compliance repository:</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">./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 folder will look like this:</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">compliance-explorer</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">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">├──</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#ECC48D;--1:#3B61B0">SCF_2024.2.csv</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">package.sql.ts</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">stateless.sql</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">resource-surveillance.sqlite.db</span><span style="--0:#D6DEEB;--1:#403F53"> </span><span style="--0:#919F9F;--1:#5F636F"># SQLite database</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 # SQLite database"><div></div></button></div></figure></div> </li> <li> <p><strong>Query and Visualize Data:</strong> Once data is ingested, Surveilr is no longer required. Use standard tools like <code dir="auto">sqlite3</code>, DBeaver, or DataGrip to access your compliance data from the <code dir="auto">resource-surveillance.sqlite.db</code> database. You can also load the Surveilr Web UI for a richer interface:</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">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></code></pre><div class="copy"><button title="Copy to clipboard" data-copied="Copied!" data-code="deno run -A ./package.sql.ts | surveilr shell"><div></div></button></div></figure></div> </li> <li> <p><strong>Accessing the Web UI:</strong> Start the Surveilr web UI to view compliance 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:#C5E478;--1:#3B61B0">.</span><span style="--0:#ECC48D;--1:#3B61B0">./</span><span style="--0:#C5E478;--1:#3B61B0">.</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>Visit <code dir="auto">http://localhost:9000/</code> to browse the UI or access the specific schema for data management services (DMS) at <code dir="auto">http://localhost:9000/dms/info-schema.sql</code>.</p> </li> </ol> <h3 id="compliance-explorers-advantage">Compliance Explorer’s Advantage</h3> <p>The Surveilr Compliance Explorer Pattern streamlines compliance workflows with reusable SQL scripts for data extraction and caching, enabling organizations to:</p> <ul> <li><strong>Centralize Compliance Data:</strong> Store and organize compliance information in a single, easily accessible SQLite database.</li> <li><strong>Simplify Data Management:</strong> Run one-time ingestions and visualize data in real time without needing to repeat complex extraction processes.</li> <li><strong>Enhance Flexibility:</strong> Use SQL queries to generate views or reports on-demand, facilitating quick compliance checks, audits, and updates.</li> </ul> <p>This pattern empowers teams to effectively manage compliance requirements and reduces the complexity of regulatory data handling, offering a seamless, accessible solution across varied operational environments.</p> </article> </div> </div> </div> </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="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 4 2025, 7:58 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" src="../../_astro/_...slug_.astro_astro_type_script_index_0_lang.CKLJBlmu.js"></script> <script type="module">const l=()=>{const o=document.querySelector("article");if(!o)return;const e=o.offsetHeight,t=o.offsetTop,s=window.scrollY||document.documentElement.scrollTop;if(e&&t&&s){const r=(s-t)/(e-window.innerHeight)*100,n=document.getElementById("progress"),c=document.getElementById("progress-mobile");n&&c&&(n.style.width=`${r}%`,c.style.width=`${r}%`)}};document.addEventListener("DOMContentLoaded",o=>{window.onscroll=l;const e=document.getElementById("progress"),t=document.getElementById("progress-mobile");e&&t&&(e.style.width="0%",t.style.width="0%")});</script> | html | 72889 | 2025-04-04 10:30:47.782727408 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJHXAGJAW5YR5J6PVCP | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/contact.html | 06634cb522ad94f9d659fdf0c94d49635b325871 | <!DOCTYPE html><!--Utilizing MainLayout for the outer layout of the page, and defining meta for SEO purposes--><!-- 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":"Contact | surveilr","url":"https://www.surveilr.com/contact/","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="contact.html"><link rel="alternate" hreflang="en" href="contact.html" /> <link rel="alternate" hreflang="fr" href="https://www.surveilr.com/fr/contact/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/contact/"><meta property="og:type" content="website"><meta property="og:title" content="Contact | 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/contact/"><meta name="twitter:title" content="Contact | 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>Contact | 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.C1i_5bqm.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="contact.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="8e0c5e5e-d975-4915-b7d9-53471ef2da7b" data-path-length="1" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="8e0c5e5e-d975-4915-b7d9-53471ef2da7b"> <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="contact.html" aria-disabled="true" class="c-breadcrumbs__link is-current" aria-current="location"> Contact </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":"/contact/","name":"Contact"}}]}</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"> <!-- Contact Us --><section class="mx-auto max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14"> <div class="mx-auto max-w-2xl lg:max-w-5xl"> <div class="text-center"> <h1 class="text-balance text-2xl font-bold tracking-tight text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"> Contact us </h1> <p class="mt-1 text-pretty text-neutral-600 dark:text-neutral-400"> Have questions or want to discuss a project? Reach out, and let's craft the perfect solution with our tools and services. </p> </div> <div class="mt-12 grid items-center gap-6 lg:grid-cols-2 lg:gap-16"> <div class="flex flex-col rounded-xl p-4 sm:p-6 lg:p-8"> <h2 class="mb-8 text-xl font-bold text-neutral-700 dark:text-neutral-300"> Fill in the form below </h2> <!-- Form for user input with various input fields.--> <!-- Each field utilizes a different input component for the specific type of input (text, email, phone, and textarea)--> <form> <div class="grid gap-4"> <div class="grid grid-cols-1 gap-4 sm:grid-cols-2"> <div> <label for="hs-firstname-contacts" class="sr-only">First Name</label> <input type="text" name="hs-firstname-contacts" id="hs-firstname-contacts" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 placeholder:text-neutral-500 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:placeholder:text-neutral-400 dark:focus:ring-1" placeholder="First Name"> </div> <div> <label for="hs-lastname-contacts" class="sr-only">Last Name</label> <input type="text" name="hs-firstname-contacts" id="hs-lastname-contacts" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 placeholder:text-neutral-500 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:placeholder:text-neutral-400 dark:focus:ring-1" placeholder="Last Name"> </div> </div> <!-- Container for the label and email input field --><div> <!-- Label for the email input field, visually hidden but accessible to screen readers --> <label for="hs-email-contacts" class="sr-only">Email</label> <!-- Email input field --> <input type="email" name="hs-email-contacts" id="hs-email-contacts" autocomplete="email" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 placeholder:text-neutral-500 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:placeholder:text-neutral-400 dark:focus:ring-1" placeholder="Email"> </div> <div> <label for="hs-phone-number" class="sr-only">Phone Number</label> <input type="tel" name="hs-phone-number" id="hs-phone-number" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 placeholder:text-neutral-500 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:placeholder:text-neutral-400 dark:focus:ring-1" placeholder="Phone Number"> </div> <div> <label for="hs-about-contacts" class="sr-only">Details</label> <textarea id="hs-about-contacts" name="hs-about-contacts" rows="4" class="block w-full rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 text-sm text-neutral-700 placeholder:text-neutral-500 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:placeholder:text-neutral-400 dark:focus:ring-1" placeholder="Details"></textarea> </div> </div> <div class="mt-4 grid"> <!-- 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">Send Message</button> </div> <div class="mt-3 text-center"> <p class="text-sm text-neutral-600 dark:text-neutral-400"> We'll get back to you in 1-2 business days. </p> </div> </form> </div> <!--ContactIconBlocks are used to display different methods of contacting, including visiting office, email, browsing knowledgebase, and FAQ.--> <div class="divide-y divide-neutral-300 dark:divide-neutral-700"> <!-- Root container, which arranges the heading and content --><div class="flex gap-x-7 py-6"> <!-- Slot to allow for extensibility of the component --> <svg class="mt-1.5 h-6 w-6 flex-shrink-0 text-neutral-600 dark:text-neutral-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" class></path></svg> <div class="grow"> <!-- Heading of the section --> <h3 class="font-bold text-neutral-700 dark:text-neutral-300"> Knowledgebase </h3> <!-- Content of the section --> <p class="mt-1 text-sm text-neutral-600 dark:text-neutral-400">Browse through all of our knowledgebase articles.</p> <!-- Conditional rendering of address content if isAddressVisible is true --> <!-- Conditional rendering of a link if isLinkVisible is true. The link also conditionally includes an arrow SVG if isArrowVisible is true --> <a class="group mt-2 inline-flex items-center gap-x-2 rounded-lg text-sm font-medium text-zinc-600 outline-none ring-zinc-500 transition duration-300 hover:text-zinc-800 focus-visible:ring dark:text-zinc-400 dark:ring-zinc-200 dark:hover:text-zinc-200 dark:focus:outline-none dark:focus:ring-1 " href="contact.html#"> Visit guides & tutorials <svg class="h-4 w-4 flex-shrink-0 transition ease-in-out group-hover:translate-x-1" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" > <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" /> </svg> </a> </div> </div> <!-- Root container, which arranges the heading and content --><div class="flex gap-x-7 py-6"> <!-- Slot to allow for extensibility of the component --> <svg class="mt-1.5 h-6 w-6 flex-shrink-0 text-neutral-600 dark:text-neutral-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155" class></path></svg> <div class="grow"> <!-- Heading of the section --> <h3 class="font-bold text-neutral-700 dark:text-neutral-300"> FAQ </h3> <!-- Content of the section --> <p class="mt-1 text-sm text-neutral-600 dark:text-neutral-400">Explore our FAQ for quick, clear answers to common queries.</p> <!-- Conditional rendering of address content if isAddressVisible is true --> <!-- Conditional rendering of a link if isLinkVisible is true. The link also conditionally includes an arrow SVG if isArrowVisible is true --> <a class="group mt-2 inline-flex items-center gap-x-2 rounded-lg text-sm font-medium text-zinc-600 outline-none ring-zinc-500 transition duration-300 hover:text-zinc-800 focus-visible:ring dark:text-zinc-400 dark:ring-zinc-200 dark:hover:text-zinc-200 dark:focus:outline-none dark:focus:ring-1 " href="contact.html#"> Visit FAQ <svg class="h-4 w-4 flex-shrink-0 transition ease-in-out group-hover:translate-x-1" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" > <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" /> </svg> </a> </div> </div> <!-- Root container, which arranges the heading and content --><div class="flex gap-x-7 py-6"> <!-- Slot to allow for extensibility of the component --> <svg class="mt-1.5 h-6 w-6 flex-shrink-0 text-neutral-600 dark:text-neutral-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" class></path><path d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1 1 15 0Z" class></path></svg> <div class="grow"> <!-- Heading of the section --> <h3 class="font-bold text-neutral-700 dark:text-neutral-300"> Visit our office </h3> <!-- Content of the section --> <p class="mt-1 text-sm text-neutral-600 dark:text-neutral-400">UK Survelir</p> <!-- Conditional rendering of address content if isAddressVisible is true --> <p class="mt-1 text-sm italic text-neutral-500">72 Union Terrace, E10 4PE London</p> <!-- Conditional rendering of a link if isLinkVisible is true. The link also conditionally includes an arrow SVG if isArrowVisible is true --> </div> </div> <!-- Root container, which arranges the heading and content --><div class="flex gap-x-7 py-6"> <!-- Slot to allow for extensibility of the component --> <svg class="mt-1.5 h-6 w-6 flex-shrink-0 text-neutral-600 dark:text-neutral-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><title></title><path d="M21.75 9v.906a2.25 2.25 0 0 1-1.183 1.981l-6.478 3.488M2.25 9v.906a2.25 2.25 0 0 0 1.183 1.981l6.478 3.488m8.839 2.51-4.66-2.51m0 0-1.023-.55a2.25 2.25 0 0 0-2.134 0l-1.022.55m0 0-4.661 2.51m16.5 1.615a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V8.844a2.25 2.25 0 0 1 1.183-1.981l7.5-4.039a2.25 2.25 0 0 1 2.134 0l7.5 4.039a2.25 2.25 0 0 1 1.183 1.98V19.5Z" class></path></svg> <div class="grow"> <!-- Heading of the section --> <h3 class="font-bold text-neutral-700 dark:text-neutral-300"> Contact us by email </h3> <!-- Content of the section --> <p class="mt-1 text-sm text-neutral-600 dark:text-neutral-400">Prefer the written word? Drop us an email at</p> <!-- Conditional rendering of address content if isAddressVisible is true --> <!-- Conditional rendering of a link if isLinkVisible is true. The link also conditionally includes an arrow SVG if isArrowVisible is true --> <a class="group mt-2 inline-flex items-center gap-x-2 rounded-lg text-sm font-medium text-zinc-600 outline-none ring-zinc-500 transition duration-300 hover:text-zinc-800 focus-visible:ring dark:text-zinc-400 dark:ring-zinc-200 dark:hover:text-zinc-200 dark:focus:outline-none dark:focus:ring-1 " href="contact.html#"> support@survelir.com </a> </div> </div> </div> </div> </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="contact.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 4 2025, 7:58 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 | 68138 | 2025-04-04 10:30:48.381726748 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJH6F4J4XGH6E8RWZAD | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/sitemap-index.xml | a20cadb3bc56953634ff44cdfa3c645d02364b1a | <?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>https://www.surveilr.com/sitemap-0.xml</loc></sitemap></sitemapindex> | xml | 187 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJJC05BKVCRZ46KPFEX | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/favicon.ico | - | ico | 2258 | 2025-04-04 08:01:47 UTC | 2025-04-04 10:30:48 | UNKNOWN | ||||||||||
01JR05MVJJVE8S4ZQ1PR2J5814 | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/fhir-explorer/index.html | 1c308c467e97df1a68b5e81e3d77a27b1e1c8daa | <!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":"FHIR Explorer | surveilr","url":"https://www.surveilr.com/pattern/fhir-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/fhir-explorer/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/fhir-explorer/"><meta property="og:type" content="website"><meta property="og:title" content="FHIR 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/fhir-explorer/"><meta name="twitter:title" content="FHIR 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>FHIR 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.C1i_5bqm.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="46b98d65-618a-408d-b5e9-262450fe13f0" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="46b98d65-618a-408d-b5e9-262450fe13f0"> <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"> Fhir 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/fhir-explorer/","name":"Fhir 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 FHIR Explorer Pattern for surveilr ingests healthcare FHIR JSON files and allows querying, quality metrics, 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"> FHIR Explorer </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> HL7 FHIR Content Aggregator and Explorer </p> </div> <div> <img src="../../_astro/fhir-explorer-pattern.DmWEO2EG_ewmN5.avif" id="fadeInMoveRight" alt="FHIR Explorer" loading="eager" width="1356" height="528" 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"> HL7 FHIR Content Aggregator and Explorer </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> The FHIR Explorer Pattern for surveilr ingests healthcare FHIR JSON files and allows querying, quality metrics, and exploration of those files. surveilr ingests healthcare FHIR data (represented as JSON files), 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/fhir-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/fhir-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 FHIR data </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Easily search, filter, and interact with healthcare records in FHIR 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 FHIR 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 FHIR resources against FHIR schema 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 FHIR bundles </h3> <p class="text-neutral-600 dark:text-neutral-400"> Supports ingestion of FHIR 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/fhir-explorer-pattern-ss-3.CmdadhWq_NO04N.avif" alt="Blueprint Illustration" width="927" height="739" 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/fhir-explorer-pattern-ss-1.gAtRbOmV_Z1VPBzY.avif" alt="Blueprint Illustration" width="927" height="739" 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 4 2025, 7:58 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 | 68913 | 2025-04-04 10:30:48.238726906 UTC | 2025-04-04 10:30:48 | UNKNOWN | |||||||||
01JR05MVJJWHC8G9JQSTT8V9DR | 01JR05MVHAMRA4RMC80WZ2VSM4 | 01JR05MVHBYQM19YXVAMNTS3J1 | 01JR05MVHCX3NXA3S6VEVKEJS1 | /app/www.surveilr.com/lib/pattern/site-quality-explorer/content/website-resources/www.surveilr.com/pattern/fleetfolio/index.html | 9e9f3ede19558189a0cf940026ca7880cf9e36bd | <!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":"Fleetfolio | surveilr","url":"https://www.surveilr.com/pattern/fleetfolio/","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/fleetfolio/" /><!-- Facebook Meta Tags --><meta property="og:locale" content="en_US"><meta property="og:url" content="https://www.surveilr.com/pattern/fleetfolio/"><meta property="og:type" content="website"><meta property="og:title" content="Fleetfolio | 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/fleetfolio/"><meta name="twitter:title" content="Fleetfolio | 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>Fleetfolio | 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.C1i_5bqm.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="c83a42d4-eac6-4378-a208-1594cedbdddb" data-path-length="2" data-truncated="true"> <nav aria-label="Site navigation" class="c-breadcrumbs" id="c83a42d4-eac6-4378-a208-1594cedbdddb"> <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"> Fleetfolio </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/fleetfolio/","name":"Fleetfolio"}}]}</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"> Fleetfolio brings comprehensive asset and identity intelligence, enabling your security operations to stay ahead of evolving digital threats. With the continuous monitoring and accurate inventory of all your organization's assets—whether devices, users, applications, or networked systems—Fleetfolio ensures no asset is overlooked. Powered by real-time updates and enriched data, Fleetfolio offers complete visibility into your assets, reduces risk exposure, and accelerates threat detection and compliance. </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"> Fleetfolio </h1> <p class="text-lg text-neutral-600 dark:text-neutral-400"> Continuous Asset and Identity Intelligence for Enhanced Security </p> </div> <div> <img src="../../_astro/fleetfolio-continuous-asset-and-identity-intelligence.1s-dj6Pd_ODWkv.avif" id="fadeInMoveRight" alt="Fleetfolio" loading="eager" width="1536" height="1024" 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"> Continuous Asset and Identity Intelligence for Enhanced Security </h2> <p class="mt-3 text-pretty text-neutral-600 dark:text-neutral-400"> Fleetfolio continuously pulls data from a variety of sources—network, endpoint, cloud systems, and vulnerability scanning tools—to create and maintain an accurate, real-time inventory of all assets and identities within your organization. By correlating this data, Fleetfolio ensures that no device, user, or application is overlooked, eliminating outdated or incomplete information and providing real-time visibility into the asset landscape. It integrates seamlessly with your existing Security Information and Event Management (SIEM) systems and Configuration Management Databases (CMDBs), enhancing both the asset discovery process and the accuracy of the asset inventory. Through bi-directional integration, Fleetfolio enriches SIEM data with detailed asset context, enabling more precise alert correlation and faster detection of threats. Simultaneously, it updates the CMDB with up-to-date asset information, ensuring all records are aligned and enhancing workflows for streamlined compliance reporting and incident response. This integrated, dynamic approach ensures continuous visibility, improved security, and more efficient risk management across your digital environment. </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/fleetfolio/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="https://demo.hub.opsfolio.com/fleetfolio-service/" 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"> Continuous Asset Discovery & Identity Intelligence </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Fleetfolio continuously discovers and monitors your assets, building a comprehensive inventory of devices, users, applications, and cloud resources in real time. This approach keeps your organization’s asset visibility up to date, eliminating the risk of outdated or incomplete asset data. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Enriched Asset Data for Deep Context </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Filling in the gaps of traditional asset management, Fleetfolio provides enriched data that includes network activity, device associations, and health metrics. This richer context improves risk assessments, compliance checks, and threat detection. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Compliance Tracking Made Simple </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Fleetfolio includes out-of-the-box (OOTB) compliance frameworks for major security standards such as ISO 27001, NIST, HIPAA, and PCI DSS. With customizable compliance metrics, your security teams can tailor the system to meet your organization's specific needs, ensuring comprehensive reporting and minimized risk exposure. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Seamless Integration with Security Tools </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Fleetfolio integrates effortlessly with existing security information and event management (SIEM) systems, enriching the alerts and logs with asset and identity details. This empowers your team to correlate incidents with precise asset and identity data, ensuring faster and more accurate investigations. </p> </div> </div><div class="flex"> <div> <h3 class="text-base font-bold text-neutral-800 dark:text-neutral-200 sm:text-lg"> Bidirectional CMDB Integration </h3> <p class="mt-1 text-neutral-600 dark:text-neutral-400"> Keep your Configuration Management Database (CMDB) up to date with continuous asset and identity intelligence. Fleetfolio seamlessly integrates with CMDBs, ensuring that your asset inventory is always synchronized, and helping close any gaps in your asset records. </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"> Reduced Risk Exposure </h3> <p class="text-neutral-600 dark:text-neutral-400"> With up-to-date, comprehensive asset and identity data, Fleetfolio reduces security blind spots, minimizes compliance risks, and enables faster incident response. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Accelerated Investigations </h3> <p class="text-neutral-600 dark:text-neutral-400"> By providing security teams with accurate asset context, Fleetfolio significantly reduces the time needed to investigate threats. With real-time data and historical records, you can quickly pinpoint affected assets and the associated risks. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Proactive Security and Compliance Management </h3> <p class="text-neutral-600 dark:text-neutral-400"> Fleetfolio ensures ongoing compliance by continuously tracking and measuring your assets' security controls. It proactively identifies vulnerabilities and compliance gaps, reducing the burden of manual audits and helping you stay compliant with ease. </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"> Asset & Identity Discovery </h3> <p class="text-neutral-600 dark:text-neutral-400"> Gain real-time visibility of your network's assets, ensuring no device, user, or application is left unmonitored. Fleetfolio ensures your asset inventory is always accurate, reducing security gaps and non-compliance risks. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Compliance Reporting </h3> <p class="text-neutral-600 dark:text-neutral-400"> Fleetfolio simplifies compliance reporting, allowing your team to quickly demonstrate adherence to critical security standards. Customizable compliance dashboards provide insights into your risk posture, helping you close security gaps before they lead to breaches. </p> </div><div> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> Incident Investigation & Response </h3> <p class="text-neutral-600 dark:text-neutral-400"> Fleetfolio enhances your ability to track and analyze security incidents by providing detailed insights into asset behavior and identity relations. This enables faster identification of the root cause of an incident, minimizing downtime and damage. </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/fleetfolio-screenshot-1.BvMYEE66_ZFm5dn.avif" alt="Blueprint Illustration" width="997" height="625" 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/fleetfolio-screenshot-2.BIzQd42p_Z1vYoKz.avif" alt="Blueprint Illustration" width="997" height="625" 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 4 2025, 7:58 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 | 71841 | 2025-04-04 10:30:46.869728417 UTC | 2025-04-04 10:30:48 | UNKNOWN |
(Page 1 of 92) Next