Architecture¶
Flowinator is a local-first Moho Lua package. It is intentionally split into small modules so UI changes, metadata rules, and file operations do not become one large script.
Runtime entry point¶
Moho discovers the menu script first:
menu/Flowinator.lua
-> adds ScriptResources/Flowinator to package.path
-> loads ui.lua
-> opens the modeless Flowinator window
Flowinator.lua is deliberately thin. It registers the Script-menu item, resolves the installed script location, and loads the UI module. It also keeps the UI module alive while the window is open so Moho cannot create duplicate Flowinator windows.
The UI is a native LM.GUI.SimpleDialog modeless window. Flowinator does not use a browser, database, external process, or background service for its main workflow.
Module boundaries¶
ui.lua
project.lua users.lua assets.lua shots.lua versions.lua
\ | | | /
metadata.lua
|
json.lua
|
paths.lua
| Module | Responsibility | Should not contain |
|---|---|---|
ui.lua |
Native dialogs, list selection state, labels, button handlers, confirmation prompts, and focused UI refreshes. | Direct JSON encoding, raw file-path rules, or duplicated version logic. |
project.lua |
Project folder creation, project.json, recent-project state, and project updates. |
Asset or shot hierarchy behavior. |
users.lua |
Local users, roles, login session state, and permission checks. | UI controls or workfile saves. |
assets.lua |
Asset type/name/variant/work-branch metadata. | Shot-specific hierarchy logic. |
shots.lua |
Episode/sequence/shot hierarchy and shot work branches. | Asset-specific folder rules. |
versions.lua |
Workfile saving, version numbering, publish copies, Live files, previews, and Moho load/import/reference actions. | Selection widgets or project settings UI. |
metadata.lua |
Read/write JSON documents safely through the local encoder. | Business decisions about metadata fields. |
json.lua |
Dependency-free JSON encoder and decoder. | File-system access. |
paths.lua |
Path joining, relative paths, folders, copying, moving, and platform-specific folder opening. | Project-specific naming rules. |
recycle.lua |
Non-destructive deletion into the project recycle tree. | Version generation or UI state. |
When adding a feature, place the rule in the module that owns its data. The UI should call a small module function and refresh only the controls affected by the result.
Data and folder model¶
Each Flowinator project is self-contained. Metadata is separate from .moho files:
PROJECT_ROOT/
00_Pipeline/
Metadata/
project.json
users.json
session.json
assets.json
shots.json
previews/
01_Assets/
02_Scenes/
05_Publish/
99_Flowinator_Recycle/
The exact asset and shot workfile folders are derived from the selected hierarchy branch. Published files are kept separately under 05_Publish.
Relative paths¶
Metadata records project-relative paths whenever a file is inside the project root. At runtime, paths.lua resolves these paths against the currently selected root.
This is important for shared projects: one user can mount the project as G:\Show, another as T:\Show, and a macOS user can mount the same content under /Volumes/Show.
paths.lua compares paths case-insensitively on Windows and case-sensitively on Unix-like systems. Do not bypass it with custom string concatenation for project files.
Core hierarchy records¶
Assets and shots use a shared concept: a work branch. A work branch identifies the set of versions that belong together.
Asset: Type > Name > Variant > Work Type > Work Item
Shot: Episode > Sequence > Shot > Work Type > Work Item
The selected branch provides the naming context for its workfile, publish, and Live files. Default values are omitted from file names when appropriate so names stay readable.
Asset and shot metadata is stored as JSON arrays. Each mutation updates the relevant project metadata file once, rather than rebuilding the complete UI or repeatedly writing the same data.
Workfile and publish lifecycle¶
Workfiles¶
ui.luaresolves the current selection to an asset or shot branch.- It asks
versions.luato create a workfile or next version. versions.luacalculates the next available number, creates the destination folder, and asks Moho to save a numbered.mohofile.- It appends a record containing version, author, date, commit, and relative path.
- The owner module writes the updated metadata and the UI refreshes the current branch.
Numbered workfiles are append-only. Never implement a feature that overwrites an existing numbered file.
Publishing and Live¶
Publishing creates two related outputs:
- An immutable numbered publish, such as
P001orP002. - A stable
*_Live.mohocopy pointing to the latest approved publish for that branch.
The Live file is the integration target. Import Live brings it into the open scene, while Reference Live uses Moho's layer-reference behavior. A later publish replaces the stable Live copy but preserves all numbered publish versions.
UI update strategy¶
Moho's Lua UI is synchronous. Large, repeated list rebuilds are noticeable to users, especially for branches with many versions. Flowinator therefore follows these rules:
- Fill hierarchy lists left to right only after the preceding selection exists.
- Keep selection state in the UI module and invalidate downstream lists when an upstream selection changes.
- Refresh only the affected hierarchy controls after an add/delete action where possible.
- Cache known directories in
paths.luato avoid repeated folder-creation shell calls. - Keep preview work out of the normal version-save path unless explicitly requested.
When changing a list, preserve the existing selection if it remains valid. Avoid calling the full project refresh from a simple local add operation.
Platform behavior¶
Flowinator targets Moho Pro 14.x on Windows and macOS.
| Concern | Windows | macOS |
|---|---|---|
| Folder creation/removal | Native command-line tools through paths.lua |
POSIX shell commands through paths.lua |
| Open folder | start |
open |
| Preview resize | PowerShell with System.Drawing | Built-in sips |
| Path case comparison | Case-insensitive | Case-sensitive |
New file-system behavior must go through paths.lua and must not embed Windows-only commands inside UI code.
Permissions and destructive actions¶
users.lua exposes permission checks used by the UI:
- Project Admin can manage settings, users, and all project items.
- Artist can create work and delete only items they own.
UI delete actions must ask for confirmation and use recycle.lua. The action should preserve the original relative folder structure under 99_Flowinator_Recycle and remove the item from active metadata only after the move succeeds.
Adding a feature¶
Use this sequence for new pipeline capabilities:
- Define the project-relative data model and the module that owns it.
- Add a focused read/write function in that module.
- Reuse
metadata.luaandpaths.luafor persistence and paths. - Add the smallest UI control that calls the function.
- Refresh only affected controls and keep unrelated selections intact.
- Document user-visible behavior and manual verification steps.
Good extension points¶
- Publish validation before creating a publish copy.
- Dependency metadata beside version records.
- Review and approval state on publish versions.
- Render submission metadata.
- Optional remote synchronization layered above the existing JSON files.
Avoid¶
- Storing absolute workstation paths in project metadata.
- Adding cloud or database dependencies to basic local actions.
- Putting large file-operation logic directly in button handlers.
- Replacing append-only numbered versions with overwrites.
- Changing the shape of existing JSON records without a migration strategy.