Skip to content

surveydown

1.3.0Package record

Markdown-Based Programmable Surveys Using 'Quarto' and 'shiny'

1packages depend
5.8Kdownloads / year
0.3%test coverage
13/13flavors OK

Overview

About

Generate programmable surveys using markdown and R code chunks. Surveys are composed of two files: a survey.qmd 'Quarto' file defining the survey content (pages, questions, etc), and an app.R file defining a 'shiny' app with global settings (libraries, database configuration, etc.) and server configuration options (e.g., conditional skipping / display, etc.). Survey data collected from respondents is stored in a 'PostgreSQL' database. Features include controls for conditional skip logic (skip to a page based on an answer to a question), conditional display logic (display a question based on an answer to a question), a customizable progress bar, and a wide variety of question types, including multiple choice (single choice and multiple choices), select, text, numeric, multiple choice buttons, text area, and dates. Because the surveys render into a 'shiny' app, designers can also leverage the reactive capabilities of 'shiny' to create dynamic and interactive surveys.

Changes in 1.3.0
  • New feature: mc_image and mc_multiple_image question types — multiple choice where each option is a clickable image card (single selection with mc_image, multiple with mc_multiple_image). Pass a new image argument to sd_question(): a vector of image paths or URLs, one per option, in the same order as option (paths resolve against the survey's images/www folder, e.g. "images/cat.png", or use full URLs). Captions are optional and controlled by the option names: named options (e.g. c('Cat' = 'cat')) show the names as text captions beneath each image, while an unnamed option vector (e.g. c('cat', 'dog')) shows the images only with no captions. (This differs from the other multiple-choice types, where an unnamed vector uses the values as visible labels.) Values are stored exactly like mc/mc_multiple (single value, or pipe-joined for multiple), so storage, restoration, and required-question logic all work the same.
  • New feature: matrix_multiple question type — a matrix where each row allows multiple selections (checkboxes), complementing the single-selection matrix type (radio buttons). Usage is identical to matrix (same row and option parameters); each row becomes a <question_id>_<row_id> sub-question stored as its own column, with multiple selections pipe-joined (e.g., "fast|cheap"). Row shuffling, required-question handling, and session restoration work the same as for matrix.
  • Enhancement: Sliders have been restyled. slider and slider_numeric questions now get a slim, theme-colored track with a clean circular handle and value bubble (previously ionRangeSlider shipped completely unstyled). The dense minor tick marks between positions are hidden; only the labeled major tick marks at the main breaks are shown.
  • Enhancement: sd_reactive() no longer warns when its expression fails simply because the questions it references are not answered yet (e.g., arithmetic on a blank value at session start). Question references (input$x, all_data$x, sd_value(), sd_values()) are extracted from the expression; if any referenced value is still blank when an error occurs, the error is treated as the expected "not answered yet" state and "" is stored quietly. Genuine errors (all referenced values filled in, or no detectable references) still warn. For this detection to work, call sd_value() *inside* the sd_reactive() expression rather than capturing values in local variables beforehand.
  • Bug fix: Navigating back to and then forward again past an answered matrix (or matrix_multiple) question no longer crashes the survey. The matrix parent question has no input of its own, so its stored value can be NA; the restoration guard now handles NA safely instead of erroring.
  • Bug fix: Multi-value answers (mc_multiple, mc_multiple_buttons, daterange, and range slider_numeric) are now correctly restored when a respondent navigates back to a page or refreshes. These answers are stored pipe-joined (e.g. "red|blue"), but the restoration logic was splitting on commas, so previously the inputs came back blank. They now split on the pipe to match how the values are stored.
  • Bug fix: mode: preview (and mode: local) now guarantee that the database is never used, even when a valid connection is passed to sd_server(). Previously, if sd_db_connect() succeeded while mode: preview was set, responses were silently written to the database while the banner claimed they were going to preview_data.csv. The connection is still created and tested by sd_db_connect() (so credentials are verified during preview), but all reads and writes go to the local CSV. When a connection exists but is ignored, the preview banner now reads "Database connected but not used" and a console message explains how to switch to database mode. sd_db_connect() no longer claims "Running in database mode" on connection (it cannot know the survey mode); it simply reports that the connection succeeded. sd_server() now always prints the operating mode on the console at session start for every mode: preview/local (with or without an ignored connection), database with a working connection, and a warning when mode is database but no connection is available (responses not saved). This also applies to sd_store_value(), which previously could read session-persistence values from the database in preview mode via the auto-detected db object.
  • Bug fix: Restoring a cookied session in preview/local mode crashed the app with object 'local_csv_file' not found (a respondent refreshing the page in these modes hit a grey screen and a new session row). The local CSV filename is now set before handle_sessions() runs. The bug was introduced with the mode setting in v1.2.0 and only affected cookie restoration without a database connection; database mode was unaffected.
  • Bug fix: A warm _survey/ cache is now invalidated when the installed surveydown package is newer than the cached render. Previously, upgrading the package did not trigger a re-render, so surveys kept serving the previous package version's embedded JavaScript and CSS until survey.qmd was next edited.
  • Efficiency: Consolidated the per-question observers in sd_server(). Two of the three observer sets created for every question (*_manual_range and *_autosave_timestamp) were dead code — the client-side JavaScript that emitted those inputs was removed in earlier refactors — so each question now registers one observer instead of three. The *_value, *_label_option, and *_label_question outputs are registered once per question (reading reactively from all_data) instead of being re-registered on every input event; as a side benefit, sd_output(id, type = "value") now shows values restored from a resumed session before any new interaction.
  • Efficiency: In preview/local mode, the response CSV (preview_data.csv / local_data.csv) is now held in an in-process cache instead of being re-read from disk on every save and every lookup. Local modes run in a single R process, so all sessions share one copy per file; entries are keyed by absolute path and invalidated if the file changes on disk (external edits or deletion are picked up). Saves still write the complete file to disk every time, so no data is lost on a crash. Also removed a duplicate definition of get_local_data() that existed in both server.R and util.R. Database mode is unaffected.
  • Efficiency: App startup with a warm _survey/ cache no longer runs quarto::quarto_inspect() (a 1-3s subprocess) or rewrites settings.yml. When nothing changed, sd_ui() reads the progress bar and footer settings from the cached _survey/settings.yml; previously the unconditional settings rewrite also bumped its mtime, forcing run_config() to re-parse all pages and questions on every startup. This mainly speeds up cold starts of deployed apps (new workers, container restarts). The full inspect path still runs whenever survey.qmd, any YAML file, or app.R changes, or if the cached settings are missing/unreadable.
Show all changes in 1.3.0Hide the rest of the changes in 1.3.0
  • Efficiency / bug fix: The per-question inline JavaScript for mc_buttons, mc_multiple_buttons, and numeric questions has been replaced with delegated handlers in interaction.js, registered once per page load. Previously each question embedded its own script; for reactive questions (re-rendered via the server), the mc_buttons/mc_multiple_buttons scripts re-registered a new document-level click handler on every re-render, so handlers accumulated over a session. The numeric input's validation, spinner UI, and paste handling now also live in the shared file (the spinner is injected on Shiny's shiny:bound event, so it works for reactive questions too), shrinking the rendered HTML. Surveys with a stale _survey/ cache keep working (the old inline scripts remain functional alongside the new handlers until the next re-render).
  • Efficiency: The cookie-sync observer (which mirrors current-page answers, page history, and shuffle orders into the browser cookie) is now debounced by 500ms. Previously it re-serialized all current-page answers and messaged the client on every input change — including every keystroke in text questions. Now a single cookie update is sent shortly after the respondent pauses.
  • Efficiency: Parsed _survey/settings.yml content (settings and system messages) is now cached per Shiny session in session$userData, so repeated calls (e.g., per reactive question or per sd_store_value()) no longer re-read and re-parse the file from disk. Calls made outside a Shiny session (e.g., during Quarto rendering of survey.qmd) still read directly from disk.
  • Efficiency: The show_if observer no longer depends on every input via reactiveValuesToList(input), which re-evaluated all show_if conditions on every keystroke of any input. It now depends only on the question values actually referenced in the conditions (extracted statically, plus dependencies registered dynamically during condition evaluation). Since show_if target containers are baked into each page's HTML as hidden, the rendered page now signals the server when its DOM is inserted (sd_page_rendered) so question visibility is re-applied on every page render.
  • Internal: Question types are now defined in a single registry (R/question_types.R). Each type provides a render() (build the UI) and restore() (re-apply a stored value when navigating back) function plus a requires_option flag. sd_question() and the page-restoration logic in sd_server() dispatch through this registry instead of long if/else chains, so adding a new question type touches one place. No change to existing behavior.
  • Testing: Added tests/manual/ with chromote-based headless browser tests covering sd_show_if() (all condition styles, including cross-page input$/all_data$ conditions), sd_skip_if() (simple and two-question skips, required-question blocking), sd_stop_if() (stop messages, priority over required warnings, per-page applicability), data storage in preview mode (every question type verified end-to-end in preview_data.csv, including pipe-joined multi-selects, slider label-to-value mapping, matrix sub-columns, sd_store_value(), and session metadata), and cookies/session restoration (page refresh restores the current page and answers, sessions resume with the same session_id and a single CSV row, and a fresh browser starts a new session). The tests run against bundled apps in tests/manual/apps/, so they are self-contained and machine-independent. tests/manual/run-all.R runs the whole suite (in parallel when mirai is installed). Not run by devtools::test() or R CMD check.

