You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/developer/developer-index.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,6 +17,10 @@ This section is designed for:
17
17
- Architects evaluating ODE architecture
18
18
- Contributors wanting to improve the codebase
19
19
20
+
:::tip AI coding assistants
21
+
Building **custom applications** (HTML, JS, CSS bundles and JSON forms) without cloning the ODE monorepo? Use the **[custom_app](https://github.com/OpenDataEnsemble/custom_app)** repository on GitHub (`AGENTS.md` and `CONTEXT_*.md` for assistants and authors), together with the main **[documentation](https://opendataensemble.org/docs/)** site.
22
+
:::
23
+
20
24
:::info Not developing?
21
25
If you're collecting data, see the [Data Collector Guide](/docs/collector/collector-index).
22
26
If you're designing forms, see the [Implementer Guide](/docs/implementer/implementer-index).
Copy file name to clipboardExpand all lines: docs/guides/custom-applications.md
+25-20Lines changed: 25 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,39 +10,42 @@ Complete guide to building and deploying custom applications that integrate with
10
10
11
11
## Overview
12
12
13
-
Custom applications are React applications that run within the Formulus mobile app, providing specialized workflows and user experiences. They allow you to create custom navigation, integrate with the ODE form system, and build specialized interfaces for specific use cases.
13
+
Custom applications are **web applications** (HTML, CSS, and JavaScript) that run inside the Formulus mobile app’s WebView. You may author them with **any** stack—plain static files, **Vite**, **React**, **Vue**, **Svelte**, or another bundler—**as long as the build output** can be packaged as described in the [app bundle format](/docs/reference/app-bundle-format) (entry HTML, assets, and `forms/` layout). They provide specialized workflows, custom navigation, integration with the ODE form system, and interfaces tailored to your use case.
14
+
15
+
## Scaffolding
16
+
17
+
ODE does **not** require a special installer: start from a **standard** project scaffold (for example **`npm create vite@latest`** with React, Svelte, or Solid templates) and then align the **folder layout** with the app bundle spec. Copy-paste commands, a **Vite `outDir` example**, and a post-scaffold checklist are maintained in the **[custom_app](https://github.com/OpenDataEnsemble/custom_app)** repository README on GitHub (AI and author context for the Formulus API and forms live in that repo as well).
14
18
15
19
## Application Structure
16
20
17
-
Custom applications follow a standardized structure for consistency and maintainability:
21
+
There is **no single mandatory** project layout. The tree below is **one** common pattern (React + Vite + optional `app.config.json`for theming). You can use a simpler folder tree if you prefer hand-written HTML/JS or a different framework, provided the **zip** you upload matches the [bundle format](/docs/reference/app-bundle-format).
18
22
19
23
```
20
24
my-app/
21
-
├── app.config.json # App configuration and theme
22
-
├── forms/ # Form definitions
23
-
│ ├── survey/
25
+
├── app.config.json # Optional: app metadata and theme (if your template uses it)
26
+
├── forms/ # Form definitions (see bundle format)
27
+
│ ├── survey/ # One folder per form type (form name)
│ └── forms-manifest.json # Form registry (if used by your project)
31
+
├── src/ # Optional: only if you use a bundler (e.g. React)
32
+
│ ├── components/
33
+
│ ├── screens/
34
+
│ ├── utils/
35
+
│ └── theme.js
36
+
├── scripts/
37
+
├── package.json # Optional: if you use npm tooling
38
+
└── vite.config.js # Optional: example bundler config
35
39
```
36
40
37
41
## Configuration System
38
42
39
43
### app.config.json
40
44
41
-
The `app.config.json` file is the single source of truth for your application's configuration:
45
+
If your template uses **`app.config.json`** (common in React-based examples), it can hold application metadata and theme. Plain HTML apps may omit it and configure styling in CSS/JS instead. When present, it is typically the single place for those settings:
@@ -108,10 +111,12 @@ export function buildTheme(mode = 'light') {
108
111
109
112
### Form Structure
110
113
111
-
Each form consists of two files:
114
+
Each form is a **directory** named with the **form type** (for example `survey/`). Inside it, two files are required:
115
+
116
+
1. **`schema.json`**: [JSON Schema](https://json-schema.org/) (draft-07) defining data shape, validation, and question types (including ODE `format` values). See [Form specifications](/docs/reference/form-specifications).
117
+
2. **`ui.json`**: [JSON Forms](https://jsonforms.io/) **UI schema** defining layout (`VerticalLayout`, `Control`, `scope`, rules). ODE follows JSON Forms with project-specific rules—see [Form specifications](/docs/reference/form-specifications). The [app bundle format](/docs/reference/app-bundle-format) describes how these files sit inside the zip.
112
118
113
-
1. **schema.json**: JSON Schema (draft-07) defining data structure
114
-
2. **ui.json**: Formulus UI schema defining form layout and behavior
119
+
Synkronus accepts **`forms/<formType>/schema.json`** and **`ui.json`** at the **bundle root** (with **`forms/`** as a **sibling** of **`app/`**), or the alternate path **`app/forms/<formType>/...`** where **`forms`** sits **inside** **`app`**. See [App bundle format](/docs/reference/app-bundle-format).
Copy file name to clipboardExpand all lines: docs/implementer/implementer-index.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,6 +17,10 @@ This section is designed for users who:
17
17
- Need guidance on deployment and data management
18
18
- Are responsible for project outcomes
19
19
20
+
:::tip AI coding assistants
21
+
If you use an AI assistant to build **custom applications** (bundles and JSON forms) for ODE, see **[custom_app](https://github.com/OpenDataEnsemble/custom_app)** on GitHub and the **[documentation](https://opendataensemble.org/docs/)** site—no need to clone the full ODE monorepo.
22
+
:::
23
+
20
24
:::info Not collecting data?
21
25
If you're collecting data with Formulus, see the [Data Collector Guide](/docs/collector/collector-index).
22
26
If you're developing or extending ODE, see the [Developer Guide](/docs/developer/developer-index).
Copy file name to clipboardExpand all lines: docs/reference/app-bundle-format.md
+63-51Lines changed: 63 additions & 51 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,27 +12,35 @@ App bundles are ZIP archives containing custom application files, form specifica
12
12
13
13
## Bundle Structure
14
14
15
-
An app bundle is a ZIP file with the following structure:
15
+
Synkronus validates bundles that use **top-level** folders **`app/`**, **`forms/`**, and optionally **`renderers/`**. The **`app`** directory (your HTML/JS/CSS) and the **`forms`** directory (JSON Forms) are **siblings** at the root of the ZIP—they are **not** nested inside each other in the default layout.
16
16
17
17
```
18
18
app-bundle.zip
19
-
├── index.html # Main entry point (required)
20
19
├── manifest.json # Bundle metadata (required)
21
-
├── assets/
22
-
│ ├── css/
23
-
│ │ └── styles.css
24
-
│ ├── js/
25
-
│ │ ├── app.js
26
-
│ │ └── formulus-load.js
27
-
│ └── images/
28
-
│ └── logo.png
29
-
├── forms/ # Form specifications (optional)
30
-
│ ├── survey-v1.json
31
-
│ └── health-v1.json
32
-
└── config/ # Configuration files (optional)
33
-
└── settings.json
20
+
├── app/ # Web UI (required): sibling of forms/, not parent of it
21
+
│ ├── index.html # Main entry point (required)
22
+
│ ├── assets/
23
+
│ │ ├── css/
24
+
│ │ ├── js/
25
+
│ │ │ ├── app.js
26
+
│ │ │ └── formulus-load.js
27
+
│ │ └── images/
28
+
│ └── public/ # Optional: e.g. app.config.json copied into build
29
+
├── forms/ # Form specs (optional; see Form specifications)
└── renderers/ # Optional: custom JSON Forms renderers
38
+
└── myRenderer/
39
+
└── renderer.jsx
34
40
```
35
41
42
+
**Alternate layout (nested forms):** Some projects put form folders under **`app/forms/<formType>/`** instead of top-level **`forms/<formType>/`**. In that case **`forms`** is a **subdirectory inside `app`** (path `app/forms/...`). That is **different** from having **`app/`** and **`forms/`** as **two separate top-level folders**. Synkronus accepts both; use one style consistently in a given bundle.
43
+
36
44
## Manifest Format
37
45
38
46
The `manifest.json` file defines bundle metadata:
@@ -42,7 +50,7 @@ The `manifest.json` file defines bundle metadata:
42
50
"version": "20250114-123456",
43
51
"name": "My Custom App",
44
52
"description": "Description of the custom application",
45
-
"entryPoint": "index.html",
53
+
"entryPoint": "app/index.html",
46
54
"createdAt": "2025-01-14T10:00:00Z"
47
55
}
48
56
```
@@ -59,13 +67,13 @@ The `manifest.json` file defines bundle metadata:
59
67
60
68
## Entry Point
61
69
62
-
The entry point (`index.html` by default) is the main HTML file loaded when the app bundle is opened. It should:
70
+
Validated bundles include **`app/index.html`** (path from the **ZIP root**). The manifest **`entryPoint`** should reference that file (commonly `app/index.html`). The entry HTML should:
63
71
64
72
1. Include the Formulus load script
65
73
2. Initialize the application
66
74
3. Use the Formulus JavaScript interface
67
75
68
-
**Example:**
76
+
**Example** (paths below assume assets live under `app/assets/`):
69
77
70
78
```html
71
79
<!DOCTYPE html>
@@ -84,38 +92,40 @@ The entry point (`index.html` by default) is the main HTML file loaded when the
84
92
85
93
## Form Specifications
86
94
87
-
Form specifications can be included in the `forms/` directory. Each form file should contain:
95
+
Use a **one-folder-per-form** layout. The **folder name** is the **form type** identifier (for example `survey`, `registration`). Synkronus validates that each form directory contains both required files.
88
96
89
-
- Schema definition
90
-
- UI schema definition
91
-
- Form metadata
97
+
**Folder structure:****`forms/<formType>/`** at the **root** of the ZIP, as a **sibling** of **`app/`**.
92
98
93
-
**Example form file:**
99
+
### Required files per form
100
+
101
+
| File | Role |
102
+
|------|------|
103
+
|**`schema.json`**|**[JSON Schema](https://json-schema.org/)** (draft-07 in ODE) for the observation payload: properties, types, validation, and ODE-specific **`format`** values for question types. Defines *what* is collected. |
104
+
|**`ui.json`**|**[JSON Forms UI schema](https://jsonforms.io/docs/uischema/)** for layout: `VerticalLayout`, `Control` elements, `scope` pointers into the schema, rules, etc. Defines *how* the form is shown. ODE follows JSON Forms with additional rules documented in [Form specifications](/docs/reference/form-specifications). |
105
+
106
+
Upstream JSON Forms concepts and UI schema structure are described at **[jsonforms.io](https://jsonforms.io/)**. Always cross-check ODE-specific behavior in [Form specifications](/docs/reference/form-specifications)—not every JSON Forms feature is available in Formulus.
107
+
108
+
**Example paths (two files per form, not one combined JSON) — top-level `forms/` (sibling of `app/`):**
94
109
95
-
```json
96
-
{
97
-
"formType": "survey",
98
-
"version": "1.0.0",
99
-
"schema": {
100
-
"type": "object",
101
-
"properties": {
102
-
"name": {
103
-
"type": "string",
104
-
"title": "Name"
105
-
}
106
-
}
107
-
},
108
-
"uischema": {
109
-
"type": "VerticalLayout",
110
-
"elements": [
111
-
{
112
-
"type": "Control",
113
-
"scope": "#/properties/name"
114
-
}
115
-
]
116
-
}
117
-
}
118
110
```
111
+
forms/
112
+
└── survey/
113
+
├── schema.json
114
+
└── ui.json
115
+
```
116
+
117
+
**Same form type using nested `app/forms/` instead:**
118
+
119
+
```
120
+
app/
121
+
├── index.html
122
+
└── forms/
123
+
└── survey/
124
+
├── schema.json
125
+
└── ui.json
126
+
```
127
+
128
+
See [Form specifications](/docs/reference/form-specifications) and [Form design](/docs/guides/form-design) for complete examples of `schema.json` and `ui.json` pairs.
0 commit comments