iso27diy-corp/AuditGlue/System alternative/SurveyJS.md

3.8 KiB
Raw Blame History

tags
iso27DIY
stack
dev

With an open source library, Id recommend SurveyJS as your best option. Heres 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, its 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.