From NEWS.md in the release

Install

Health

CRAN checks
13OK
Slowest check: 1.8 min · r-oldrel-windows-x86_64
Status changes
  • OK13 OK2026-08-04
  • NOTE12 OK, 1 NOTE2026-08-01
  • OK13 OK2026-06-09
  • WARNING12 OK, 1 WARNING2026-06-08
  • NOTE12 OK, 1 NOTE2026-06-07
Show 1 earlier changeHide 1 earlier change
  • OK14 OK2026-03-10
Advisories

none known

Documentation

In release 1.3.0
READMEYes · 520 wordsVignettesNoNEWSYes · 100% structured · mentions 1.3.0Citation fileYes · cites a publicationWebsiteYes · pkgdown
Help pages
38
Examples that run
87%27 run in a plain check (25 of them under a condition) · 4 never run
Exported functions with examples
82%
Documented parameters
99%
Return-value docs
97%
Help pages citing references
0%

Downloads

5.8K
CRAN downloads in the past year
Rank #6,731 · ~16/day · ~480/mo
Daily download trend is not available in this view yet.
47330 days
1.3K90 days
5.8K1 year
Compare downloads with other packages →
Also on156 r2u

Repository

186Stars
24Forks
15Open issues
2Open PRs
3Releases
1,450Commits
12Commit identities
markdownrsurveyquartoshinyshiny-appsshiny-rsupabase
1,450 commits · Last activity 2026-06-23 · +1.6% stars, 30d · Discussions: 80 posts
Responsiveness
How these are sampled
PRs merged (all time)
97%
Median days to close, 50 most recently updated closed issues
7
Median days to close, 50 most recently updated closed PRs
0

