[{"data":1,"prerenderedAt":387},["ShallowReactive",2],{"agmd-flowfuse-app-delivery-methods":3,"application-guide-nav":283},{"id":4,"title":5,"blurb":6,"body":7,"description":20,"extension":273,"guide":274,"meta":275,"navOrder":276,"navTitle":5,"navigation":277,"parent":278,"path":279,"seo":280,"slug":13,"stem":281,"__hash__":282},"applicationGuideDoc\u002Fapplication-guide\u002Fflowfuse\u002Fapp-delivery-methods.md","App delivery methods","Two different units of code, delivered two ways. Ship the whole app — a complete, versioned project promoted through environments — or publish one reusable piece — a package the whole team installs and upgrades in one place. Pick by what you're shipping: the app, or a part of it.",{"type":8,"value":9,"toc":269},"minimark",[10,14,21,23,233,251],[11,12,5],"h1",{"id":13},"app-delivery-methods",[15,16,17],"p",{},[18,19,20],"strong",{},"App delivery methods — start here",[15,22,6],{},[24,25,26,127],"guide-tabs",{},[27,28,30,36,41,44,50,56,61,101,117,123],"guide-tab",{"label":29},"Whole app",[15,31,32,35],{},[18,33,34],{},"Snapshots & pipelines"," — promote a complete, versioned project through dev → staging → prod to every place that runs it.",[37,38],"flow-diagram",{":edges":39,":nodes":40},"[{\"from\":\"golden\",\"to\":\"fleet\",\"accent\":\"indigo\",\"label\":\"snapshot · pipeline\"}]","[{\"id\":\"golden\",\"label\":\"Dev instance\",\"sub\":\"the golden one you build & test\",\"accent\":\"indigo\"},{\"id\":\"fleet\",\"label\":\"Instances\",\"sub\":\"every place it runs\",\"accent\":\"slate\",\"many\":true}]",[15,42,43],{},"Take the whole app — every flow, setting and dependency — as a versioned snapshot, then promote that one controlled build through pipeline stages to every place that should run it.",[15,45,46,49],{},[18,47,48],{},"Use it when"," — You're shipping a complete application and every site should run the same, controlled version.",[15,51,52,55],{},[18,53,54],{},"How it works"," — A pipeline promotes a snapshot dev → staging → production; each target is parameterised by its own env vars, so one controlled build serves every site.",[15,57,58],{},[18,59,60],{},"Major components",[62,63,64,75,84,93],"ul",{},[65,66,67,74],"li",{},[18,68,69],{},[70,71,73],"a",{"href":72},"\u002Fdocs\u002Fuser\u002Fsnapshots\u002F","Snapshot"," — the whole app, frozen as one versioned build",[65,76,77,83],{},[18,78,79],{},[70,80,82],{"href":81},"\u002Fdocs\u002Fuser\u002Fdevops-pipelines\u002F","Pipeline"," — promotes that snapshot through dev → staging → prod",[65,85,86,92],{},[18,87,88],{},[70,89,91],{"href":90},"\u002Fdocs\u002Fuser\u002Fconcepts\u002F#instance","Dev instance"," — where you build and test the project",[65,94,95,100],{},[18,96,97],{},[70,98,99],{"href":90},"Remote \u002F Hosted Instances"," — the fleet each snapshot rolls out to",[15,102,103,106,107,111,112,116],{},[18,104,105],{},"Where config & data live"," depends on the kind of app you're shipping — a hardware app tied to a device, or a software app on the platform. See ",[70,108,110],{"href":109},"\u002Fapplication-guide\u002Fflowfuse\u002Fhardware-apps\u002F","Hardware apps →"," and ",[70,113,115],{"href":114},"\u002Fapplication-guide\u002Fflowfuse\u002Fsoftware-apps\u002F","Software apps →",".",[15,118,119,122],{},[18,120,121],{},"More phases when you need them"," — a pipeline isn't limited to two stages. Add the phases your process needs — an extra staging tier, an approval gate, per-region rollouts — each one a controlled promotion of the same golden build:",[37,124],{":edges":125,":nodes":126},"[\"dev>stage\",\"stage>prod\"]","[{\"id\":\"dev\",\"label\":\"Dev\",\"sub\":\"golden build\",\"accent\":\"indigo\"},{\"id\":\"stage\",\"label\":\"Staging\"},{\"id\":\"prod\",\"label\":\"Production\",\"sub\":\"every place it runs\",\"accent\":\"slate\",\"many\":true}]",[27,128,130,136,141,148,153,165,169,215,219],{"label":129},"Pieces",[15,131,132,135],{},[18,133,134],{},"Subflow export"," — publish one piece as a package the team installs, like a shared library.",[37,137],{":edges":138,":nodes":139,":legend":140},"[{\"from\":\"sub\",\"to\":\"node\",\"label\":\"export as\"},{\"from\":\"node\",\"to\":\"inst\",\"accent\":\"red\",\"dashed\":true,\"label\":\"install\"},{\"from\":\"inst\",\"to\":\"bom\",\"label\":\"version-tracked\"}]","[{\"id\":\"sub\",\"label\":\"Subflow\",\"sub\":\"reusable block\",\"accent\":\"indigo\"},{\"id\":\"node\",\"label\":\"Custom node\",\"sub\":\"installable package\",\"accent\":\"slate\"},{\"id\":\"inst\",\"label\":\"Instances\",\"sub\":\"install & run the piece\",\"accent\":\"indigo\",\"many\":true},{\"id\":\"bom\",\"label\":\"Bill of Materials\",\"sub\":\"which version each runs\",\"accent\":\"slate\"}]","[{\"line\":\"red\",\"dashed\":true,\"label\":\"install\"},{\"line\":\"neutral\",\"label\":\"version-tracked\"}]",[15,142,143,144,147],{},"Package a single piece of a flow — a block of logic or UI — as a reusable subflow, export it as a ",[18,145,146],{},"custom node"," other apps install, and pull it in instead of copying code between projects.",[15,149,150,152],{},[18,151,48],{}," — A part of an app should be reused across many apps and upgraded in one place — a shared library, not a whole application.",[15,154,155,157,158,160,161,164],{},[18,156,54],{}," — Export the subflow as a ",[18,159,146],{}," — an installable package apps pull in like any library dependency. Apps install it and the Bill of Materials tracks every version in use. Share an ",[18,162,163],{},"example flow"," in the Team Library to show how to wire it up.",[15,166,167],{},[18,168,60],{},[62,170,171,180,189,198,206],{},[65,172,173,179],{},[18,174,175],{},[70,176,178],{"href":177},"\u002Fdocs\u002Fuser\u002Fpackaging-subflows\u002F","Subflow"," — the one reusable piece you package",[65,181,182,188],{},[18,183,184],{},[70,185,187],{"href":186},"\u002Fdocs\u002Fuser\u002Fcustom-npm-packages\u002F","Custom node"," — the installable package your subflow is exported to",[65,190,191,197],{},[18,192,193],{},[70,194,196],{"href":195},"\u002Fdocs\u002Fuser\u002Fshared-library\u002F","Team Library"," — example flows the team shares (a custom node can ship with one to show its use)",[65,199,200,205],{},[18,201,202],{},[70,203,204],{"href":90},"Instances"," — the apps that install and run the piece",[65,207,208,214],{},[18,209,210],{},[70,211,213],{"href":212},"\u002Fdocs\u002Fuser\u002Fbill-of-materials\u002F","Bill of Materials"," — tracks which version each app runs",[15,216,217],{},[18,218,105],{},[62,220,221,227],{},[65,222,223,226],{},[18,224,225],{},"Config"," — the subflow's instance properties \u002F env where it's installed.",[65,228,229,232],{},[18,230,231],{},"Distribution"," — export once as a custom node; apps install and upgrade from it, like a library.",[234,235,237],"callout",{"icon":236},"i-lucide-triangle-alert",[15,238,239,242,243,246,247],{},[18,240,241],{},"Dev and prod in the same team?"," Every instance on a team reaches the same shared resources — the Team Broker, FlowFuse Tables, project links, any external Postgres. So a dev instance can read and write the very data prod depends on. ",[18,244,245],{},"Name and namespace resources per environment"," so test data and real data never mix: separate broker topic prefixes, table or schema names, and project-link targets, driven by each instance's env vars. ",[70,248,250],{"href":249},"\u002Fapplication-guide\u002Fflowfuse\u002Fdata-plane\u002F","See the Data plane →",[234,252,254],{"icon":253},"i-lucide-git-branch",[15,255,256,257,260,261,264,265],{},"Dev and prod on ",[18,258,259],{},"separate servers"," — dev in IT or the cloud, prod in OT or air-gapped? A ",[18,262,263],{},"GitHub bridge"," carries the same versioned code across the boundary. That's an architecture decision. ",[70,266,268],{"href":267},"\u002Fapplication-guide\u002Fflowfuse\u002Farchitectures\u002F","See Architectures →",{"title":270,"searchDepth":271,"depth":271,"links":272},"",4,[],"md","flowfuse",{},3,true,null,"\u002Fapplication-guide\u002Fflowfuse\u002Fapp-delivery-methods",{"title":5,"description":20},"application-guide\u002Fflowfuse\u002Fapp-delivery-methods","NHYFkSzl0gpl2H3u5ISHR5TfmnlFVh0aV64mluKfTtY",[284,290,294,300,303,305,310,315,320,325,330,336,340,345,351,357,362,367,372,377,381],{"guide":274,"slug":285,"title":286,"navOrder":287,"parent":278,"blurb":288,"path":289},"overview","Overview",1,"The map of the FlowFuse guide — apps, architectures, and a worked example.","\u002Fapplication-guide\u002Fflowfuse\u002Foverview\u002F",{"guide":291,"slug":285,"title":286,"navOrder":287,"parent":278,"blurb":292,"path":293},"node-red","The map of the Node-RED guide — the pattern families that turn an app into a clean flow.","\u002Fapplication-guide\u002Fnode-red\u002Foverview\u002F",{"guide":274,"slug":295,"title":296,"navOrder":297,"parent":278,"blurb":298,"path":299},"foundations","Foundations",2,"The foundation to build on: what FlowFuse is, its core pieces, and how code is shared across teams.","\u002Fapplication-guide\u002Fflowfuse\u002Ffoundations\u002F",{"guide":291,"slug":295,"title":296,"navOrder":297,"parent":278,"blurb":301,"path":302},"The handful of concepts you need to build with Node-RED, and how they fit together.","\u002Fapplication-guide\u002Fnode-red\u002Ffoundations\u002F",{"guide":274,"slug":13,"title":5,"navOrder":276,"parent":278,"blurb":6,"path":304},"\u002Fapplication-guide\u002Fflowfuse\u002Fapp-delivery-methods\u002F",{"guide":291,"slug":306,"title":307,"navOrder":276,"parent":278,"blurb":308,"path":309},"patterns","Patterns","The moves that turn an architecture into a clean, reusable flow — find the seams and reuse well, then handle data on the right paths.","\u002Fapplication-guide\u002Fnode-red\u002Fpatterns\u002F",{"guide":274,"slug":311,"title":312,"navOrder":313,"parent":13,"blurb":314,"path":109},"hardware-apps","Hardware apps",3.1,"The three shapes a FlowFuse app takes when it runs on a device. Pick by how much varies per site: nothing (Packaged App), a few settings (Configurable App), or you assemble it yourself (Edge Building Block).",{"guide":291,"slug":316,"title":317,"navOrder":313,"parent":306,"blurb":318,"path":319},"design-patterns","Design patterns","The structural choices you select for a flow: find the seams it breaks into, then reuse each piece at the lightest level that solves it — link in\u002Fout, link call, subflow, or packaged node.","\u002Fapplication-guide\u002Fnode-red\u002Fdesign-patterns\u002F",{"guide":274,"slug":321,"title":322,"navOrder":323,"parent":13,"blurb":324,"path":114},"software-apps","Software apps",3.2,"The three shapes a FlowFuse app takes when it runs on the platform. Pick by what it needs: a headless job (Packaged App), a user-facing app driven by data (Data-Driven App), or a reusable piece other apps embed (Shared Building Block).",{"guide":291,"slug":326,"title":327,"navOrder":323,"parent":306,"blurb":328,"path":329},"handling-data","Handling data","Classify each signal by shape, purpose and direction, then pick the methods it needs — separate the paths, pace the flow, hold state in context, and manage config. The methods you select to move a flow's data.","\u002Fapplication-guide\u002Fnode-red\u002Fhandling-data\u002F",{"guide":291,"slug":331,"title":332,"navOrder":333,"parent":306,"blurb":334,"path":335},"good-form","Good form",3.3,"A clean flow isn't luck — it's a handful of habits. Wire for reading, lay it out on a grid, decouple UI from logic, catch errors where you can see them, and keep data on a stable contract. Follow these and a flow stays readable, reusable, and out of spaghetti.","\u002Fapplication-guide\u002Fnode-red\u002Fgood-form\u002F",{"guide":274,"slug":337,"title":338,"navOrder":271,"parent":278,"blurb":339,"path":249},"data-plane","Data plane","Before you pick where things run, decide how data is handled. Two stores come built into every FlowFuse server install — the Team Broker and relational Tables — exposed to every instance with nothing extra to stand up. Everything else you bring your own: run it (a time-series DB, an existing database, a model) and expose it to the fleet over Project Link, no inbound ports. This is the data plane the architectures on the next pages all sit on.",{"guide":291,"slug":341,"title":342,"navOrder":271,"parent":278,"blurb":343,"path":344},"worked-examples","Worked examples","Turn an app concept into a Node-RED flow — or a few — leaning on the design patterns and data handling. The method, then the OEE apps end to end.","\u002Fapplication-guide\u002Fnode-red\u002Fworked-examples\u002F",{"guide":291,"slug":346,"title":347,"navOrder":348,"parent":341,"blurb":349,"path":350},"oee-edge-aggregator","OEE - Edge Aggregator",4.1,"The edge app from the OEE use case as a Node-RED flow — a straight-line flow packaged as a subflow and configured per line (its PLC tags, via a config UI and a get-config node), with the data treated as a stream and its counts held in context.","\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator\u002F",{"guide":291,"slug":352,"title":353,"navOrder":354,"parent":341,"blurb":355,"path":356},"oee-central-dashboard","OEE - Central Dashboard",4.2,"The cloud app from the OEE use case as a Node-RED flow — one link out fanning to two link ins on separate tabs (dashboard and batched history), so the live and history paths stay separate and easy to read.","\u002Fapplication-guide\u002Fnode-red\u002Foee-central-dashboard\u002F",{"guide":274,"slug":358,"title":359,"navOrder":360,"parent":278,"blurb":361,"path":267},"architectures","Architectures",5,"Every FlowFuse deployment is the same building blocks arranged for where it runs — pick the world you're designing for.",{"guide":274,"slug":363,"title":364,"navOrder":365,"parent":358,"blurb":278,"path":366},"it-architectures","IT architectures",5.1,"\u002Fapplication-guide\u002Fflowfuse\u002Fit-architectures\u002F",{"guide":274,"slug":368,"title":369,"navOrder":370,"parent":358,"blurb":278,"path":371},"ot-architectures","OT architectures",5.2,"\u002Fapplication-guide\u002Fflowfuse\u002Fot-architectures\u002F",{"guide":274,"slug":373,"title":374,"navOrder":375,"parent":358,"blurb":278,"path":376},"iiot-architectures","IIoT architectures",5.3,"\u002Fapplication-guide\u002Fflowfuse\u002Fiiot-architectures\u002F",{"guide":274,"slug":341,"title":342,"navOrder":378,"parent":278,"blurb":379,"path":380},6,"Start from a use case, break it into apps, and draw the architecture that ties them together — the same method a FlowFuse Proof of Value runs.","\u002Fapplication-guide\u002Fflowfuse\u002Fworked-examples\u002F",{"guide":274,"slug":382,"title":383,"navOrder":384,"parent":341,"blurb":385,"path":386},"worked-example","OEE, end to end",6.1,"One use case — OEE across three lines — broken into two apps and two shared services, then drawn out end to end.","\u002Fapplication-guide\u002Fflowfuse\u002Fworked-example\u002F",1788279697331]