Tips & Tricks
RehabAlpha is still under active development. It is not yet HIPAA compliant and should only be used with dummy data.
This page collects practical patterns for writing RehabAlpha schemas that are easier to read, safer to maintain, and friendlier for clinicians to use.
Start simple, then add logic
A common mistake is trying to design a giant, highly dynamic schema all at once.
A better workflow is:
- build a simple working structure first
- confirm the base groups and inputs render correctly
- extract repeated option lists into reusable
optionsnodes - add
showIf,conditional,switch, ormultiSwitchonly where they clearly reduce clutter - refine labels, tooltips, and defaults last
The simpler the base structure, the easier it is to debug.
Prefer referenced nodes over giant inline trees
Branch nodes can contain inline child objects, but referenced IDs are usually easier to maintain.
Referenced nodes make it easier to:
- reuse groups
- move sections around
- scan the schema quickly
- troubleshoot broken references
- keep diffs smaller in version control
Recommended style:
{
id: "history_group",
type: "group",
label: "History",
children: ["chief_complaint", "medical_history"]
},
{
id: "chief_complaint",
type: "textInput",
label: "Chief Complaint"
},
{
id: "medical_history",
type: "textAreaInput",
label: "Medical History"
}
Inline child objects are supported, but referenced IDs are usually easier to read once a schema grows.
Use predictable naming conventions
Consistent naming makes schemas dramatically easier to read.
A good pattern is:
- groups end with
_group - conditionals end with
_logic - text nodes end with
_text - inputs end with
_input - reusable option lists end with
_options
Examples:
pain_group
pain_logic
gait_instructions_text
pain_level_input
assistance_level_options
This is especially helpful once a schema grows past a few dozen nodes.
Use structured option values when consistency matters
If an input will feed reporting, validation logic, or analytics, avoid relying on display text as the stored value.
Prefer this:
{
id: "assist_levels",
type: "options",
items: [
{ label: "Independent", value: "independent" },
{ label: "Minimal Assistance", value: "min_assist" },
{ label: "Moderate Assistance", value: "mod_assist" }
]
}
Instead of this:
{
id: "assist_levels",
type: "options",
items: ["Independent", "Minimal Assistance", "Moderate Assistance"]
}
Structured values are more stable over time, especially if labels need to be reworded later.
Reuse option lists aggressively
If the same choices appear in multiple places, define them once.
This reduces:
- duplication
- typo risk
- inconsistent wording
- maintenance burden
Example:
{
id: "side_options",
type: "options",
items: ["Left", "Right", "Bilateral"]
},
{
id: "affected_side_input",
type: "selectInput",
label: "Affected Side",
options: "side_options",
flavor: "buttons"
},
{
id: "dominant_side_input",
type: "selectInput",
label: "Dominant Side",
options: "side_options",
flavor: "list"
}
The same idea applies to multiSelectInput fields too.
Keep schemas focused
Avoid building one giant “everything form” if the workflow naturally breaks into distinct sections or contexts.
Smaller, focused schemas or focused subsections are usually better because they are:
- easier to understand
- faster to edit
- safer to validate
- easier for clinicians to complete
A focused structure often beats a hyper-generic one.
Use groups for human readability, not just structure
A group is not only a technical container. It is also a UX tool.
Use groups to help clinicians mentally chunk the form into sections such as:
- Subjective
- Objective
- Assessment
- Plan
- Fall History
- ROM
- Transfers
- Swallowing
- Cognition
A good group label makes a long form feel shorter.
Use text nodes to guide the clinician
Static instructional text can improve documentation quality.
Good uses for text nodes include:
- short reminders
- scoring instructions
- workflow notes
- clinician prompts
- disclaimers
Example:
{
id: "rom_instructions_text",
type: "text",
value: "Document active range of motion in degrees. Use estimated values only when direct measurement is not possible."
}
Keep these short. Long blocks of text are often ignored.
Use conditional logic to reduce clutter, not to impress yourself
Dynamic forms are powerful, but too much logic can become hard to reason about.
Good conditional logic hides fields that are truly irrelevant until needed.
Less helpful conditional logic hides fields unnecessarily and makes the form feel unpredictable.
A good question to ask is:
Does this rule reduce noise for the clinician, or does it just make the schema more complicated?
Keep conditional dependencies one-directional
A safer pattern is for early questions to reveal later detail fields.
Example:
has_falls_inputcontrolsfall_details_inputpain_present_inputcontrolspain_scale_inputuses_device_inputcontrolsdevice_type_input
This direction is easy to understand.
Riskier patterns are when fields in separate sections depend on each other in tangled ways. Those are harder to maintain and more likely to create confusing behavior.
Use elseChildren deliberately
elseChildren is most useful when the false branch still needs a meaningful UI outcome.
Good uses include:
- showing “No pain reported”
- showing a simpler alternate section
- showing a reminder when a required pathway is not met
Example:
{
id: "pain_logic",
type: "conditional",
when: { field: "has_pain_input", equals: true },
children: ["pain_scale_input", "pain_location_input"],
elseChildren: ["no_pain_text"]
},
{
id: "no_pain_text",
type: "text",
value: "Patient denies pain at time of assessment."
}
If you do not need a false-branch UI, omit elseChildren.
Use special context variables when the system already knows the answer
Special variables let a schema adapt to context without asking the clinician to answer setup questions the system already knows.
Supported examples include:
*disciplineId*facilityType*templateType*payorTypes
This is especially useful when a section should only appear for:
- a certain discipline
- a certain facility setting
- a certain document type
- certain payor scenarios
Example:
{
id: "snf_pdpm_logic",
type: "conditional",
when: {
all: [
{ field: "*facilityType", equals: "SNF" },
{ field: "*payorTypes", includes: "medicarePartA" }
]
},
children: ["pdpm_group"]
}
Use special variables when the context is authoritative and should not be manually re-entered.
Be careful with duplicate meanings, even when IDs differ
The validator catches duplicate IDs, but it cannot protect you from creating several different fields that mean almost the same thing.
For example, these may be semantically redundant:
pain_location_inputprimary_pain_location_inputsite_of_pain_input
Even if all are technically valid, they can confuse clinicians and clutter the form.
Try to standardize wording across the schema.
Use defaults thoughtfully
A defaultValue can be helpful, but defaults can also create accidental charting if overused.
Good default candidates:
checkboxInputdefaulting tofalse- obvious administrative defaults
- common, neutral starting values
Use caution with defaults for clinically meaningful content, especially when they could be mistaken for intentionally documented findings.
Use showExplicitNone only when unanswered and “none” really mean different things
For selectInput and multiSelectInput, showExplicitNone: true allows RehabAlpha to distinguish:
- unanswered
- explicitly none
That distinction is useful when both states are clinically meaningful.
Good uses include questions like:
- symptoms present
- barriers present
- precautions present
- relevant comorbidities present
Example:
{
id: "symptoms_input",
type: "multiSelectInput",
label: "Symptoms",
options: ["Dizziness", "Nausea", "Fatigue"],
flavor: "badges",
showExplicitNone: true
}
Do not enable explicit-none behavior unless the distinction genuinely matters. Otherwise it adds unnecessary complexity.
Choose the right selection style for the number of options
selectInput and multiSelectInput support different flavor values:
"buttons""badges""list"
As a rule of thumb:
- use
"buttons"for short, obvious option sets - use
"badges"for short multi-select sets where visible toggles are helpful - use
"list"when the option set is longer or needs a more compact UI
Example:
{
id: "mobility_barriers_input",
type: "multiSelectInput",
label: "Mobility Barriers",
options: "mobility_barriers_options",
flavor: "list",
showExplicitNone: true
}
Even a technically valid schema can still create poor UX if the selection style is not a good fit for the size of the option set.
Keep labels clinician-friendly
Labels should be:
- clear
- specific
- brief
- written in the language clinicians actually use
Better:
Current Pain Level (0-10)Assistive Device UsedDate of Surgery
Worse:
PainDeviceDate
The clearer the label, the less tooltip text you usually need.
Use tooltips for nuance, not for basic meaning
A tooltip is best when the field label is already clear, but a short clarification helps.
Good tooltip uses include:
- how to score a field
- when to use the field
- what unit to enter
- subtle workflow guidance
If the label itself is confusing, fix the label first.
Keep option lists short when possible
Huge option lists slow clinicians down.
If an option list is getting large, consider whether you should:
- split it into multiple questions
- narrow the choices by discipline or facility type
- use a more compact
"list"flavor - move some complexity into earlier routing logic
Shorter, better targeted lists usually produce better documentation UX.
Watch out for copy-paste drift
Schemas often grow by copying similar sections.
After pasting, double-check:
idlabeldefaultValueoptionsshowIfwhenchildrenelseChildrenbranchesfallbackChildren
Many schema bugs come from a copied node whose ID or condition was never updated.
Keep comments in the schema while drafting
Because RehabAlpha uses JSON5, comments are allowed.
During authoring, comments can help explain intent:
// Only show this section for PT users in SNF
{
id: "pt_snf_logic",
type: "conditional",
when: {
all: [
{ field: "*disciplineId", equals: "PT" },
{ field: "*facilityType", equals: "SNF" }
]
},
children: ["mobility_group"]
}
Comments are especially helpful in complex schemas with lots of reused branches.
Test one branch at a time
When debugging a schema:
- confirm the schema parses
- confirm hydration succeeds
- confirm references resolve
- confirm the expected visible tree appears for the current conditions
- test each conditional branch independently
- verify hidden fields disappear when they should
- verify explicit-none behavior only where intended
Do not try to debug the entire schema mentally all at once.
Prefer simple visibility logic over clever logic
This is easier to maintain:
{
id: "has_falls_logic",
type: "conditional",
when: { field: "has_falls_input", equals: true },
children: ["fall_count_input", "fall_details_input"]
}
Than this:
{
id: "fall_complex_logic",
type: "conditional",
when: {
notAll: [
{ field: "fall_status_input", equals: "none" },
{ field: "risk_override_input", equals: false },
{
any: [
{ field: "*facilityType", equals: "Outpatient" },
{ field: "manual_override_input", equals: true }
]
}
]
},
children: ["fall_details_input"]
}
The second may be valid, but it is much harder to reason about.
Avoid situations where the same input could render twice
RehabAlpha protects against duplicate rendered input IDs, but it is still best to design schemas so that one input can only appear once in the visible tree at a time.
Be especially careful when:
- reusing the same child ID in multiple branches
- combining
multiSwitchwith shared descendants - copying sections into multiple places
If two branches can both render the same input at once, the runtime will reject that visible tree.
Keep schemas modular across time
A schema that is easy to extend later is often better than a schema that looks “perfect” today.
A few habits help:
- keep IDs predictable
- isolate reusable option lists
- avoid giant deeply nested trees
- keep conditions understandable
- separate truly different workflows instead of overloading one structure
Future you will appreciate it.
A practical authoring checklist
Before saving a schema, ask yourself:
- Are the IDs predictable and unique?
- Are repeated option lists centralized?
- Are labels clear to clinicians?
- Are conditions simple enough to explain out loud?
- Could the same input ID render twice at the same time?
- Are groups and branches focused instead of overloaded?
- Are defaults minimal and intentional?
- Is
showExplicitNoneenabled only where the distinction matters? - Would another person understand this schema in six months?
If the answer is yes, you are probably in good shape.
Where to go next
After this page, the most useful follow-up pages are:
- Schemas Overview
- Frequently Asked Questions
- Writing Your Own Schema
- Writing Schemas with AI
- Test Your Knowledge
- Schema Library