Hi @Sujal_Co,
Congratulations on being selected for GSoC 2026! Use this topic for all communications this summer. No private messages should happen. Use the Jitsi link below if you need to have real-time discussions with your mentors.
Hi @Sujal_Co,
Congratulations on being selected for GSoC 2026! Use this topic for all communications this summer. No private messages should happen. Use the Jitsi link below if you need to have real-time discussions with your mentors.
Thank you @r0bby and @sunbiz! I am ready to begin the community bonding period. @sunbiz, I would like to schedule a call to discuss the architecture decisions, JSON schema format, and FHIR binding approach. Please let me know your availability. I will also post a detailed week-by-week project plan in this thread shortly. Thanks ![]()
Hi @sunbiz, I was going through lh-toolkit-webcomponents and I think my form designer should go as a new package inside packages/ like how fhir-vitals and fhir-period are there. I couldn’t find any separate lh-toolkit-form-entry repo so I’m assuming that’s the right place. Just wanted to confirm before I go deeper and also should I work on master directly or create a separate branch?
Hi @sunbiz, sharing my community bonding plan and a couple of questions before coding starts
I Went through lh-toolkit-webcomponents understood the monorepo structure under packages/, LitElement-based components, and how FHIR resources are bound as element properties,
Explored drag-and-drop approaches — leaning toward SortableJS over native HTML5 DnD for better touch support
My plan for the remaining bonding period (until May 24):
Finalize where the form designer package should live (new package inside lh-toolkit-webcomponents vs. separate repo)
Draft the JSON schema structure for the form definition
Set up project scaffolding and make a small exploratory commit
Two questions I need your input on:
My May 5 message asked about repo location, should the form designer go as a new package inside packages/ in lh-toolkit-webcomponents, or as a separate repo?
And @sunbiz please correct me if i am wrong, For midterm evaluation, I’m planning to have a working drag-drop canvas with field palette and JSON export by then. Does that match your expectation?
Available for a Jitsi call or happy to continue on Rocket.Chat, whatever works for you.
I also re-read the original project discussion thread from March where @parumenon1 suggested using Lit for the designer shell and starting with component-registry.json. My plan aligns with that, using LitElement for the Canvas, Palette, Properties Panel, and DataBinder components, with component-registry.json as the component registry. My main open question is still the repo location, and whether to use a Lit Reactive Controller for FHIR data binding.
Thanks for the detailed write-up. Sounds like you’ve got a solid handle on the codebase. Understanding the monorepo layout and how FHIR resources bind to component properties is exactly the grounding that pays off later.
On SortableJS vs. native HTML5 DnD: agreed, SortableJS is the safer call. Touch support and consistent cross-browser behavior matter more here than shaving a dependency.
On repo location: rather than a brand-new package or a separate repo, take a look at the react-ehr branch: https://gitlab.com/librehealth/toolkit/lh-toolkit-webcomponents/-/tree/react-ehr, which demonstrates the components in use. A dedicated branch for the form designer following that same pattern might be the cleanest path: you stay close to the components, can iterate freely without disturbing main, and we can have CI generate the publishable packages from that branch. Could you look at how react-ehr is set up and let me know if that approach works for the designer? If a branch turns out to be awkward, a new package under packages/ is the fallback.
Your remaining bonding-period plan looks right. Finalizing where the designer lives, drafting the JSON schema, and a small scaffolding commit is good scope for the time left.
For midterm, a working drag-drop canvas with a field palette and JSON export is a reasonable target. One suggestion: let’s review the JSON export schema together before you build much on top of it. It’s the contract the rest of the tool depends on, so it’s worth getting an early look. @parumenon1 anything you’d add or reprioritize there?
Looking forward to the exploratory commit.
Hi @Sujal_Co Firstly congratulations on being selected. And great to see the thoughtful preparation going into the bonding period.
I agree with @sunbiz on the dedicated branch approach and midterm scope. On the Lit Reactive Controller for FHIR binding - the react-ehr branch uses Redux for state management since it’s a React app, so I think there’s no existing precedent in the repo for this pattern. Since the form designer will be LitElement-based, a Reactive Controller seems like a natural fit for encapsulating FHIR fetch/update logic, but wanted to check with you before Sujal goes down that path. What do you think? @sunbiz
Hi @sunbiz and @parumenon1, thank you both for the detailed guidance this really helps clarify the path forward.
I’ll study the react-ehr branch more closely and treat that as the reference for how the designer branch should be structured. I also understand that the JSON export schema should be reviewed together early, so I’ll draft a first version and share it here before building too much on top of it.
For the FHIR binding approach, I’ll wait for your suggestion before committing to a pattern. Since the project is Lit-based, a Reactive Controller does sound like a good fit, but I agree it’s better to confirm the direction first.
I’m also going through the OpenMRS O3 demo to better understand the real workflow context. My goal for the remaining bonding period is to finish the branch setup, share the schema draft, and make a small exploratory commit.
Thanks again, I’ll keep you updated here.
@parumenon1 agreed — Reactive Controller is the right call for FHIR binding. It’s exactly what the controller pattern is designed for: encapsulating reusable, cross-cutting behavior with its own reactive update cycle, independent of any single component. Redux would be overkill here and pulls in patterns that don’t fit Lit’s mental model. The react-ehr branch uses Redux because React doesn’t have a built-in equivalent — we don’t have that constraint on the Lit side.
A few suggestions as you go down that path:
Consider a single FhirController parameterized by resource type rather than one controller per resource. Easier to keep behavior consistent (caching, error handling, auth) and easier for the Canvas, Properties Panel, and DataBinder to share an instance.
Expose loading and error state alongside the data. That’s the main payoff of the reactive pattern, and the designer UI will want to surface those states.
Going through the OpenMRS O3 demo is a great call. Pay attention to how forms are actually rendered and submitted in that workflow; it’ll inform the JSON schema decisions more than you’d expect, especially around field metadata and conditional logic.
Plan sounds good overall. (1) branch setup, (2) schema draft, (3) small exploratory commit. Share the schema draft here when you have a first cut and we’ll review it together before you build too much on top of it.
Hi @sunbiz and @parumenon1 I’ve completed the local setup, run polymer serve to explore the component catalog, studied the LitElement pattern from existing components, created the gsoc26-form-designer branch, and pushed an initial exploratory lh-form-designer shell following the repo’s component structure. The package includes lh-form-designer.js, package.json, and README.md.
Commit link: b7f4ed5b87157057ef631314867501c8009e7d38. I also noticed the element does not appear in the catalog yet, likely because it still needs the demo registration files. Should I add demos/lh-form-designer.html, the catalog link in index.html, and the fragment entry in polymer.json now, or keep this branch minimal for the exploratory phase?
{
"resourceType": "Questionnaire",
"id": "patient-intake-form",
"title": "Patient Intake Form",
"status": "draft",
"item": [
{
"linkId": "1",
"text": "Patient Name",
"type": "string",
"required": true
},
{
"linkId": "2",
"text": "Date of Birth",
"type": "date",
"required": true
},
{
"linkId": "3",
"text": "Gender",
"type": "choice",
"required": false,
"answerOption": [
{ "valueCoding": { "code": "M", "display": "Male" } },
{ "valueCoding": { "code": "F", "display": "Female" } },
{ "valueCoding": { "code": "O", "display": "Other" } }
]
},
{
"linkId": "4",
"text": "Pregnancy Status",
"type": "boolean",
"required": false,
"enableWhen": [
{
"question": "3",
"operator": "=",
"answerCoding": { "code": "F" }
}
]
}
]
}
This is my first draft of the FHIR Questionnaire schema that the form designer will produce as output. I’ve included the four core field types I expect the palette to support: string, date, choice, and boolean. I’ve also added an enableWhen condition on the Pregnancy Status field to show how conditional logic will be represented.
A few open questions:
(1) Should the schema also include a section/group type for multi-section forms?
(2) Should I use standard FHIR enableWhen or a custom metadata layer on top?
Happy to revise before starting the coding phase on May 25th.
Nice progress, @Sujal_Co . The schema draft is a solid starting point. Quick answers to your open questions:
group item type rather than waiting. Real clinical forms almost always have sections (Demographics, History, Vitals, etc.), and group items can be nested, which gives you hierarchical structure for free without inventing anything. Building the palette, Canvas, and DataBinder around flat items first and retrofitting groups later tends to be painful. The traversal logic touches every level. Better to model it from day one even if your first demo only uses one or two groups.enableWhen. That’s the whole point of emitting a real Questionnaire. Anything outside the spec breaks interop with other FHIR consumers and forces us to ship our own renderer to interpret the output. enableWhen covers the common operators (=, !=, >, <, exists), and for anything more complex FHIR already has enableWhenExpression (FHIRPath) as the escape hatch. Reach for that before reaching for custom metadata.There is a legitimate need for designer-only metadata, such as canvas coordinates, “is this group collapsed in the editor,” palette categorization, etc. Keep that in FHIR extension blocks with a clear URL prefix (e.g. https://librehealth.io/fhir/StructureDefinition/designer-*), or in a sibling editor-state object that you strip on export. Just don’t mix it into the spec fields themselves.
On your earlier demo-registration question: Go ahead and add demos/lh-form-designer.html, the catalog link in index.html, and the polymer.json fragment entry now. Seeing your component in the catalog while iterating is much more valuable than keeping the branch minimal, and you’ll want a demo target to develop against the moment the Canvas starts rendering anything.
Post the revised schema with group support when you have it and we’ll do one more pass before the 25th.
Hi @sunbiz, thanks again for the guidance. I revised the draft to use native FHIR group for sections and kept conditional logic in standard enableWhen as suggested. For this pass I’m sharing the clean Questionnaire export shape first, without adding designer-only metadata into the resource yet.
One small question: for editor-only state such as collapsed groups or canvas coordinates, would you prefer that I keep it in a separate sibling editor-state object during editing and strip it on export, or start modeling it through FHIR extensions from the beginning? I also noticed the example LibreHealth extension URL pattern does not currently resolve in the browser on my side, so I wanted to confirm whether that was meant as a draft canonical-style identifier/example rather than a published definition page.
Here is the revised draft:
{
"resourceType": "Questionnaire",
"id": "patient-intake-form",
"title": "Patient Intake Form",
"status": "draft",
"item": [
{
"linkId": "1",
"text": "Demographics",
"type": "group",
"item": [
{
"linkId": "1.1",
"text": "Patient Name",
"type": "string",
"required": true
},
{
"linkId": "1.2",
"text": "Date of Birth",
"type": "date",
"required": true
},
{
"linkId": "1.3",
"text": "Gender",
"type": "choice",
"answerOption": [
{ "valueCoding": { "code": "M", "display": "Male" } },
{ "valueCoding": { "code": "F", "display": "Female" } },
{ "valueCoding": { "code": "O", "display": "Other" } }
]
},
{
"linkId": "1.4",
"text": "Pregnancy Status",
"type": "boolean",
"enableWhen": [
{
"question": "1.3",
"operator": "=",
"answerCoding": { "code": "F" }
}
]
}
]
}
]
}
Hi @sunbiz and @parumenon1 demo registration is done and pushed. I can see lh-form-designer showing up in the catalog and the placeholder shell opens fine. Starting on the group-aware canvas now.
Hi @sunbiz and @parumenon1 since coding has now started, I’m opening a Draft MR on the gsoc26-form-designer branch so progress stays visible in one place.
My current understanding of the near-term MVP / likely midterm scope is:
a basic lh-form-designer with demo integration, a group-aware canvas, a small palette of core field types, simple selection/editing, and export to grouped FHIR Questionnaire JSON using native group and enableWhen. Please let me know if you’d like me to adjust that scope up or down.
Hi @sunbiz and @parumenon1 Draft MR is up and the catalog registration is working. Moving on to building the group-aware canvas next.
Hi @sunbiz and @namratanehete , quick update on gsoc26-form-designer: I’ve synced the branch with the latest upstream changes, and the build/test infra fix is in place. I’ve already landed choice.answerOption editing and minimal enableWhen editing in the properties panel, and I’m now moving to JSON export from designer state next.
I’m keeping the work incremental so it stays easy to review and stays aligned with the current merge request flow. Please let me know if you want me to adjust the next step order, but my current plan is to finish JSON export, then add basic tests, and then continue with the next authoring features.