Stars over time

2025-10-21 · 1422026-10-22 · 186
PracticesBeta

12 development-tooling and community-health practices detected across 5 families in the upstream repository

Checks run against github.com/surveydown-dev/surveydown on 2026-10-18.

Continuous integration (1)
GitHub Actions
Governance and community (4)
Code of conductContributing guideIssue templatesPR template
Docs source (4)
README.Rmdpkgdown

GitHub Pages site last deployed 2026-06-23 · The repository has a site deploy workflow

pkgdown site last built 2026-06-23

CRAN release process (2)
cran-comments.mdCRAN-SUBMISSION
Show all practicesHide 1 practice
Lint, format, editor (1)
RStudio project
How this is detected·Detection ruleset v3 (2026-09-26)
AI coding toolsBeta

This repository shows signs of AI coding tools.

  • Claude Codefirst seen 2025-06-11
    Seen in the repository: CLAUDE.md
    Named in .Rbuildignore: .claude, CLAUDE.md
    Named in .gitignore: .claude
    Commits: at least 7 crediting it in the message
Models named in its commits
  • Claude Opus 4.62 commits · Mar 2026
  • Claude Sonnet 4.62 commits · Jun 2026
  • Claude Opus 4.81 commit · Jun 2026
Counts are commits, not lines of code. Commits by a tool's accounts count once across all of its accounts. Commits crediting it are the largest count among its credit lines, a minimum.How this is detected·Detection ruleset v4 (updated 2026-09-27)

