Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PlainSurvey

A tiny self-hosted survey: one page, PHP + SQLite, no framework. Define questions in JSON, collect answers, glance at charts. Languages are whatever config/lang/ui.<code>.json files you ship.

Demo

https://survey.schick-software.de/demo

Requirements

  • PHP 8+ with PDO SQLite
  • A web server that can write to data/

Point the document root at this folder (or drop it into an existing PHP host).

Quick start

  1. Deploy these files to your server.
  2. Ensure data/ is writable (SQLite lives there; .htaccess blocks direct access).
  3. Open index.php to take the survey.

⚠️ Protect the analysis folder

The charts page is not active by default and must not be left open on the internet.

  1. Restrict analysis/ (HTTP auth, IP allowlist, VPN, server ACL — your choice).
  2. Rename analysis/index.php.please-protectanalysis/index.php.
  3. Open /analysis/ for the summary.

Until you rename the file, the analysis UI will not run.

Languages

UI strings live in config/lang/ui.<lang>.json (e.g. ui.de.json). Add or remove a language by adding or deleting that file — the switcher picks them up automatically (2-letter codes).

  • Switcher in the header (hidden if only one file exists), or ?lang=de (cookie)
  • Falls back to Accept-Language, then config/brand.jsonlang, then en if present
  • App title and slogan are keys in those UI files
  • Question text uses the same locale codes in config/questions.json maps

Questions

Edit config/questions.json, then reload.

Each survey needs a stable id (lowercase letters, digits, _, -) and a questions array:

{
  "id": "demo",
  "questions": [
    { "id": "q1", "type": "text", "label": { "en": "" } }
  ]
}

The survey id is stored on every row in SQLite (survey_id on questions, responses, answers), so one database can hold multiple surveys and files can be merged later. The browser stores the last response id per survey under plainsurvey.<id>.id in localStorage (theme stays global).

Type Notes
text Free text
choice Single choice — options need stable id + label map
multi Multiple choice — same option shape
rating scale: stars, emoji, or number; optional min / max (e.g. 0–10)

Answers store option ids (not translated labels), so charts stay correct across languages.

Updating wording: change labels/descriptions in questions.json — synced on the next request, answers stay.

Adding, removing, or reshaping questions (ids, types, options): delete data/survey.sqlite so the DB re-seeds (wipes all surveys in that file). Alternatively, change the survey id in JSON to start a fresh namespace in the same database without touching older rows.

If you still have an older SQLite file from before survey_id, delete data/survey.sqlite once and let it re-seed.

Branding

Edit config/brand.json (see brand.sample-*.json). Font, light/dark colors and logos, optional default lang. Title and slogan are in the language files.

Powered-by banner

A footer link (“Powered by PlainSurvey”) points at the project repo by default. Configure it with poweredBy in brand.json:

"poweredBy": true
"poweredBy": false
"poweredBy": {
  "enabled": true,
  "url": "https://github.com/fschick/plainsurvey"
}

Label text comes from powered_by in config/lang/ui.*.json.

Taking & updating answers

  • Opening the survey creates a short personal id and link (?id=…).
  • Share or bookmark that link to change answers later — open it, edit, submit again.
  • The browser remembers the last id per survey (localStorage key plainsurvey.<survey-id>.id). Use Start over / ?new=1 for a fresh response.

SQL analysis

data/survey.sqlite holds everything. Filter by survey_id (see config/questions.json). Sample queries for counts, ratings, and free-text lists are in analysis/analysis.sample.sql:

sqlite3 data/survey.sqlite < analysis/analysis.sample.sql

Or open the DB in any SQLite client and run queries from that file.

Layout

index.php                            Survey form
assets/css/style.css                 Styles
assets/js/survey.js                  Front-end behaviour
analysis/index.php.please-protect    Answer charts (enable after locking the folder)
analysis/analysis.sample.sql         Sample SQL
config/                              questions, brand, languages
src/                                 PHP helpers (db, i18n)
data/                                SQLite (not public)
fonts/                               Optional local webfonts

Disclaimer

Almost all parts of this project were created with a human-controlled AI assistant.

About

Short surveys. Clear answers. Your brand, your host, your data.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages