Hi Ben, that’s one to get the brain juices flowing at the start of the week:
Five main patterns for building your FEM app on Speckle - ALL SPECULATIVE off the top of my head but flexible:
- A Config model that holds all your app’s configuration and registry data in a single place.
- Using Speckle as your sole database, where every piece of data —geometry, results, and even user settings —lives in versioned Speckle objects.
- A hybrid approach that combines Speckle’s 3d data store with an external database for relational or user-scoped data.
- Fingerprinting your Speckle projects to mark exactly which ones belong to your FEM workflow.
- A grab-bag of additional patterns, from remote references to Automate workflows and multi-model composition.
1. “Project Config” Model for App-Wide Key ↔ Dict
Data
Rather than scattering app-wide settings and stream references across multiple places, you create a dedicated “Config” model. In practice, you publish a single object tree to the Config
model. Then, whenever your web app starts up, it simply fetches the latest version of config
to learn your UI theme, concurrency limits, any feature flags, and the list of FEM project IDs you’ve onboarded. This keeps all your key→dict
data in one versioned, centrally queryable location.
globals = {
registry: [
{ projectId: "abc123", purpose: "FEM", label: "Tower Analysis" },
…
]
}
COMMIT globals AS latest Version TO Globals/main
Your app fetches the latest Version from Globals/main
to read configuration, feature flags, and registry data.
2. Speckle as Your Sole Database
If you want a single source of truth, you can store everything in Speckle. You carve out separate models for each domain, one for FEM geometry, one for user profiles, one for config and you commit JSON-like “Base” trees to versions in those models. Real-time GraphQL subscriptions or webhooks drive your UI updates, and Speckle’s content-addressable storage automatically deduplicates identical objects. Stroing indecies in you data model can aid GraphQl queries down the line in entirely bespoke ways.
Store everything in Speckle—geometry, analysis inputs, results, and even user-scoped settings:
- Models for each domain (e.g.
models
, users
, config
)
- Versions contain arbitrary JSON-like objects (“Base” trees)
- Subscriptions drive real-time UI updates when new Versions arrive
Pros
- Single source of truth, full version history
- Automatic deduplication of identical objects
Cons & Mitigations
- Ad-hoc filtering/joins can be slower—embed simple indices in your objects or rely on GraphQL filters
- Transactional or truly private data may be better suited to a dedicated database
3. Speckle as Data Store + Augmented Database
In a hybrid pattern, Speckle remains the home of versioned 3D and analysis data, but you layer on a lightweight external database, Firebase, PostgreSQL, MongoDB, for anything relational or user-scoped (permissions, audit logs, indexed result summaries). On each new version in Speckle (detected via webhook or subscription), your analysis service pulls the model, runs calculations, and writes results to the external DB keyed by projectId + versionId. The client then embeds the Speckle Viewer or SDK to load geometry and separately calls your DB API to fetch the analysis outputs, overlaying charts or annotations on the 3D scene. This gives you the best of both worlds: Speckle’s rich data exchange plus your database’s fast filtering and joins.
- Speckle holds versioned 3D and analysis data.
- External DB holds relational or user-scoped data (profiles, permissions, indexed result summaries).
- On each new Version in Speckle (via webhook or subscription), trigger your analysis service to:
- Pull the new data
- Run calculations
- Write results into the external DB, keyed by
projectId
+ versionId
- In your web app:
- Load the model via the embedded Speckle Viewer or SDK
- Fetch analysis results from your DB API
- Overlay charts or annotations in the client
This keeps Speckle focused on shareable 3D data while leveraging the database for fast filtering and joins.
4. Fingerprinting Projects for Your FEM App
To mark which Speckle projects are part of your FEM app, you have three light-touch options:
- Registry Versions
In a dedicated APP_REGISTRY/main
model you commit an object with fields like appFingerprint: "MyFEM-App-v1"
, the target projectId
, and timestamp. Your app queries that model for versions where appFingerprint == "MyFEM-App-v1"
to discover exactly which projects to load.
- Tags on Projects
Simply assign tags such as ["fem-app","v1"]
to each target project. A GraphQL filter on projects by tag “fem-app” instantly yields your app’s streams.
- Naming Convention
Enforce a prefix on project names (e.g. femapp-bridge
, femapp-tower
) and query for projects whose names start with that prefix.
All three keep your fingerprint data in Speckle’s data layer (versions or tags), avoiding the pitfalls of using the user-editable description field.
-
Registry Version
registryEntry = {
appFingerprint: "MyFEM-App-v1",
projectId: "def456",
modelName: "main",
createdAt: "2025-04-28T12:34:00Z"
}
COMMIT registryEntry AS new Version TO APP_REGISTRY/main
Then query all Versions in APP_REGISTRY/main
where appFingerprint == "MyFEM-App-v1"
to list registered projects.
-
Tags on Projects
SET tags = ["fem-app","v1"] ON each target project
Then filter projects by tag “fem-app” to discover your app’s streams.
- Naming Convention
- Prefix project names with
femapp-
(e.g. femapp-bridge
, femapp-tower
)
- Filter projects whose names start with that prefix
Avoid stuffing JSON into the description field—users can edit it, and it may be truncated. Versions and tags live safely in the data layer.
5. Other Patterns & Options
- Remote References / Detachment
Reference shared sub-objects across projects to avoid re-uploading large meshes.
- Version Messages or Dedicated Mesage Models
Embed small structured metadata in commit messages or a special branch for annotations.
- Speckle Automate
Watch for new Versions, run serverless or containerised calculations, and write results back as child Versions or metadata.
- Multi-Model Composition
Use a single project with multiple Models (e.g. “passA”, “passB”), then a “master” Model that references each pass via detached references.
indeed im quite exceited to see if we can work with you on getting something scaffolded here - a web application that is polling ofor automate results is definitely on my agenda…
cc: @chuck