Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions nuxt/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,11 @@ export default defineNuxtConfig({
'/landing/tulip/',
'/landing/plc/',
'/landing/factory-efficiency/',
// The partner pages are .vue files; only the listing is linked from the nav.
'/partners/',
'/partners/certify-hardware/',
'/partners/ctrlx/',
'/partners/referral-sign-up/',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dgatti0213 Do you handle the inputs on that page? Or should it be removed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The port is 1:1 and the form is still HubSpot form aad1cda7, so submissions land where they always did. Whether the page stays is a content call rather than a migration one. If it should go, a deletion plus a redirect is cleaner as its own change than dropping it from this port.

@dgatti0213 dgatti0213 Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content on the pages was before me, It probably needs some review from me. Port for now is fine tho.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this one open, it needs an answer from whoever owns that form rather than from me. Nothing in this PR changes that page beyond the port; the only thing pushed here since review is the /partners registration in legacy.ts.

// The six architecture pages are .vue files with no listing that links to them all, so the crawler never reaches them.
'/use-cases/data-integration/',
'/use-cases/edge-connectivity/',
Expand Down
96 changes: 96 additions & 0 deletions nuxt/pages/partners/certify-hardware.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script setup lang="ts">
// Ported from src/partners/certify-hardware.njk (11ty), which this replaces. Same page,
// same copy, same classes from src/css/style.css.
//
// What the port changes on purpose:
// - The step glyphs were {% include %}d raw inside .ff-certify-list-icon. They are all
// stock Heroicons, so they become <UIcon> from the installed set. .ff-certify-list-icon
// is w-[24px] with no height of its own, and <UIcon> renders a masked <span> with no
// intrinsic ratio, so each one is sized w-6 h-6 rather than left to fill the box.
// - ctaContactUs becomes <CtaContactUs>.
// - The Documentation link was written as "/../docs/device-agent/introduction/", which
// browsers resolve to /docs/... anyway. It is spelled that way here.
const TECHNICAL_STEPS = [
{ icon: 'i-heroicons-book-open', slot: 'repository' },
{ icon: 'i-heroicons-check-circle', text: 'Ensure that the Device Agent comes pre-installed on your device. Alternatively, it should be available from a store or marketplace as a "one-click" installer.' },
{ icon: 'i-heroicons-document-arrow-up', text: 'Users can easily upload their device configuration either through a custom user interface (e.g., file upload or input mask) or via the built-in Device Agent UI.' },
]

useSeoMeta({
title: 'How to Certify Your Hardware',
description: 'Follow these steps to get your hardware certified for compatibility with FlowFuse and Node-RED',
ogDescription: 'Follow these steps to get your hardware certified for compatibility with FlowFuse and Node-RED',
ogUrl: 'https://flowfuse.com/partners/certify-hardware/',
twitterSite: '@FlowFuseinc',
})
</script>

<template>
<div class="w-full page hero">
<div class="content">
<div class="py-20 px-6 md:px-0">
<h1><div class="m-auto max-w-xl text-center">How to Certify Your Hardware</div></h1>
<div class="max-w-[550px] m-auto gap-6 md:gap-2">
<h4 class="text-center m-auto text-indigo-400">Follow these steps to get your hardware certified for compatibility with FlowFuse and Node-RED.</h4>
</div>
</div>
<div class="w-full px-6 pb-20 md:px-0 flex flex-col gap-10 md:gap-12">
<div class="container max-w-screen-md m-auto flex flex-col gap-4">
<h3 class="m-auto text-center w-full mb-6">Technical Qualification in 3 Steps</h3>
<div class="ff-certify-list">
<div v-for="(step, i) in TECHNICAL_STEPS" :key="step.icon" class="ff-item">
<div class="ff-line-container" :class="{ 'sm:invisible': i === 0 }">
<div class="ff-line" />
</div>
<div class="ff-certify-list-icon"><UIcon :name="step.icon" class="w-6 h-6" /></div>
<div class="ff-line-container">
<div class="ff-line" :class="{ 'sm:hidden': i === TECHNICAL_STEPS.length - 1 }" />
</div>
<div class="font-light sm:row-span-3 col-span-3 sm:col-auto my-auto pt-6 sm:pt-0">
<template v-if="step.slot === 'repository'">
Explore the FlowFuse Device Agent
<a href="https://github.com/FlowFuse/device-agent" target="_blank" rel="noopener">Repository</a> and
<NuxtLink to="/docs/device-agent/introduction/">Documentation</NuxtLink>.
</template>
<template v-else>{{ step.text }}</template>
</div>
</div>
</div>
</div>
<hr class="w-full md:w-[768px] mx-auto">
<div class="container max-w-screen-md m-auto flex flex-col gap-4">
<h3 class="m-auto text-center w-full">Certification</h3>
<div class="flex flex-col gap-6 md:px-10">
<p class="w-full">After successfully navigating the technical qualification, take the next step by booking a meeting with our team. Together, we'll work towards ensuring your device is fully compatible with FlowFuse and Node-RED.</p>
<ul class="flex flex-row justify-center w-full items-center">
<li class="pb-6">
<CtaContactUs variant="primary" position="certify-hardware" class="inline-block w-[218px] text-center" />
</li>
</ul>
</div>
</div>
<hr class="w-full md:w-[768px] mx-auto">
<div class="container max-w-screen-md m-auto flex flex-col gap-4">
<h3 class="m-auto text-center w-full mb-6">Marketing and Publications</h3>
<div class="ff-certify-list">
<div class="ff-item">
<div class="ff-line-container sm:invisible"><div class="ff-line" /></div>
<div class="ff-certify-list-icon"><UIcon name="i-heroicons-chat-bubble-bottom-center-text" class="w-6 h-6" /></div>
<div class="ff-line-container"><div class="ff-line" /></div>
<div class="font-light sm:row-span-3 col-span-3 sm:col-auto my-auto pt-6 sm:pt-0">In a joint meeting, we will discuss marketing activities on a case-by-case basis.</div>
</div>
<div class="ff-item ff-certified">
<div class="ff-line-container"><div class="ff-line" /></div>
<div class="ff-certify-list-icon"><UIcon name="i-heroicons-check-badge" class="w-6 h-6" /></div>
<div class="ff-line-container"><div class="ff-line sm:hidden" /></div>
<div class="font-light sm:row-span-3 col-span-3 my-auto pt-6 sm:pt-0">Upon successful technical qualification, you will be granted the right to use the "FlowFuse Certified" logo.</div>
<div class="w-[86px] col-span-3 sm:row-span-3 m-auto pt-6 sm:pt-0">
<img src="/images/partners/ff-certified-device.svg" alt="FlowFuse certification badge" width="86" class="w-full h-auto">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
136 changes: 136 additions & 0 deletions nuxt/pages/partners/ctrlx.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<script setup lang="ts">
// Ported from src/partners/ctrlx.njk (11ty), which this replaces. Same page, same copy,
// same classes from src/css/style.css.
//
// What the port changes on purpose:
// - ctaBookDemo becomes <CtaBookDemo>.
useSeoMeta({
title: 'Node-RED Resources',
description: 'FlowFuse and ctrlX',
ogDescription: 'FlowFuse and ctrlX',
ogUrl: 'https://flowfuse.com/partners/ctrlx/',
twitterSite: '@FlowFuseinc',
})
</script>

<template>
<div class="w-full page hero">
<div class="content">
<div class="nohero w-full px-6">
<div class="w-full px-6 pt-8 md:pt-16 pb-16 md:px-0">
<div class="container md:m-auto text-center max-w-4xl flex flex-col items-center md:items-start">
<h1 class="mt-0 mb-3 text-4xl leading-[2.65rem] md:pl-0 md:pr-3 md:text-left md:max-w-lg">
Production Ready <span class="inline-block">Node-RED</span> for ctrlX AUTOMATION
</h1>
</div>
<div class="container m-auto md:-mt-6 text-center max-w-4xl flex flex-col md:flex-row md:text-left md:gap-8">
<p class="flex justify-center items-center mt-6 md:mt-0 md:w-1/2 text-lg">
FlowFuse offers Node-RED support and third party nodes for production use on ctlrX AUTOMATION
</p>
<div class="flex justify-center items-center mt-12 md:mt-0 md:w-1/2">
<div class="relative max-w-md">
<img src="/images/partners/nr-ctrlx.png" alt="Graphics depicting Node-RED compatibility with ctrlX." width="412" class="w-full h-auto">
</div>
</div>
</div>
<div class="container m-auto md:-mt-6 text-center max-w-4xl flex flex-col md:items-start mt-10">
<a
class="ff-btn ff-btn--primary flex flex-col"
href="https://developer.community.boschrexroth.com/t5/Store-and-How-to/FlowFuse-Node-RED/ba-p/82135"
target="_blank"
rel="noopener"
>
<span class="text-base uppercase md:px-4">Get Node-RED from ctrlX Store</span>
</a>
</div>
</div>

<div class="w-full pt-8 px-0 ff-prose">
<div class="text-center mt-4 md:mt-6 mb-6">
<h2>What FlowFuse Offers</h2>
</div>
<div class="container m-auto max-w-4xl">
<div class="grid px-6 md:px-0 grid-cols-1 md:grid-cols-2 gap-6 md:gap-10 sm:gap-x-8 sm:gap-y-0 mb-10">
<div class="prose text-left self-start">
<h3 class="flex items-center gap-4">
<div class="w-16">
<img src="/images/pictograms/results_blue.png" alt="Graphics depicting low-code programming." width="64" class="w-full h-auto">
</div>
<div class="flex flex-col leading-8">Professional Support</div>
</h3>
<p class="mb-0">
FlowFuse reduces the risk of using Node-RED in production. We offer professional support for
Node-RED deployments on the crtlX platform. Customers have direct access to Node-RED experts who can
help with development and production deployment issues.
</p>
</div>
<div class="prose text-left self-start">
<h3 class="flex items-center gap-4">
<div class="w-16">
<img src="/images/pictograms/node_catalog_blue.png" alt="Graphics depicting connectivity and integration." width="64" class="w-full h-auto">
</div>
<div class="flex flex-col leading-8">Support for Third Party Nodes</div>
</h3>
<p class="mb-0">
The Node-RED package for ctrlX includes pre-installs <span class="font-bold">third party nodes</span> for
popular industrial protocols, including OMRON, MC Protocol, Modbus and S7. FlowFuse will support the
use of these nodes in production.
</p>
</div>
</div>
</div>
</div>

<hr class="w-full md:w-[896px] mx-auto">

<div class="w-full pt-8 px-0 pb-6 ff-prose">
<div class="text-center mt-4 md:my-6">
<h2>For CtrlX Customers</h2>
</div>
<div class="container m-auto max-w-4xl">
<div class="grid px-6 md:px-0 grid-cols-1 md:grid-cols-2 gap-6 md:gap-10 sm:gap-x-8 sm:gap-y-0 mb-16">
<div class="text-left self-start h-full flex flex-col justify-between">
<div class="prose">
<h3 class="flex items-center gap-4">
<div class="w-16 mt-6">
<img src="/images/pictograms/support_blue.png" alt="Graphics depicting low-code programming." width="64" class="w-full h-auto">
</div>
<div class="flex flex-col leading-8 mt-6">Customer Support</div>
</h3>
<p class="mb-0">
Get in touch with us to access expert guidance and comprehensive assistance for your Node-RED
deployments. Our team will support you every step of the way, ensuring seamless integration and
successful implementation.
</p>
</div>
<div class="container text-center max-w-4xl flex flex-col md:items-start mt-6 md:mt-8">
<NuxtLink class="ff-btn ff-btn--primary-outlined flex flex-col" to="/support">
<span class="text-base uppercase no-underline md:px-4">CONTACT SUPPORT</span>
</NuxtLink>
</div>
</div>
<div class="text-left self-start">
<div class="mt-4 md:mt-0 prose">
<h3 class="flex items-center gap-4">
<div class="w-14 pb-2 mt-6 md:justify-start md:items-start">
<img src="/images/flowfuse-icon.png" alt="Graphics depicting low-code programming." width="64" class="w-full h-auto">
</div>
<div class="flex flex-col leading-8 mt-6">Upgrade to FlowFuse</div>
</h3>
<p class="mb-0">
CtrlX customers can update their Node-RED deployments to use the FlowFuse platform to take
advantage of our device management, team collaboration, software delivery pipelines and other
enterprise features. Book a demo to discover the FlowFuse platform.
</p>
</div>
<div class="container m-auto text-center max-w-4xl flex flex-col md:items-start mt-6 md:mt-8">
<CtaBookDemo variant="primary" position="hero" class="no-underline flex flex-col" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
113 changes: 113 additions & 0 deletions nuxt/pages/partners/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<script setup lang="ts">
// Ported from src/partners/index.njk (11ty), which this replaces. Same page, same copy,
// same classes from src/css/style.css.
//
// What the port changes on purpose:
// - The section headings carried <span class="text-indigo-600"> in frontmatter, printed
// with `| safe`. They are page-local consts rendered with v-html, the same trust
// boundary: nothing here comes from outside the repo.
// - The .njk set a `title`, so layouts/page.njk's hero branch emitted an <h1> reading
// "FlowFuse Partners" above a body that writes no heading of its own. That heading is
// kept as this page's own <h1>.

const SECTIONS = [
{
title: '<span class="text-indigo-600">Cloud</span> Providers',
description: 'FlowFuse is available for deployment from the marketplace of the following Cloud providers.',
partners: [
{ name: 'Amazon Web Services', logo: '/images/partners/logo-aws.png', url: 'https://aws.amazon.com/marketplace/pp/prodview-3ycrknfg67rug' },
{ name: 'Digital Ocean', logo: '/images/partners/logo-digital-o.png', url: 'https://marketplace.digitalocean.com/apps/flowforge' },
],
},
{
title: '<span class="text-indigo-600">Hardware</span> Partners',
description: 'FlowFuse partners with key industry hardware partners to provide an integrated experience using Node-RED and FlowFuse.',
ctaText: 'CERTIFY YOUR HARDWARE',
ctaUrl: '/partners/certify-hardware/',
partners: [
{ name: 'Bosch Rexroth', logo: '/images/partners/logo-rexroth.png', url: '/partners/ctrlx/' },
{ name: 'NCD.io', logo: '/images/partners/logo-ncd-io.png', url: 'https://ncd.io/' },
{ name: 'Wago', logo: '/images/partners/logo-wago.png', url: 'https://www.wago.com/global/' },
],
},
{
title: '<span class="text-indigo-600">Solutions</span> Partners',
subtitle: 'Build and Deploy Enterprise-Ready Solutions',
description: 'Our Solutions Partners, trusted resellers and system integrators, help you design, implement, and manage production-ready applications with Node-RED and FlowFuse. They provide:',
ctaText: 'APPLY NOW',
ctaUrl: '/partners/referral-sign-up/',
bulletPoints: [
'Expertise in enterprise industrial IoT, SCADA, MES, and UNS',
'Specialized, local support and services',
'Seamless integration with industry-specific tools',
'Scalable solutions tailored to your business needs',
],
partners: [
{ name: 'Gallarus', logo: '/images/partners/logo-gallarus.png', url: 'https://gis.ie/' },
{ name: 'Idoneos', logo: '/images/partners/logo-idoneos.png', url: 'https://idoneos.com/' },
{ name: 'Iniationware', logo: '/images/partners/logo-iniationware.png', url: 'https://iniationware.eu/' },
{ name: '4.0 Hero', logo: '/images/partners/logo-40hero.png', url: 'https://40hero.com/' },
{ name: 'Mayker', logo: '/images/partners/logo-mayker.png', url: 'https://mayker.eu/' },
],
},
]

const DESCRIPTION = 'FlowFuse partners with leading cloud, hardware, technology and consulting companies to provide a complete solution that allows our customers to deliver results using Node-RED and FlowFuse.'

useSeoMeta({
title: 'FlowFuse Partners',
description: DESCRIPTION,
ogDescription: DESCRIPTION,
keywords: 'FlowFuse Partners, Node-RED System Integrator',
ogUrl: 'https://flowfuse.com/partners/',
twitterSite: '@FlowFuseinc',
})
</script>

<template>
<div class="w-full page hero">
<div class="w-full">
<div class="hero container m-auto text-center flex flex-wrap pt-6 px-6 pb-12 md:flex-nowrap md:max-w-4xl md:pt-12">
<div class="mx-auto max-w-screen-xl md:max-w-xl">
<h1>FlowFuse Partners</h1>
<p class="lead-p m-auto mt-3">{{ DESCRIPTION }}</p>
</div>
</div>
</div>
<div class="content">
<div class="partners mx-auto w-full flex flex-col gap-4">
<div v-for="section in SECTIONS" :key="section.ctaUrl || section.title" class="w-full py-14 px-6">
<div class="max-w-screen-lg m-auto grid grid-cols-1 md:grid-cols-2 md:gap-x-10 gap-x-6 md:items-start md:grid-rows-[auto_minmax(20px,_1fr)]">
<div class="w-full">
<!-- eslint-disable-next-line vue/no-v-html -->
<h3 class="max-md:text-center w-full" v-html="section.title" />
<h5 v-if="section.subtitle" class="m-auto max-md:text-center w-full font-normal">{{ section.subtitle }}</h5>
<p class="mt-8">{{ section.description }}</p>
<div v-if="section.bulletPoints" class="prose ff-prose">
<ul>
<li v-for="point in section.bulletPoints" :key="point">{{ point }}</li>
</ul>
</div>
</div>
<ul class="grid grid-cols-2 justify-center w-full items-center gap-4 md:row-span-2 max-md:mt-6">
<a
v-for="partner in section.partners"
:key="partner.name"
:href="partner.url"
target="_blank"
class="partner-logo flex justify-center align-center items-center h-[90px] bg-white px-6 py-4 border rounded-lg hover:drop-shadow-lg transition ease-in duration-300"
>
<img :src="partner.logo" :alt="`${partner.name} logo`" loading="lazy" class="max-h-full w-auto">
</a>
</ul>
<div v-if="section.ctaText && section.ctaUrl" class="max-md:mx-auto mt-6 pt-6 md:pt-0 max-md:mt-8">
<NuxtLink :to="section.ctaUrl" class="text-center inline-block ff-btn ff-btn--primary uppercase">
<span>{{ section.ctaText }}</span>
</NuxtLink>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
Loading
Loading