Skip to main content

Tips & Tricks

warning

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:

  1. build a simple working structure first
  2. confirm the base groups and inputs render correctly
  3. extract repeated option lists into reusable options nodes
  4. add showIf, conditional, switch, or multiSwitch only where they clearly reduce clutter
  5. 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_input controls fall_details_input
  • pain_present_input controls pain_scale_input
  • uses_device_input controls device_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_input
  • primary_pain_location_input
  • site_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:

  • checkboxInput defaulting to false
  • 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 Used
  • Date of Surgery

Worse:

  • Pain
  • Device
  • Date

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:

  • id
  • label
  • defaultValue
  • options
  • showIf
  • when
  • children
  • elseChildren
  • branches
  • fallbackChildren

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:

  1. confirm the schema parses
  2. confirm hydration succeeds
  3. confirm references resolve
  4. confirm the expected visible tree appears for the current conditions
  5. test each conditional branch independently
  6. verify hidden fields disappear when they should
  7. 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 multiSwitch with 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 showExplicitNone enabled 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