--- tags: - iso27DIY - stack - dev --- With an open source library, I’d recommend **SurveyJS** as your best option. Here’s why it fits your requirements perfectly: ## SurveyJS - Best Choice for Your Use Case SurveyJS is a free and open-source MIT-licensed JavaScript library that renders dynamic JSON-based forms with integration for React, Angular, Vue, jQuery, and Knockout, storing all data on your own servers with no limits on forms or submissions . ### Key Advantages for Your Requirements: **1. Dynamic Question Generation** ```javascript // Generate questions dynamically with LLM content const surveyJson = { pages: [{ elements: [{ type: "radiogroup", name: "challenge", title: await generateQuestionWithLLM(userContext), choices: await getLLMGeneratedOptions(orgData) }] }] }; ``` **2. Advanced Conditional Logic** ```javascript { type: "text", name: "followup", title: "Tell us more about {challenge}", visibleIf: "{challenge} = 'specific_option'", // Can reference user data too enableIf: "isUserRole('manager')" } ``` **3. Supabase Integration** ```javascript survey.onComplete.add(async (result) => { await supabase.from('responses').insert({ user_id: userId, survey_data: result.data, completed_at: new Date() }); }); ``` **4. Personalization Support** ```javascript // Inject user/org data into questions survey.setValue("userName", user.name); survey.setValue("orgSize", organization.size); // Use in question text: "Given that {orgSize}, how would you..." ``` ## Alternative: Formbricks Formbricks is an open source surveying platform built with React, Next.js, TypeScript, and TailwindCSS that provides comprehensive logic capabilities . However, it’s more of a complete platform than a library you embed. ## Implementation Strategy with SurveyJS ```javascript import { Survey } from 'survey-react-ui'; import { Model } from 'survey-core'; class DynamicSurvey { async generateSurvey(userId, orgId) { // 1. Fetch user/org context from Supabase const context = await this.getContext(userId, orgId); // 2. Generate base questions with LLM const baseQuestions = await this.generateWithLLM(context); // 3. Build survey JSON with conditional logic const surveyJson = { pages: [{ elements: baseQuestions.map(q => ({ ...q, title: this.interpolateVariables(q.title, context) })) }] }; return new Model(surveyJson); } setupDynamicBehavior(survey, context) { // Add dynamic question injection based on answers survey.onValueChanged.add(async (sender, options) => { if (options.name === 'trigger_question') { const followup = await this.generateFollowup( options.value, context ); sender.addNewPage(followup); } }); } } ``` ## Why SurveyJS Over Custom Solution - **Rich question types**: 20+ built-in components - **Mature conditional logic**: Complex expressions and branching - **Extensible**: Custom question types and themes - **Well-documented**: Extensive examples and API docs - **Active development**: Regular updates and community support - **Performance**: Optimized rendering and state management ## Database Schema Integration ```sql -- Store dynamic survey templates CREATE TABLE survey_templates ( id uuid PRIMARY KEY, name text, base_schema jsonb, llm_prompts jsonb, created_by uuid REFERENCES users(id) ); -- Store completed responses CREATE TABLE survey_responses ( id uuid PRIMARY KEY, user_id uuid REFERENCES users(id), template_id uuid REFERENCES survey_templates(id), responses jsonb, context_data jsonb, completed_at timestamp ); ``` SurveyJS gives you the flexibility to build exactly what you need while handling the complex UI logic, validation, and state management that would take months to build from scratch.