diff --git a/nuxt/components/EnterpriseSecurity.vue b/nuxt/components/EnterpriseSecurity.vue new file mode 100644 index 0000000000..c49f38a81b --- /dev/null +++ b/nuxt/components/EnterpriseSecurity.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/nuxt/components/icons/AirGappedDeploymentIcon.vue b/nuxt/components/icons/AirGappedDeploymentIcon.vue new file mode 100644 index 0000000000..78f7b34816 --- /dev/null +++ b/nuxt/components/icons/AirGappedDeploymentIcon.vue @@ -0,0 +1,13 @@ + diff --git a/nuxt/components/icons/ArrowRightIcon.vue b/nuxt/components/icons/ArrowRightIcon.vue new file mode 100644 index 0000000000..e9b04b5fb6 --- /dev/null +++ b/nuxt/components/icons/ArrowRightIcon.vue @@ -0,0 +1,3 @@ + diff --git a/nuxt/components/icons/AuditLogsIcon.vue b/nuxt/components/icons/AuditLogsIcon.vue new file mode 100644 index 0000000000..d2176b8c25 --- /dev/null +++ b/nuxt/components/icons/AuditLogsIcon.vue @@ -0,0 +1,10 @@ + diff --git a/nuxt/components/icons/RoleBasedAccessIcon.vue b/nuxt/components/icons/RoleBasedAccessIcon.vue new file mode 100644 index 0000000000..60d9dc315b --- /dev/null +++ b/nuxt/components/icons/RoleBasedAccessIcon.vue @@ -0,0 +1,9 @@ + diff --git a/nuxt/components/icons/SingleSignOnIcon.vue b/nuxt/components/icons/SingleSignOnIcon.vue new file mode 100644 index 0000000000..66efe026e2 --- /dev/null +++ b/nuxt/components/icons/SingleSignOnIcon.vue @@ -0,0 +1,6 @@ + diff --git a/nuxt/components/icons/Soc2BadgeIcon.vue b/nuxt/components/icons/Soc2BadgeIcon.vue new file mode 100644 index 0000000000..4be78ccbbf --- /dev/null +++ b/nuxt/components/icons/Soc2BadgeIcon.vue @@ -0,0 +1,84 @@ + diff --git a/nuxt/nuxt.config.ts b/nuxt/nuxt.config.ts index 453e6a88a7..bdd538f507 100644 --- a/nuxt/nuxt.config.ts +++ b/nuxt/nuxt.config.ts @@ -237,6 +237,7 @@ export default defineNuxtConfig({ '/privacy-policy', '/integrations', '/pricing', + '/product', '/ebooks/beginner-guide-to-a-professional-nodered/', '/ebooks/ultimate-guide-to-building-applications-with-flowfuse-dashboard-for-node-red/', '/whitepaper/uns-decoupling-data-producers-and-consumers/', diff --git a/nuxt/pages/pricing/index.vue b/nuxt/pages/pricing/index.vue index 8117d578d4..e425229eb5 100644 --- a/nuxt/pages/pricing/index.vue +++ b/nuxt/pages/pricing/index.vue @@ -116,9 +116,15 @@ useSchemaOrg([ - + + + -
+ + +
+
+

+// Ported from src/platform/features.njk (11ty). Cta* components enforce +// fixed copy/destinations (see CLAUDE.md), so the old custom-copy "Request a +// Demo" buttons become ; "View Pricing" isn't one of the four +// unified destinations, so it keeps a plain ff-btn link, same precedent as +// BlogPostCta.vue's pricing fallback. +useSeoMeta({ + title: 'FlowFuse Features', + description: 'FlowFuse provides the features companies require to reliably deliver industrial applications to devices and cloud in a collaborative, secure manner.', + ogUrl: 'https://flowfuse.com/product/', + twitterSite: '@FlowFuseinc', +}) + +const capture = useCapture() + +const TIERS = [ + { + id: 'edge', + label: 'FlowFuse Edge', + heading: 'You run the plant floor', + description: 'Connect PLCs, machines, and controllers. Standardize automation across sites instead of reinventing it plant by plant. Built for OT and digitalization leadership running production at scale.', + idealFit: 'Ideal fit if you\'re dealing with: multi-plant rollouts, PLC/SCADA integration, machine connectivity, or Node-RED sprawl across sites.', + image: { src: '/images/home/home-scada.png', alt: 'FlowFuse Edge: industrial edge connectivity' }, + }, + { + id: 'hub', + label: 'FlowFuse Hub', + heading: 'You move data across the business', + description: 'Integrate and orchestrate data across ERPs, databases, and cloud APIs — governed centrally, not stitched together app by app. Built for central IT and enterprise architecture teams.', + idealFit: 'Ideal fit if you\'re dealing with: system integration, API orchestration, data pipelines, or governance across business systems.', + image: { src: '/images/product/hub.jpg', alt: 'FlowFuse Hub: enterprise data integration' }, + }, + { + id: 'fleet', + label: 'FlowFuse Fleet', + heading: 'You manage a Node-RED fleet', + description: 'Push flows, ship updates, and roll back remotely across thousands of distributed devices, without waiting on a firmware release. Built for hardware OEMs, partners, and asset operators.', + idealFit: "Ideal fit if you're dealing with: distributed devices, remote sites, sensors and telemetry at scale, or shipping Node-RED inside your own product.", + image: { src: '/images/product/fleet.jpg', alt: 'FlowFuse Fleet: device fleet management console' }, + }, +] + +const DIFFERENTIATORS = [ + { + heading: 'Vendor-Free Open Source', + description: 'Every factory is different, so why deploy the same solution as everyone else? Build your way with ready-made blueprints, your own app store, or anything in between — we never dictate your tools.', + icon: 'i-lucide-puzzle', + }, + { + heading: 'Flexible and Secure', + description: 'From whole-factory rollouts to last-mile fixes across any industry. Build your solution, then secure it with granular RBAC, auditing, version control, and traceability.', + icon: 'i-lucide-shield-check', + }, + { + heading: 'Seamless Collaboration', + description: 'OT teams prototype and deploy fast while IT keeps the governance, security, and auditability they need — no trade-offs.', + icon: 'i-lucide-handshake', + }, +] + +const CAPABILITIES = [ + { label: 'Industrial AI', to: '/ai/' }, + { label: 'IT/OT Middleware', to: '/use-cases/it-ot-middleware/' }, + { label: 'Unified Namespace', to: '/use-cases/uns/' }, + { label: 'MES', to: '/use-cases/mes/' }, + { label: 'SCADA', to: '/use-cases/scada/' }, + { label: 'Edge Connectivity', to: '/use-cases/edge-connectivity/' }, + { label: 'Data Integration', to: '/use-cases/data-integration/' }, +] +const activeTier = ref('edge') +const stepRefs = ref>({}) + +// Whichever step's top has crossed the viewport's vertical midpoint is active - +// walking the steps in DOM order and overwriting on each match means the +// deepest (furthest scrolled-to) step wins. An IntersectionObserver watching a +// thin band around the midpoint was tried first, but the gap between steps +// (mt-20/pt-20/border-t below) is wider than that band, so scrolling through +// a gap left neither step intersecting and the indicator stuck on whichever +// step was active before the gap. +function updateActiveTier () { + const steps = Object.entries(stepRefs.value).filter((entry): entry is [string, HTMLElement] => !!entry[1]) + if (!steps.length) return + const mid = window.innerHeight / 2 + let current = steps[0][0] + for (const [tier, el] of steps) { + if (el.getBoundingClientRect().top <= mid) current = tier + } + activeTier.value = current +} + +let tierTicking = false +function onTierScroll () { + if (!tierTicking) { tierTicking = true; requestAnimationFrame(() => { tierTicking = false; updateActiveTier() }) } +} + +onMounted(() => { + window.addEventListener('scroll', onTierScroll, { passive: true }) + window.addEventListener('resize', onTierScroll, { passive: true }) + updateActiveTier() +}) + +onUnmounted(() => { + window.removeEventListener('scroll', onTierScroll) + window.removeEventListener('resize', onTierScroll) +}) + + + diff --git a/nuxt/public/images/product/fleet.jpg b/nuxt/public/images/product/fleet.jpg new file mode 100644 index 0000000000..3d3b532dfc Binary files /dev/null and b/nuxt/public/images/product/fleet.jpg differ diff --git a/nuxt/public/images/product/flowfuse-ui.png b/nuxt/public/images/product/flowfuse-ui.png new file mode 100644 index 0000000000..75807b51f1 Binary files /dev/null and b/nuxt/public/images/product/flowfuse-ui.png differ diff --git a/nuxt/public/images/product/hub.jpg b/nuxt/public/images/product/hub.jpg new file mode 100644 index 0000000000..6803d38f61 Binary files /dev/null and b/nuxt/public/images/product/hub.jpg differ diff --git a/nuxt/redirects.ts b/nuxt/redirects.ts index 35b1ba83b1..d1bc2f649b 100644 --- a/nuxt/redirects.ts +++ b/nuxt/redirects.ts @@ -34,9 +34,9 @@ export const redirects: Record = { '/handbook/development/how-we-work/packaging/': { redirect: { to: '/handbook/engineering/packaging/', statusCode: 301 } }, '/handbook/development/how-we-work/contributing/': { redirect: { to: '/handbook/engineering/contributing/', statusCode: 301 } }, '/handbook/development/how-we-work/': { redirect: { to: '/handbook/engineering/', statusCode: 301 } }, - '/product/': { redirect: { to: '/platform/features/', statusCode: 301 } }, - '/product/why-flowfuse/': { redirect: { to: '/platform/features/', statusCode: 301 } }, - '/features/': { redirect: { to: '/platform/features/', statusCode: 301 } }, + '/platform/features/': { redirect: { to: '/product/', statusCode: 301 } }, + '/product/why-flowfuse/': { redirect: { to: '/product/', statusCode: 301 } }, + '/features/': { redirect: { to: '/product/', statusCode: 301 } }, '/blog/2024/03/flowfuse-self-hosted-starter-resource-limits/': { redirect: { to: '/blog/2024/03/flowfuse-self-hosted-open-source-resource-limits/', statusCode: 301 } }, '/unified-namespace/': { redirect: { to: '/use-cases/uns/', statusCode: 301 } }, '/solutions/manufacturing/': { redirect: { to: '/use-cases/it-ot-middleware/', statusCode: 301 } }, @@ -52,7 +52,7 @@ export const redirects: Record = { '/blueprints/other/remote-buffering/': { redirect: { to: '/blueprints/getting-started/store-and-forward/', statusCode: 301 } }, '/vs/tulip/': { redirect: { to: '/landing/tulip/', statusCode: 301 } }, '/product/security/': { redirect: { to: '/platform/security/', statusCode: 301 } }, - '/product/features/': { redirect: { to: '/platform/features/', statusCode: 301 } }, + '/product/features/': { redirect: { to: '/product/', statusCode: 301 } }, '/product/device-agent/': { redirect: { to: '/platform/device-agent/', statusCode: 301 } }, '/product/dashboard/': { redirect: { to: '/platform/dashboard/', statusCode: 301 } }, '/team/': { redirect: { to: '/about/', statusCode: 301 } }, diff --git a/nuxt/server/middleware/legacy.ts b/nuxt/server/middleware/legacy.ts index e6e60f891d..8839d8e6b5 100644 --- a/nuxt/server/middleware/legacy.ts +++ b/nuxt/server/middleware/legacy.ts @@ -10,7 +10,7 @@ const NUXT_ROUTES = new Set(['/terms', '/privacy-policy', '/integrations', '/res const NUXT_ROUTE_PREFIXES = ['/integrations/'] // Route prefixes handled by Nuxt (all paths starting with these are served by Nuxt). -const NUXT_PREFIXES = ['/handbook', '/ebooks', '/whitepaper', '/pricing', '/docs', '/changelog', '/application-guide', '/blog'] +const NUXT_PREFIXES = ['/handbook', '/ebooks', '/whitepaper', '/pricing', '/docs', '/changelog', '/application-guide', '/blog', '/product'] export default defineEventHandler(async (event) => { if (process.env.NODE_ENV !== 'development') return diff --git a/src/_data/chrome.json b/src/_data/chrome.json index d21dd985bd..e5393f1485 100644 --- a/src/_data/chrome.json +++ b/src/_data/chrome.json @@ -12,7 +12,7 @@ "links": [ { "label": "Features", - "href": "/platform/features/", + "href": "/product/", "icon": "star" }, { @@ -421,7 +421,7 @@ "links": [ { "label": "Features", - "href": "/platform/features/" + "href": "/product/" }, { "label": "Security Statement", diff --git a/src/_includes/cta-get-started.njk b/src/_includes/cta-get-started.njk index 23fa0d4b54..cd9ee2e768 100644 --- a/src/_includes/cta-get-started.njk +++ b/src/_includes/cta-get-started.njk @@ -1,4 +1,4 @@ -
+

{{ cta.title }}

{{ cta.description }}

{{ cta.buttonText }} diff --git a/src/css/style.css b/src/css/style.css index ac3dd1b825..b6f0e6ebc5 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -2470,6 +2470,12 @@ lite-youtube::before { color: var(--color-white); border: 1px solid var(--color-red-700); } + + /* Shared "Get Started" CTA backdrop - homepage (cta-get-started.njk and + its includers) and the /product page both use this exact gradient. */ + .ff-get-started-bg { + background: radial-gradient(ellipse 50% 150% at 50% 100%, var(--color-indigo-500), #211c64); + } } @layer utilities { diff --git a/src/platform/features.njk b/src/platform/features.njk deleted file mode 100644 index bf2241c1a1..0000000000 --- a/src/platform/features.njk +++ /dev/null @@ -1,300 +0,0 @@ ---- -layout: page -nohero: true -meta: - title: FlowFuse Features -description: - FlowFuse provides the features companies require to reliably deliver industrial applications to devices and cloud in a collaborative, secure manner. -sitemapPriority: 0.8 -enterprise: - heading: 'Built for Enterprise Manufacturing' - description: "FlowFuse is SOC 2 Type I and Type II certified, with role-based access control, single sign-on, audit logging, and air-gapped, self-hosted deployment options, built for the security and compliance requirements of large-scale manufacturing organizations." - badge: "components/icons/soc-2-badge.svg" - badgeLabel: "SOC 2 Type II" - items: - - icon: "components/icons/single-sign-on.svg" - label: "Single Sign-On" - - icon: "components/icons/audit-logs.svg" - label: "Audit Logs" - - icon: "components/icons/role-based-access.svg" - label: "Role-Based Access Control" - - icon: "components/icons/air-gapped-deployment.svg" - label: "Air-Gapped / Self-Hosted Deployment" - linkText: "Review our security and compliance details" - linkHref: "/platform/security/" ---- - - -
- -
-
- -
-
- -
-

- Build, deploy, and govern industrial applications - in record time. -

-

Bridge the gap between OT and IT teams using FlowFuse, the only comprehensive application platform with industrial AI and governance baked in.

- -
- -
-
- {% image "./images/features/flowfuse-features-hero.png", "FlowFuse Features", [750] %} -
-
-
- -
- -
-

- The needs of modern industry requires modern solutions -

- -
-
-

Vendor-Free Open Source

-

Every factory is different, so why deploy the same solution as everyone else? Build your way with ready-made blueprints, your own app store, or anything in between — we never dictate your tools.

-
-
-

Flexible and Secure

-

From whole-factory rollouts to last-mile fixes across any industry. Build your solution, then secure it with granular RBAC, auditing, version control, and traceability.

-
-
-

Seamless Collaboration

-

OT teams prototype and deploy fast while IT keeps the governance, security, and auditability they need — no trade-offs.

-
-
- -
-
-

Find the Product for How You Work

-
- - - -
- -
-
-
FlowFuse Edge
-

You run the plant floor

-

Connect PLCs, machines, and controllers. Standardize automation across sites instead of reinventing it plant by plant. Built for OT and digitalization leadership running production at scale.

-

Ideal fit if you're dealing with: multi-plant rollouts, PLC/SCADA integration, machine connectivity, or Node-RED sprawl across sites.

- Learn more about FlowFuse Edge → -
-
- {% image "./images/home/home-edge-connectivity.png", "FlowFuse Edge: industrial edge connectivity", [600] %} -
-
- -
-
-
FlowFuse Hub
-

You move data across the business

-

Integrate and orchestrate data across ERPs, databases, and cloud APIs — governed centrally, not stitched together app by app. Built for central IT and enterprise architecture teams.

-

Ideal fit if you're dealing with: system integration, API orchestration, data pipelines, or governance across business systems.

- Learn more about FlowFuse Hub → -
-
- {% image "./images/home/home-data-integration.png", "FlowFuse Hub: enterprise data integration", [600] %} -
-
- -
-
-
FlowFuse Fleet
-

You manage a Node-RED fleet

-

Push flows, ship updates, and roll back remotely across thousands of distributed devices, without waiting on a firmware release. Built for hardware OEMs, partners, and asset operators.

-

Ideal fit if you're dealing with: distributed devices, remote sites, sensors and telemetry at scale, or shipping Node-RED inside your own product.

- Learn more about FlowFuse Fleet → -
-
- {% image "./images/screen-pseudo-devices.png", "FlowFuse Fleet: device fleet management console", [600] %} -
-
- -
-
-
-
- - - -
-
-
-

The FlowFuse Platform is the Foundation for All of your IT/OT Applications

-

Leveraging enterprise-grade development, deployment, and governance solutions, you can build faster, scale more efficiently, and secure deployments of any size.

- -
- -
-
- -
-
-
-

{{ enterprise.heading | safe }}

-

{{ enterprise.description }}

- - {{ enterprise.linkText }} - {% include "components/icons/arrow-long-right.svg" %} - -
-
-
-
- {% include enterprise.badge %} -
-

{{ enterprise.badgeLabel }}

-
- {% for item in enterprise.items %} -
-
- {% include item.icon %} -
-

{{ item.label }}

-
- {% endfor %} -
-
-
- - -
-
-
-
-
-
-

Get Started with FlowFuse

-

Your first operational application could be running this week. Request a demo to see how, or explore pricing to find the right fit.

- -
-
-
-