Website: add /customer-stories (#23837)

For: #23721 

Changes:
- Added /customer-stories, a page that displays the testimonials from
testimonials.yml
- Changed the /testimonials redirect to go to the /customer-stories
page.
- Updated the "What people are saying" link on the homepage and the
header navigation.



@mike-j-thomas FYI: To make this PR quickly, I did not implement the
sort order in the wireframes or change the testimonials yaml.
This commit is contained in:
Eric 2024-11-14 23:52:36 -06:00 committed by GitHub
parent bead026c64
commit 4f03956c72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 698 additions and 4 deletions

View file

@ -0,0 +1,51 @@
module.exports = {
friendlyName: 'View testimonials',
description: 'Display "Testimonials" page.',
exits: {
success: {
viewTemplatePath: 'pages/testimonials'
}
},
fn: async function () {
if (!_.isObject(sails.config.builtStaticContent) || !_.isArray(sails.config.builtStaticContent.testimonials) || !sails.config.builtStaticContent.compiledPagePartialsAppPath) {
throw {badConfig: 'builtStaticContent.testimonials'};
}
// Get testimonials for the <scrolalble-tweets> component.
let testimonials = _.clone(sails.config.builtStaticContent.testimonials);
// Filter the testimonials by product category
let testimonialsForMdm = _.filter(testimonials, (testimonial)=>{
return _.contains(testimonial.productCategories, 'Device management');
});
let testimonialsForSecurityEngineering = _.filter(testimonials, (testimonial)=>{
return _.contains(testimonial.productCategories, 'Vulnerability management');
});
let testimonialsForItEngineering = _.filter(testimonials, (testimonial)=>{
return _.contains(testimonial.productCategories, 'Endpoint operations');
});
let testimonialsWithVideoLinks = _.filter(testimonials, (testimonial)=>{
return testimonial.youtubeVideoUrl;
});
return {
testimonialsForMdm,
testimonialsForSecurityEngineering,
testimonialsForItEngineering,
testimonialsWithVideoLinks,
};
}
};

View file

@ -0,0 +1,44 @@
parasails.registerPage('testimonials', {
// ╦╔╗╔╦╔╦╗╦╔═╗╦ ╔═╗╔╦╗╔═╗╔╦╗╔═╗
// ║║║║║ ║ ║╠═╣║ ╚═╗ ║ ╠═╣ ║ ║╣
// ╩╝╚╝╩ ╩ ╩╩ ╩╩═╝ ╚═╝ ╩ ╩ ╩ ╩ ╚═╝
data: {
selectedContent: 'mdm',
modal: '',
quotesWithVideoLinks: [],
},
// ╦ ╦╔═╗╔═╗╔═╗╦ ╦╔═╗╦ ╔═╗
// ║ ║╠╣ ║╣ ║ ╚╦╝║ ║ ║╣
// ╩═╝╩╚ ╚═╝╚═╝ ╩ ╚═╝╩═╝╚═╝
beforeMount: function() {
for(let quote of this.testimonialsWithVideoLinks) {
if(quote.youtubeVideoUrl){
this.quotesWithVideoLinks.push({
modalId: _.kebabCase(quote.quoteAuthorName),
embedId: quote.videoIdForEmbed,
});
}
}
},
mounted: async function() {
//…
},
// ╦╔╗╔╔╦╗╔═╗╦═╗╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
// ║║║║ ║ ║╣ ╠╦╝╠═╣║ ║ ║║ ║║║║╚═╗
// ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝
methods: {
clickChangePageContent: function(option) {
this.selectedContent = option;
},
clickOpenVideoModal: function(modalName) {
console.log(modalName);
this.modal = _.kebabCase(modalName);
},
closeModal: function() {
this.modal = undefined;
},
}
});

View file

@ -77,4 +77,5 @@
@import 'pages/integrations.less';
@import 'pages/start.less';
@import 'pages/deals.less';
@import 'pages/testimonials.less';

View file

@ -0,0 +1,441 @@
#testimonials {
h4 {
color: #515774;
font-feature-settings: 'salt' on, 'ss01' on, 'ss02' on;
font-family: 'Roboto Mono';
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 150%;
text-transform: uppercase;
}
h1 {
color: #192147;
font-family: Inter;
font-size: 48px;
font-style: normal;
font-weight: 800;
line-height: 120%;
}
[purpose='page-container'] {
padding: 64px;
}
[purpose='page-content'] {
max-width: 1072px;
margin-left: auto;
margin-right: auto;
}
[purpose='hero-quote'] {
margin-top: 32px;
margin-botom: 32px;
[purpose='quote-author-info'] {
display: inline-flex;
padding: 4px 16px 4px 4px;
border-radius: 28px;
width: fit-content;
margin-top: 8px;
margin-bottom: 48px;
[purpose='job-title'] {
color: var(--UI-Fleet-Black-75, #515774);
font-family: Inter;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 18px;
}
[purpose='name'] {
color: var(--UI-Fleet-Black-75, #515774);
/* Body XS (bold) */
font-family: Inter;
font-size: 12px;
font-style: normal;
font-weight: 700;
line-height: 18px; /* 150% */
}
[purpose='profile-picture'] {
margin-right: 16px;
img {
height: 48px;
width: 48px;
}
}
}
[purpose='quote-text'] {
color: var(--UI-Fleet-Black-75, #515774);
font-family: Inter;
font-size: 20px;
font-style: italic;
font-weight: 400;
line-height: 30px; /* 150% */
max-width: 616px;
}
}
[purpose='context-switch'] {
border-bottom: 1px solid var(--border-border-primary, #E2E4EA);
margin-bottom: 64px;
[purpose='switch-option'] {
p {
margin-bottom: 0px;
}
cursor: pointer;
display: flex;
padding: 16px;
justify-content: center;
align-items: center;
width: 33%;
color: var(--Core-Fleet-Black, #192147);
text-align: center;
font-family: Inter;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px; /* 150% */
white-space: nowrap;
&.selected {
font-weight: 700;
border-bottom: 2px solid var(--text-text-brand, #192147);
}
}
}
[purpose='testimonials-container'] {
columns: 3;
margin-bottom: 32px;
}
[purpose='testimonial-card'] {
display: inline-block;
padding: var(--spacing-3, 24px);
flex-direction: column;
justify-content: center;
align-items: flex-start;
align-self: stretch;
border-radius: 16px;
border: 1px solid var(--UI-Fleet-Black-10, #E2E4EA);
background: var(--Core-White, #FFF);
height: min-content;
[purpose='logo'] {
img {
max-height: 32px;
max-width: 100%;
}
min-height: 0;
// margin-bottom: 24px;
}
[purpose='quote'] {
color: var(--UI-Fleet-Black-75, #515774);
/* Body SM (FKA Card text) */
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 21px; /* 150% */
margin-bottom: 16px;
}
[purpose='video-link'] {
cursor: pointer;
text-decoration: underline;
}
[purpose='quote-author-info'] {
[purpose='job-title'] {
font-size: 12px;
line-height: 18px;
}
[purpose='name'] {
color: @core-fleet-black;
}
[purpose='profile-picture'] {
margin-right: 16px;
img {
height: 48px;
width: 48px;
border-radius: 50%;
}
}
}
}
[purpose='share-button'] {
display: flex;
padding: var(--spacing-spacing-xs, 8px) var(--spacing-spacing-sm, 16px);
justify-content: center;
align-items: center;
gap: var(--spacing-spacing-xxs, 4px);
border-radius: var(--spacing-spacing-sm, 16px);
background: var(--surface-surface-secondary, #F9FAFC);
color: var(--text-text-primary, #515774);
text-align: center;
/* Body SM (bold) */
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 700;
line-height: 21px; /* 150% */
&:hover {
text-decoration: none;
}
}
[parasails-component='logo-carousel'] {
margin-bottom: 64px;
}
[purpose='statistics'] {
display: flex;
flex-direction: row;
justify-content: center;
margin-top: 64px;
margin-bottom: 64px;
h4 {
color: #515774;
text-align: center;
/* Body LG (bold) */
font-family: Inter;
font-size: 18px;
font-style: normal;
font-weight: 700;
line-height: 27px;
}
p {
color: var(--text-text-primary, #515774);
text-align: center;
text-wrap: nowrap;
/* Body XS (FKA p small) */
font-family: Inter;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 18px; /* 150% */
margin-bottom: 0px;
}
[purpose='customers'] {
border-right: 1px solid #E2E4EA;
display: flex;
padding: 8px 64px;
flex-direction: column;
align-items: center;
}
[purpose='devices'] {
border-right: 1px solid #E2E4EA;
display: flex;
padding: 8px 64px;
flex-direction: column;
align-items: center;
}
[purpose='countries'] {
display: flex;
padding: 8px 64px;
flex-direction: column;
align-items: center;
}
}
[purpose='bottom-gradient'] {
background: linear-gradient(180deg, #FFFFFF 0%, #E9F4F4 100%);
}
[purpose='bottom-cta'] {
h2 {
color: var(--Fleet-Black-100, #192147);
text-align: center;
/* Title L (FKA h2) */
font-family: Inter;
font-size: 32px;
font-style: normal;
font-weight: 800;
line-height: 38.4px; /* 120% */
}
[purpose='button-row'] {
a {
font-weight: 700;
font-size: 16px;
text-decoration: none;
}
[purpose='cta-button'] {
display: flex;
height: 36px;
padding: 16px;
justify-content: center;
align-items: center;
gap: 4px;
border-radius: 8px;
background: var(--color-brand-vibrant-red, #FF5C83);
color: var(--Core-White, #FFF);
text-align: center;
/* Body MD (bold) */
font-family: Inter;
font-size: 16px;
font-style: normal;
font-weight: 700;
line-height: 24px; /* 150% */
margin-right: 24px;
position: relative;
}
[purpose='cta-button']::before {
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
opacity: 1;
content: '';
position: absolute;
top: 0;
left: -5px;
width: 50%;
height: 100%;
transform: skew(-10deg);
transition: left 0.5s ease-in, opacity 0.50s ease-in, width 0.5s ease-in;
}
[purpose='cta-button']:hover:before {
left: 160px;
width: 110%;
}
[parasails-component='animated-arrow-button'] {
width: fit-content;
display: flex;
align-items: center;
padding: 6px 0px;
text-decoration: none;
font-weight: 700;
[purpose='button-text'] {
color: var(--Core-Fleet-Black, #192147);
text-align: center;
font-family: Inter;
font-size: 15px;
font-style: normal;
font-weight: 600;
line-height: 24px; /* 160% */
}
}
}
}
[purpose='video-modal'] {
[purpose='modal-dialog'] {
width: 100%;
max-width: 100%;
}
[purpose='modal-content'] {
max-width: 1140px;
height: 641px;
background-color: transparent;
box-shadow: none;
border: none;
padding: 0px;
margin-top: 150px;
margin-left: auto;
margin-right: auto;
[purpose='modal-close-button'] {
top: -40px;
right: 0px;
border-radius: 50%;
width: 32px;
height: 32px;
padding: 0px 0px 4px 0px;
background-color: #192147;
color: #FFF;
opacity: 1;
}
}
iframe {
width: 1140px;
height: 641px;
}
}
@media (max-width: 991px) {
[purpose='testimonials-container'] {
columns: 2;
}
[purpose='page-container'] {
padding: 64px 32px;
}
}
@media (max-width: 776px) {
[purpose='page-container'] {
padding: 48px 24px;
}
[purpose='testimonials-container'] {
columns: 2;
}
}
@media (max-width: 576px) {
[purpose='page-container'] {
padding: 32px 24px;
}
[purpose='testimonials-container'] {
columns: 1;
}
[purpose='statistics'] {
flex-direction: column;
max-width: fit-content;
margin-left: auto;
margin-right: auto;
margin-top: 32px;
h4 {
margin-bottom: 0px;
}
[purpose='customers'] {
padding: 0px 64px 24px 64px;
border-right: none;
}
[purpose='devices'] {
border-top: 1px solid #E2E4EA;
border-bottom: 1px solid #E2E4EA;
padding: 24px;
border-right: none;
}
[purpose='countries'] {
padding: 24px 64px 0px 64px;
border-right: none;
}
}
[purpose='testimonial-card'] {
width: 100%;
}
[purpose='context-switch'] {
border-left: 1px solid var(--border-border-primary, #E2E4EA);
border-bottom: none;
margin-bottom: 64px;
[purpose='switch-option'] {
cursor: pointer;
display: flex;
padding: 12px;
justify-content: center;
align-items: center;
width: 100%;
color: var(--Core-Fleet-Black, #192147);
text-align: center;
font-family: Inter;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px; /* 150% */
white-space: nowrap;
&.selected {
font-weight: 700;
border-left: 2px solid var(--text-text-brand, #192147);
border-bottom: none;
}
}
}
}
}

View file

@ -57,4 +57,5 @@ module.exports.policies = {
'view-deals': true,
'deliver-deal-registration-submission': true,
'get-est-device-certificate': true,
'view-testimonials': true,
};

View file

@ -292,6 +292,14 @@ module.exports.routes = {
}
},
'GET /customer-stories': {
action: 'view-testimonials',
locals: {
pageTitleForMeta: 'Customer stories',
pageDescriptionForMeta: 'See what people are saying about Fleet'
}
},
// ╦ ╔═╗╔═╗╔═╗╔═╗╦ ╦ ╦═╗╔═╗╔╦╗╦╦═╗╔═╗╔═╗╔╦╗╔═╗
// ║ ║╣ ║ ╦╠═╣║ ╚╦╝ ╠╦╝║╣ ║║║╠╦╝║╣ ║ ║ ╚═╗
// ╩═╝╚═╝╚═╝╩ ╩╚═╝ ╩ ╩╚═╚═╝═╩╝╩╩╚═╚═╝╚═╝ ╩ ╚═╝
@ -500,7 +508,7 @@ module.exports.routes = {
//
// For example, a clever user might try to visit fleetdm.com/documentation, not knowing that Fleet's website
// puts this kind of thing under /docs, NOT /documentation. These "convenience" redirects are to help them out.
'GET /testimonials': 'https://github.com/fleetdm/fleet/blob/28cd420b086c23a6606ba17c4f3821ed267c6bbb/handbook/company/testimonials.yml#L190',
'GET /testimonials': '/customer-stories',
'GET /admin': '/admin/email-preview',
'GET /renew': 'https://calendly.com/zayhanlon/fleet-renewal-discussion',
'GET /documentation': '/docs',

View file

@ -183,7 +183,7 @@
<hr>
<a purpose="mobile-dropdown-toggle" class="d-flex align-items-center mr-4 collapsed" data-toggle="collapse" data-target="#mobileNavbarToggleCommunity">Stories</a>
<div id="mobileNavbarToggleCommunity" purpose="mobile-dropdown" class="collapse" data-parent="#mobileDropdowns">
<a purpose="mobile-dropdown-link" target="_blank" href="/testimonials">What people are saying</a>
<a purpose="mobile-dropdown-link" href="/testimonials">What people are saying</a>
<a purpose="mobile-dropdown-link" href="/announcements">News</a>
<a purpose="mobile-dropdown-link" href="/support">Ask around</a>
<span class="mt-2 mb-2">COMPANY</span>
@ -243,7 +243,7 @@
<div purpose="dropdown-button" class="btn-group" style="width: 89px;">
<a purpose="header-nav-btn" button-text="Community" class="dropdown-toggle align-items-center <%= typeof currentSection !== 'undefined' && currentSection === 'community' ? 'current-section' : '' %>" data-toggle="dropdown">Stories</a>
<div purpose="header-dropdown" class="dropdown-menu">
<a class="dropdown-item" target="_blank" href="/testimonials">What people are saying</a>
<a class="dropdown-item" href="/testimonials">What people are saying</a>
<a class="dropdown-item" href="/announcements">News</a>
<a class="dropdown-item" href="/support">Ask around</a>
<a class="dropdown-item" href="/contact">Take a tour</a><!-- «« included here in the desktop hover nav because unlike the mobile nav (which has 'Take a tour' as a primary CTA), there is no option to do that on desktop from other pages otherwise -->
@ -498,6 +498,7 @@
<script src="/js/pages/reports/state-of-device-management.page.js"></script>
<script src="/js/pages/start.page.js"></script>
<script src="/js/pages/support.page.js"></script>
<script src="/js/pages/testimonials.page.js"></script>
<script src="/js/pages/transparency.page.js"></script>
<script src="/js/pages/try-fleet/sandbox-expired.page.js"></script>
<script src="/js/pages/try-fleet/sandbox-teleporter.page.js"></script>

View file

@ -10,7 +10,7 @@
<p>Replace the sprawl with <%= primaryBuyingSituation === 'vm'? 'secure, open-source reporting that works the way you want' : primaryBuyingSituation === 'eo-security'? 'open-source endpoint observability for every platform' : 'a modern device management platform that works the way you want' %>.</p>
<div purpose="button-row" class="d-flex flex-sm-row flex-column justify-content-center align-items-center">
<a purpose="cta-button" href="<%= primaryBuyingSituation === 'mdm' ? '/device-management' : primaryBuyingSituation === 'vm' ? '/vulnerability-management' : primaryBuyingSituation === 'eo-security' ? '/endpoint-ops' : primaryBuyingSituation === 'eo-it' ? '/endpoint-ops' : '/device-management' %>">Learn how</a>
<animated-arrow-button target="_blank" href="/testimonials">What people are saying</animated-arrow-button>
<animated-arrow-button href="/testimonials">What people are saying</animated-arrow-button>
</div>
</div>
</div>

147
website/views/pages/testimonials.ejs vendored Normal file
View file

@ -0,0 +1,147 @@
<div id="testimonials" v-cloak>
<div purpose="page-container">
<div purpose="page-content">
<div purpose="page-hero">
<h4>Customer stories</h4>
<h1>What people are saying</h1>
<div purpose="hero-quote">
<img alt="an opening quotation mark" style="width:16px; margin-bottom: 8px;" src="/images/icon-quote-21x17@2x.png">
<p purpose="quote-text">
We wanted an open-source MDM to easily use configuration-as-code, deliver the best possible experience for our employees, and make security happy.
</p>
<div purpose="quote-author-info" class="d-flex flex-row align-items-center">
<div purpose="profile-picture">
<img alt="Wes Whetstone" src="/images/testimonial-author-kenny-botelho-48x48@2x.png">
</div>
<div class="d-flex flex-column align-self-top">
<p purpose="name" class="font-weight-bold m-0">Kenny Botelho</p>
<p purpose="job-title" class="m-0">Lead Client Platform Engineer</p>
</div>
</div>
</div>
</div>
<div purpose="context-switch" class="d-flex flex-sm-row flex-column">
<div purpose="switch-option" :class="[selectedContent === 'mdm' ? 'selected' : '']" @click="clickChangePageContent('mdm')"><p>Device Managment</p></div>
<div purpose="switch-option" :class="[selectedContent === 'it' ? 'selected' : '']" @click="clickChangePageContent('it')"><p>IT Engineering</p></div>
<div purpose="switch-option" :class="[selectedContent === 'security' ? 'selected' : '']" @click="clickChangePageContent('security')"><p>Security Engineering</p></div>
</div>
<div v-if="selectedContent === 'mdm'">
<div purpose="testimonials-container" class="card-columns">
<div purpose="testimonial-card" class="card" v-for="testimonial in testimonialsForMdm" target="_blank" :href="testimonial.quoteLinkUrl">
<div purpose="logo" class="mb-4" v-if="testimonial.quoteImageFilename">
<img alt="logo" :height="testimonial.imageHeight" :src="'/images/'+testimonial.quoteImageFilename"/>
</div>
<p purpose="quote">
{{testimonial.quote}}
<a purpose="video-link" v-if="testimonial.youtubeVideoUrl" @click="clickOpenVideoModal(testimonial.quoteAuthorName)">See the video.</a>
</p>
<div purpose="quote-author-info" class="d-flex flex-row align-items-center">
<div purpose="profile-picture">
<img alt="Profile picture" :src="'/images/'+testimonial.quoteAuthorProfileImageFilename">
</div>
<div class="d-flex flex-column align-self-top">
<p purpose="name" class="font-weight-bold m-0">{{testimonial.quoteAuthorName}}</p>
<p purpose="job-title" class="m-0">{{testimonial.quoteAuthorJobTitle}}</p>
</div>
</div>
</div>
</div>
</div>
<div v-if="selectedContent === 'it'">
<div purpose="testimonials-container" class="card-columns">
<div purpose="testimonial-card" class="card" v-for="testimonial in testimonialsForItEngineering" target="_blank" :href="testimonial.quoteLinkUrl">
<div purpose="logo" class="mb-4" v-if="testimonial.quoteImageFilename">
<img alt="logo" :height="testimonial.imageHeight" :src="'/images/'+testimonial.quoteImageFilename"/>
</div>
<p purpose="quote">
{{testimonial.quote}}
<a purpose="video-link" v-if="testimonial.youtubeVideoUrl" @click.prevent.self="clickOpenVideoModal(testimonial.quoteAuthorName)">See the video.</a>
</p>
<div purpose="quote-author-info" class="d-flex flex-row align-items-center">
<div purpose="profile-picture">
<img alt="Profile picture" :src="'/images/'+testimonial.quoteAuthorProfileImageFilename">
</div>
<div class="d-flex flex-column align-self-top">
<p purpose="name" class="font-weight-bold m-0">{{testimonial.quoteAuthorName}}</p>
<p purpose="job-title" class="m-0">{{testimonial.quoteAuthorJobTitle}}</p>
</div>
</div>
</div>
</div>
</div>
<div v-if="selectedContent === 'security'">
<div purpose="testimonials-container" class="card-columns">
<div purpose="testimonial-card" class="card" v-for="testimonial in testimonialsForSecurityEngineering" target="_blank" :href="testimonial.quoteLinkUrl">
<div purpose="logo" class="mb-4" v-if="testimonial.quoteImageFilename">
<img alt="logo" :height="testimonial.imageHeight" :src="'/images/'+testimonial.quoteImageFilename"/>
</div>
<p purpose="quote">
{{testimonial.quote}}
<a purpose="video-link" v-if="testimonial.youtubeVideoUrl" @click.prevent.self="clickOpenVideoModal(testimonial.quoteAuthorName)">See the video.</a>
</p>
<div purpose="quote-author-info" class="d-flex flex-row align-items-center">
<div purpose="profile-picture">
<img alt="Profile picture" :src="'/images/'+testimonial.quoteAuthorProfileImageFilename">
</div>
<div class="d-flex flex-column align-self-top">
<p purpose="name" class="font-weight-bold m-0">{{testimonial.quoteAuthorName}}</p>
<p purpose="job-title" class="m-0">{{testimonial.quoteAuthorJobTitle}}</p>
</div>
</div>
</div>
</div>
</div>
<div purpose="page-section">
<div class="d-flex flex-row align-items-center justify-content-center">
<a purpose="share-button" href="https://github.com/fleetdm/fleet/edit/main/handbook/company/testimonials.yml" target="_blank">Share your story</a>
</div>
<div purpose="logos-and-statistics" class="mx-auto">
<div purpose="statistics">
<div purpose="customers">
<h4>100+</h4>
<p>customers</p>
</div>
<div purpose="devices">
<h4>2,000,000+</h4>
<p>computing devices</p>
</div>
<div purpose="countries" >
<h4>90+</h4>
<p>countries</p>
</div>
</div>
<logo-carousel></logo-carousel>
</div>
</div>
</div><%// page content%>
</div><%// page container%>
<%/* Bottom gradient */%>
<div purpose="bottom-gradient">
<div purpose="homepage-content" class="container">
<div class="text-center" purpose="bottom-cta">
<h4 v-if="selectedContent === 'security'">Open-source vulnerability reporting</h4>
<h4 v-else>For teams with lots of computing devices</h4>
<h2 class="mx-auto" v-if="selectedContent === 'mdm'">Open-source device management for everyone</h2>
<h2 class="mx-auto" v-if="selectedContent === 'it'">Untangle your endpoints</h2>
<h2 class="mx-auto" v-if="selectedContent === 'security'">Check vulnerabilities anywhere</h2>
<div purpose="button-row" style="margin-top: 40px;" class="d-flex flex-sm-row flex-column justify-content-center align-items-center mx-auto">
<a purpose="cta-button" href="/register">Try it yourself</a>
<animated-arrow-button href="/contact">Talk to us</animated-arrow-button>
</div>
</div>
</div>
</div>
<%/* Cloud city banner */%>
<parallax-city></parallax-city>
<div v-for="video in quotesWithVideoLinks">
<modal purpose="video-modal" v-if="modal === video.modalId" @close="closeModal()" >
<iframe width="560" height="315" :src="'https://www.youtube.com/embed/'+video.embedId+'?rel=0'" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture;" allowfullscreen></iframe>
</modal>
</div>
</div>
<%- /* Expose server-rendered data as window.SAILS_LOCALS :: */ exposeLocalsToBrowser() %>