3.8 KiB
| tags | |||
|---|---|---|---|
|
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
// 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
{
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
survey.onComplete.add(async (result) => {
await supabase.from('responses').insert({
user_id: userId,
survey_data: result.data,
completed_at: new Date()
});
});
4. Personalization Support
// 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
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
-- 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.