Dependencies

Declared dependencies
23 external dependencies (excludes base and recommended)

Installing surveydown adds 71 packages (36 with compiled code, 39 MB of source tarballs). Heaviest: bslib 5.6 MB, promises 3.1 MB, sass 2.9 MB.

Depends (1)
R >= 4.1.0
LinkingTo (0)
none
Enhances (0)
none
Reverse dependencies
1direct
0indirect
Imports 1
Depends, Imports or LinkingTo, most downloaded first

People & History

People (7)
Author, Maintainer since 0.4.0 (2024), Copyright holder
Author, Copyright holder
Author, Copyright holder
Contributor · added in 1.3.0
Contributor · added in 1.3.0
Contributor · added in 0.5.0
Contributor · added in 1.3.0
Releases (14)

Pick two releases to compare their code metrics.

  • 1.3.0Latest
    record
    2026-06-23 · current release · diff ↗ ·
    added 2 exports
    sd_value, sd_values
  • R
    R 4.6.0 released · 2026-04-24
  • 1.0.1
    record
    2025-12-19 · diff ↗ ·
    removed 1 export
    sd_create_translations
    added 2 exports
    sd_create_messages, sd_nav
  • 0.14.0
    record
    2025-11-03 · diff ↗
  • 0.13.3
    record
    2025-09-30 · diff ↗ ·
    added 1 export
    sd_stop_if
  • 0.13.0
    record
    2025-08-20 · diff ↗
  • 0.12.6
    record
    2025-07-07 · diff ↗
  • 0.11.0
    record
    2025-04-17 · diff ↗
  • R
    R 4.5.0 released · 2025-04-11
  • 0.10.1
    record
    2025-04-08 · diff ↗ ·
    removed 1 export
    sd_show_password
    added 2 exports
    sd_page_gadget, sd_question_gadget
  • 0.9.0
    record
    2025-03-18 · diff ↗ ·
    added 2 exports
    sd_reactive, sd_skip_forward
  • 0.8.0
    record
    2025-01-27 · diff ↗ ·
    added 3 exports
    sd_dashboard, sd_db_config, sd_db_connect
  • 0.7.2
    record
    2024-12-13 · diff ↗ ·
    added 1 export
    sd_question_custom
  • 0.5.1
    record
    2024-11-27 · diff ↗
  • 0.5.0
    record
    2024-11-25 · diff ↗ ·
    added 1 export
    sd_create_translations
  • 0.4.0
    record
    2024-11-01
Show 1 earlier eventHide 1 earlier event
  • R
    R 4.4.0 released · 2024-04-24

Package metadata

First published
2024-11-01
Total releases
14 / 2 yrs
License
MIT + file LICENSE OSI
Minimum R
≥ 4.1.0
Download size
650 KB

Cite

Cite this package

Run in R for the authors' entry:

citation("surveydown")

The package provides a citation file, so citation() returns the authors' own entry.

It points to 10.1371/journal.pone.0331002.

Cite the R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

APA

Balamuta, J. J. (2026). R Observatory: Metrics for surveydown version 1.3.0 [Data set]. HJJB, LLC. Data release v2026-10-22. https://doi.org/10.5281/zenodo.21843040

From data release v2026-10-22, which the citation names so these numbers can be found later. More on citing and the projects behind them.

Report a problem with this page →

Privacy choices

These apply to this browser and are stored on this device only. Nothing about your choice is sent to us.

Read the privacy policy