Skip to content

plutov/formulosity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Formulosity - self-hosted Surveys as Code platform.

This approach offers a number of advantages, including:

  • Version control: Survey files can be stored in a Github repository, which makes it easy to track changes and collaborate with others.
  • Reproducibility: Survey files can be easily shared and reproduced, making it easy to reuse surveys or create variations of existing surveys.
  • Automation: Survey files can be used to automate the creation and deployment of surveys, which can save time and effort.

Formulosity uses human-readable declarative language YAML.

Features

  • Management API
  • Survey UI: for end users (respondents)
  • Console UI: manage surveys
  • YAML survey configuration
  • Basic question types
  • Default theme
  • Custom themes support
  • Personalized options: intro, outro, etc.
  • Cookie/IP duplicate response protection
  • Admin user authentication
  • Different database options: SQLite and Postgres
  • Continue where you left off
  • Advanced validation rules
  • Detect survey changes in real time
  • Export responses in UI or via API
  • Advanced question types
  • Pipe answers into the following questions

Survey Structure

Each directory in SURVEYS_DIR is a survey. You can configure the source of your surveys by setting different SURVEYS_DIR env var.

surveys/
├── survey1/
│   ├── metadata.yaml
│   ├── questions.yaml
│   ├── security.yaml
│   ├── variables.yaml
│   └── ...
└── survey2/
    ├── metadata.yaml
    ├── questions.yaml
    └── ...

To get started, check out the ./api/surveys folder with multiple examples.

Survey Files

metadata.yaml

This file is required! The file consists of a YAML object with specific properties describing the survey.

  • title: This is the main title displayed to users at the beginning of the survey.
  • theme: This specifies the visual theme applied to the survey. Currently supported themes are: default.
  • intro: This text appears as an introduction before the first question.
  • outro: This text appears as a conclusion after the last question.
title: Survey Title
theme: default # or custom
intro: |
  This is the introduction to the survey.
  It can be multiple lines long.
outro: |
  Thank you for taking the survey.
  Your feedback is important to us.

questions.yaml

This file is required! The file consists of a list of questions, each defined as a YAML object with specific properties.

  • type: This specifies the type of question being asked.
  • id: This provides a unique identifier for the question. It is useful for referencing specific questions in branching logic or data analysis. IDs must be unique across all questions in the survey.
  • label: This is the text displayed to the user as the question itself.
  • description: This provides additional information about the question for the user, such as clarification or instructions.
  • options: This list defines the available answer choices for question types like single-choice, multiple-choice and ranking.
  • optionsFromVariable: This property references a variable defined in a separate variables.yaml file. The variable should contain a list of options to be used for the question. This allows for reusability and centralized management of option lists.
  • validation: This property is used to define validation rules for specific question types.
questions:
  - type: single-choice
    id: question1 # optional ID, must be unique across all questions
    label: What is the capital of Germany?
    description: You can select multiple options
    optionsFromVariable: german-city-options # defined in variables.yaml
    options:
      - Berlin
      - Munich
      - Paris
      - London
      - Hamburg
      - Cologne
    validation:
      min: 1
      max: 3

security.yaml

This file is optional. The file consists of a YAML object with specific properties for survey security settings.

  • duplicateProtection: This property defines how the platform handles duplicate responses from the same user.
duplicateProtection: cookie # cookie | ip

variables.yaml

This file is optional. The file consists of a list of variables, each defined as a YAML object with specific properties.

  • id: This unique identifier references the variable within questions. IDs must be unique across all variables defined in the file.
  • type: This specifies the type of data stored in the variable. Currently supported types are: list.
variables:
  - id: german-city-options # must be unique
    type: list
    options:
      - Berlin
      - Munich
      - Hamburg
      - Cologne

Question Types

Short Text

Prompts users for a brief written answer.

- type: short-text
  label: What is the capital of Germany?
  # set min/max characters
  validation:
    min: 10
    max: 100

Long Text

Prompts users for a detailed written answer.

- type: long-text
  label: What is the capital of Germany?
  # set min/max characters
  validation:
    min: 10
    max: 100

Single Choice

Presents a question with only one correct answer from a list of options.

- type: single-choice
  label: What is the capital of Germany?
  options:
    - Berlin
    - Munich
    - Paris
    - London
    - Hamburg
    - Cologne

Multiple Choice

Presents a question where users can select multiple answers (with limitations). You can customize the minimum and maximum allowed selections in the validation section.

- type: multiple-choice
  label: Which of the following are cities in Germany?
  description: You can select multiple options
  validation:
    min: 1
    max: 3
  options:
    - Berlin
    - Munich
    - Paris
    - London
    - Hamburg
    - Cologne

Date

Asks users to enter a specific date.

- type: date
  label: When was the Berlin Wall built?

Rating

Presents a scale for users to rate something on a predefined range.

- type: rating
  label: How much do you like Berlin?
  min: 1
  max: 5

Ranking

Asks users to rank options based on a given criteria.

- type: ranking
  label: Rank the following cities by population
  optionsFromVariable: german-city-options

Yes/No

Presents a question where users can only answer "yes" or "no".

- type: yes-no
  label: Is Berlin the capital of Germany?

Email

Prompts user to enter their email

- type: email
  label: Please enter your email.

File

Prompts user to upload their file based on a given formats and maximum upload size.

- type: file
  label: Upload a Berlin Image
  validation:
    formats:
      - .jpg
      - .png
    max_size_bytes: 5*1024*1024 # 5 MB

Responses

Responses can be shown in the UI and exported as a JSON. Alternatively you can use REST API to get survey resposnes:

curl -XGET \
http://localhost:9900/app/surveys/{SURVEY_ID}/sessions?limit=100&offset=0&sort_by=created_at&order=desc

Where {SURVEY_ID} id the UUID of a given survey.

Screenshots

Installation & Deployment

docker-compose up -d --build

And you should be able to access the UI on localhost:3000 (default basic auth: user:pass).

You can deploy individual services to any cloud provider or self host them.

  • Go backend. It's packaged as a Docker container and can be deployed anywhere.
  • Next.js frontend. It's also packaged as a Docker container, but also can be deployed to Vercel for example.
  • [Optional] Postgres database. You can use managed Postgres services or deploy it yourself.

Environment Variables

API:

  • DATABASE_TYPE - sqlite or postgres
  • DATABASE_URL - Postgres or SQLite connection string
  • SURVEYS_DIR - Directory with surveys, e.g. /root/surveys. It's suggested to use mounted volume for this directory.
  • UPLOADS_DIR - Directory for uploading files from the survey forms.

UI:

  • CONSOLE_API_ADDR - Public address of the Go backend. Need to be accessible from the browser.
  • CONSOLE_API_ADDR_INTERNAL - Internal address of the Go backend, e.g. http://api:8080 (could be the same as CONSOLE_API_ADDR).
  • IRON_SESSION_SECRET - Secret for session encryption
  • HTTP_BASIC_AUTH - Format: user:pass for basic auth (optional)

Tech Stack

  • Backend: Go, (Postgres or SQLite)
  • UI: Next.js, Tailwind CSS

Create new SQLite/Postgres migration

Make sure to install go-migrate first.

cd api
migrate create -dir migrations/postgres -ext sql -seq name
migrate create -dir migrations/sqlite -ext sql -seq name

Run Go tests

cd api
make test

Contributing Guidelines

Pull requests, bug reports, and all other forms of contribution are welcomed and highly encouraged!