siamang 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. siamang-0.5.0/CHANGELOG.md +55 -0
  2. siamang-0.5.0/LICENSE +21 -0
  3. siamang-0.5.0/MANIFEST.in +13 -0
  4. siamang-0.5.0/PKG-INFO +335 -0
  5. siamang-0.5.0/README.md +282 -0
  6. siamang-0.5.0/docs/concepts.md +247 -0
  7. siamang-0.5.0/docs/cookbook.md +351 -0
  8. siamang-0.5.0/docs/getting-started.md +112 -0
  9. siamang-0.5.0/docs/index.md +104 -0
  10. siamang-0.5.0/docs/reference/cli.md +193 -0
  11. siamang-0.5.0/docs/reference/core.md +491 -0
  12. siamang-0.5.0/docs/reference/data.md +187 -0
  13. siamang-0.5.0/docs/reference/deploy.md +494 -0
  14. siamang-0.5.0/docs/reference/frontend.md +278 -0
  15. siamang-0.5.0/docs/reference/io.md +155 -0
  16. siamang-0.5.0/docs/reference/reporting.md +318 -0
  17. siamang-0.5.0/pyproject.toml +131 -0
  18. siamang-0.5.0/setup.cfg +4 -0
  19. siamang-0.5.0/siamang/__init__.py +124 -0
  20. siamang-0.5.0/siamang/__main__.py +6 -0
  21. siamang-0.5.0/siamang/cli/__init__.py +5 -0
  22. siamang-0.5.0/siamang/cli/__main__.py +6 -0
  23. siamang-0.5.0/siamang/cli/deploy.py +54 -0
  24. siamang-0.5.0/siamang/cli/entry.py +91 -0
  25. siamang-0.5.0/siamang/cli/init.py +63 -0
  26. siamang-0.5.0/siamang/cli/loader.py +34 -0
  27. siamang-0.5.0/siamang/cli/preview.py +73 -0
  28. siamang-0.5.0/siamang/cli/validate.py +32 -0
  29. siamang-0.5.0/siamang/config/__init__.py +14 -0
  30. siamang-0.5.0/siamang/config/loader.py +193 -0
  31. siamang-0.5.0/siamang/config/secrets.py +29 -0
  32. siamang-0.5.0/siamang/core/__init__.py +59 -0
  33. siamang-0.5.0/siamang/core/block.py +26 -0
  34. siamang-0.5.0/siamang/core/expression.py +235 -0
  35. siamang-0.5.0/siamang/core/filter_rule.py +18 -0
  36. siamang-0.5.0/siamang/core/media.py +93 -0
  37. siamang-0.5.0/siamang/core/option.py +57 -0
  38. siamang-0.5.0/siamang/core/page.py +30 -0
  39. siamang-0.5.0/siamang/core/question.py +254 -0
  40. siamang-0.5.0/siamang/core/questionnaire.py +527 -0
  41. siamang-0.5.0/siamang/core/quota.py +17 -0
  42. siamang-0.5.0/siamang/core/script.py +174 -0
  43. siamang-0.5.0/siamang/core/serialization.py +92 -0
  44. siamang-0.5.0/siamang/core/variable.py +497 -0
  45. siamang-0.5.0/siamang/data/__init__.py +6 -0
  46. siamang-0.5.0/siamang/data/analysis.py +285 -0
  47. siamang-0.5.0/siamang/data/processing.py +20 -0
  48. siamang-0.5.0/siamang/data/survey_data.py +404 -0
  49. siamang-0.5.0/siamang/data/tables.py +114 -0
  50. siamang-0.5.0/siamang/deploy/__init__.py +24 -0
  51. siamang-0.5.0/siamang/deploy/backend_config.py +23 -0
  52. siamang-0.5.0/siamang/deploy/backends/gsheets.py +416 -0
  53. siamang-0.5.0/siamang/deploy/backends/local.py +169 -0
  54. siamang-0.5.0/siamang/deploy/backends/supabase.py +501 -0
  55. siamang-0.5.0/siamang/deploy/base.py +45 -0
  56. siamang-0.5.0/siamang/deploy/frontends/local.py +241 -0
  57. siamang-0.5.0/siamang/deploy/frontends/netlify.py +274 -0
  58. siamang-0.5.0/siamang/deploy/frontends/vercel.py +196 -0
  59. siamang-0.5.0/siamang/deploy/pipeline.py +79 -0
  60. siamang-0.5.0/siamang/deploy/registry.py +69 -0
  61. siamang-0.5.0/siamang/deploy/result.py +36 -0
  62. siamang-0.5.0/siamang/frontend/__init__.py +66 -0
  63. siamang-0.5.0/siamang/frontend/builder.py +110 -0
  64. siamang-0.5.0/siamang/frontend/bundle.py +97 -0
  65. siamang-0.5.0/siamang/frontend/client/__init__.py +14 -0
  66. siamang-0.5.0/siamang/frontend/client/base.py +34 -0
  67. siamang-0.5.0/siamang/frontend/client/gsheets.py +98 -0
  68. siamang-0.5.0/siamang/frontend/client/local.py +51 -0
  69. siamang-0.5.0/siamang/frontend/client/supabase.py +66 -0
  70. siamang-0.5.0/siamang/frontend/compiler/__init__.py +12 -0
  71. siamang-0.5.0/siamang/frontend/compiler/logic.py +43 -0
  72. siamang-0.5.0/siamang/frontend/compiler/quota.py +22 -0
  73. siamang-0.5.0/siamang/frontend/compiler/react.py +466 -0
  74. siamang-0.5.0/siamang/frontend/compiler/schema.py +116 -0
  75. siamang-0.5.0/siamang/frontend/constants.py +26 -0
  76. siamang-0.5.0/siamang/frontend/runtime/__init__.py +7 -0
  77. siamang-0.5.0/siamang/frontend/runtime/base.py +61 -0
  78. siamang-0.5.0/siamang/frontend/runtime/react.py +207 -0
  79. siamang-0.5.0/siamang/frontend/runtime/surveyjs.py +142 -0
  80. siamang-0.5.0/siamang/frontend/schema.py +71 -0
  81. siamang-0.5.0/siamang/frontend/templates/closed.html.tpl +16 -0
  82. siamang-0.5.0/siamang/frontend/templates/index.html.tpl +101 -0
  83. siamang-0.5.0/siamang/frontend/templates/react/__init__.py +0 -0
  84. siamang-0.5.0/siamang/frontend/templates/react/app.jsx +712 -0
  85. siamang-0.5.0/siamang/frontend/templates/react/closed.html.tpl +18 -0
  86. siamang-0.5.0/siamang/frontend/templates/react/dist/bundle.js +1 -0
  87. siamang-0.5.0/siamang/frontend/templates/react/hooks.jsx +263 -0
  88. siamang-0.5.0/siamang/frontend/templates/react/index.html.tpl +39 -0
  89. siamang-0.5.0/siamang/frontend/templates/react/questions.jsx +785 -0
  90. siamang-0.5.0/siamang/frontend/templates/react/store.jsx +130 -0
  91. siamang-0.5.0/siamang/frontend/templates/react/style.css.tpl +1868 -0
  92. siamang-0.5.0/siamang/frontend/templates/react/vendor/__init__.py +0 -0
  93. siamang-0.5.0/siamang/frontend/templates/react/vendor/react-dom.production.min.js +267 -0
  94. siamang-0.5.0/siamang/frontend/templates/react/vendor/react.production.min.js +31 -0
  95. siamang-0.5.0/siamang/frontend/templates/react/visibility.jsx +164 -0
  96. siamang-0.5.0/siamang/frontend/theme/__init__.py +7 -0
  97. siamang-0.5.0/siamang/frontend/theme/css.py +483 -0
  98. siamang-0.5.0/siamang/frontend/theme/presets.py +98 -0
  99. siamang-0.5.0/siamang/frontend/theme/ui_config.py +205 -0
  100. siamang-0.5.0/siamang/io/__init__.py +26 -0
  101. siamang-0.5.0/siamang/io/csv.py +22 -0
  102. siamang-0.5.0/siamang/io/dictionary.py +26 -0
  103. siamang-0.5.0/siamang/io/excel.py +22 -0
  104. siamang-0.5.0/siamang/io/r.py +77 -0
  105. siamang-0.5.0/siamang/io/reader.py +26 -0
  106. siamang-0.5.0/siamang/io/spss.py +155 -0
  107. siamang-0.5.0/siamang/io/stata.py +111 -0
  108. siamang-0.5.0/siamang/local_simulator.py +216 -0
  109. siamang-0.5.0/siamang/py.typed +0 -0
  110. siamang-0.5.0/siamang/reporting/__init__.py +22 -0
  111. siamang-0.5.0/siamang/reporting/accessors.py +250 -0
  112. siamang-0.5.0/siamang/reporting/charts.py +473 -0
  113. siamang-0.5.0/siamang/reporting/tables.py +373 -0
  114. siamang-0.5.0/siamang.egg-info/PKG-INFO +335 -0
  115. siamang-0.5.0/siamang.egg-info/SOURCES.txt +119 -0
  116. siamang-0.5.0/siamang.egg-info/dependency_links.txt +1 -0
  117. siamang-0.5.0/siamang.egg-info/entry_points.txt +12 -0
  118. siamang-0.5.0/siamang.egg-info/requires.txt +37 -0
  119. siamang-0.5.0/siamang.egg-info/top_level.txt +1 -0
  120. siamang-0.5.0/tests/test_adapters.py +360 -0
  121. siamang-0.5.0/tests/test_reporting.py +183 -0
@@ -0,0 +1,55 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.5.0] — 2026-05-28
9
+
10
+ ### Added
11
+
12
+ - **Theming system**: `UIConfig` with `font_preset` (classic, modern, humanist),
13
+ `accent_color`, and CSS custom properties for full visual customization.
14
+ - **"Other (specify)"** option for `SingleChoice` and `MultiChoice` questions
15
+ via `other_specify=True`.
16
+ - **Answers store**: lightweight reactive store (`useSyncExternalStore`) replacing
17
+ top-level `useState` — eliminates full-tree re-renders on every keystroke.
18
+ - **Compiled visibility**: `show_if`/`hide_if` conditions compiled to JS functions
19
+ at load time (no more per-render AST interpretation).
20
+ - **Hooks decomposition**: `useSurveyNav`, `useSubmission`, `useAutosave`,
21
+ `useLifecycleScripts`, `useKeyboardShortcuts`, `useTheme`.
22
+ - Supabase backend now uses a single shared `responses` table with `survey_id`
23
+ column (consistent with local SQLite backend).
24
+ - Environment variable naming: `SIAMANG_SUPABASE_*` with backward-compatible
25
+ fallback to legacy `SURVLIB_SUPABASE_*`.
26
+ - Script factory functions now use `json.dumps()` for parameter escaping
27
+ (prevents injection from special characters in IDs/messages).
28
+
29
+ ### Changed
30
+
31
+ - Development status set to **Beta** (honest reflection of current test coverage).
32
+ - Slider component: adaptive tick rendering (≤20 steps → labeled ticks,
33
+ >20 steps → end-labels only). Fixes the "wall of numbers" bug.
34
+ - Frontend JS globals renamed: `window.SIAMANG_ENV` / `window.SIAMANG_TRANSPORTS`
35
+ (runtime falls back to legacy `SURVLIB_*` names for backward compatibility).
36
+
37
+ ### Fixed
38
+
39
+ - Supabase backend/frontend mismatch: frontend now POSTs `{survey_id, data}`
40
+ matching the shared table schema (previously sent `{survey_id, payload}` to
41
+ a per-survey table that didn't have a `survey_id` column).
42
+ - Slider rendering bug: no longer outputs 61 `<option>` elements for range 0–60.
43
+
44
+ ### Removed
45
+
46
+ - Per-survey table creation (`responses_{survey_id}`) in Supabase backend —
47
+ replaced by shared `responses` table.
48
+ - `BUILD.md` reference removed from MANIFEST.in (file never existed).
49
+
50
+ ## [0.4.1] — 2026-04-15
51
+
52
+ ### Added
53
+
54
+ - Initial public structure with core survey engine, React frontend, CLI,
55
+ local SQLite backend, and Supabase/Vercel deployment support.
siamang-0.5.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Siamang Project Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ include README.md CHANGELOG.md LICENSE MANIFEST.in
2
+ include pyproject.toml
3
+
4
+ recursive-include siamang *.tpl *.jsx *.js py.typed
5
+ recursive-include docs *.md
6
+ recursive-include examples *.py
7
+
8
+ global-exclude *.map
9
+ global-exclude *.ts
10
+ global-exclude *.tsx
11
+ global-exclude __pycache__
12
+ global-exclude *.py[cod]
13
+ global-exclude .DS_Store
siamang-0.5.0/PKG-INFO ADDED
@@ -0,0 +1,335 @@
1
+ Metadata-Version: 2.4
2
+ Name: siamang
3
+ Version: 0.5.0
4
+ Summary: Research-as-code framework for sociological surveys.
5
+ Author: Siamang Project Contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/hanelias/siamang
8
+ Project-URL: Manual, https://github.com/hanelias/siamang/blob/main/MANUAL.md
9
+ Project-URL: Issues, https://github.com/hanelias/siamang/issues
10
+ Keywords: survey,research,sociology,questionnaire,polling
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Classifier: Topic :: Sociology
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: pandas>=2.0
26
+ Requires-Dist: fastapi>=0.110
27
+ Requires-Dist: uvicorn>=0.29
28
+ Requires-Dist: openpyxl>=3.1
29
+ Requires-Dist: pyreadstat>=1.2
30
+ Requires-Dist: scipy>=1.11
31
+ Requires-Dist: supabase>=2.0
32
+ Requires-Dist: requests>=2.31
33
+ Provides-Extra: dev
34
+ Requires-Dist: ruff>=0.4; extra == "dev"
35
+ Requires-Dist: mypy>=1.10; extra == "dev"
36
+ Requires-Dist: pytest>=8.0; extra == "dev"
37
+ Requires-Dist: siamang[charts]; extra == "dev"
38
+ Provides-Extra: charts
39
+ Requires-Dist: matplotlib>=3.7; extra == "charts"
40
+ Requires-Dist: seaborn>=0.13; extra == "charts"
41
+ Provides-Extra: gsheets
42
+ Requires-Dist: google-auth>=2.0; extra == "gsheets"
43
+ Requires-Dist: google-auth-httplib2>=0.1; extra == "gsheets"
44
+ Requires-Dist: google-api-python-client>=2.0; extra == "gsheets"
45
+ Provides-Extra: all
46
+ Provides-Extra: excel
47
+ Provides-Extra: pyreadstat
48
+ Provides-Extra: server
49
+ Provides-Extra: supabase
50
+ Provides-Extra: vercel
51
+ Provides-Extra: scipy
52
+ Dynamic: license-file
53
+
54
+ <h1 align="center">siamang</h1>
55
+
56
+ <p align="center">
57
+ <strong>Research-as-code framework for sociological surveys.</strong><br>
58
+ Define variables, questionnaires, and logic in pure Python — then
59
+ deploy, collect, and analyze in a single pipeline.
60
+ </p>
61
+
62
+ <p align="center">
63
+ <a href="#quick-start">Quick start</a> ·
64
+ <a href="#full-pipeline-example">Full pipeline example</a> ·
65
+ <a href="docs/reference/">API Reference</a>
66
+ </p>
67
+
68
+ ---
69
+
70
+ ```bash
71
+ pip install git+https://github.com/hanelias/siamang.git
72
+ siamang validate my_survey.py
73
+ siamang preview my_survey.py # local preview
74
+ siamang deploy my_survey.py --backend supabase --frontend vercel
75
+ ```
76
+
77
+ ---
78
+
79
+ ## What it does
80
+
81
+ siamang turns a survey into a running web application from a single
82
+ Python script:
83
+
84
+ ```
85
+ my_survey.py ← you write this
86
+
87
+ ├─ siamang validate → catches errors before deployment
88
+ ├─ siamang preview → local frontend (hot-reload)
89
+ ├─ siamang deploy → Vercel + Supabase (cloud deployment)
90
+ └─ survey.simulate() → synthetic data for testing
91
+ ```
92
+
93
+ **No GUI builders. No drag-and-drop. No lock-in.** Your survey is a
94
+ Python module — version-control it, test it, reuse it.
95
+
96
+ ---
97
+
98
+ ## Quick start
99
+
100
+ ```python
101
+ from siamang.core import (
102
+ Variable, SingleChoice, LikertScale, Page, Questionnaire,
103
+ )
104
+
105
+ # Define variables with full metadata
106
+ satisfaction = Variable(
107
+ "satisfaction", scale="ordinal",
108
+ label="Overall satisfaction",
109
+ labels={1: "Very dissatisfied", 2: "Dissatisfied",
110
+ 3: "Neutral", 4: "Satisfied", 5: "Very satisfied"},
111
+ )
112
+ remote_freq = Variable(
113
+ "remote_freq", scale="ordinal",
114
+ label="Remote work frequency",
115
+ labels={1: "Never", 2: "1-2 days/week",
116
+ 3: "3-4 days/week", 4: "Fully remote"},
117
+ )
118
+
119
+ # Build questions
120
+ q_sat = LikertScale("How satisfied are you with your current role?",
121
+ var=satisfaction, points=5, required=True)
122
+ q_remote = SingleChoice("How often do you work remotely?",
123
+ var=remote_freq, display="radio", required=True)
124
+
125
+ # Assemble questionnaire
126
+ survey = Questionnaire(
127
+ title="Work Attitudes Study",
128
+ pages=[Page("main", items=[q_sat, q_remote])],
129
+ )
130
+
131
+ # Simulate and analyze
132
+ data = survey.simulate(n=200)
133
+ print(data.report.freq("satisfaction").to_markdown())
134
+
135
+ # Visualize (requires: pip install siamang[charts])
136
+ data.plot.bar("satisfaction").show()
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Full Pipeline Example
142
+
143
+ The [`examples/full_pipeline/`](examples/full_pipeline/) directory contains a complete Jupyter notebook demonstrating the entire research workflow — from survey design to statistical analysis:
144
+
145
+ 1. **Survey Design** — 12 variables, 5 pages, conditional routing (`show_if`), matrix questions, Likert scales
146
+ 2. **Simulation & Deployment** — 250 synthetic respondents, local SQLite storage, interactive HTML preview
147
+ 3. **Declarative Reporting** — frequency tables, cross-tabs with Chi², grouped means with auto-selected tests, correlation heatmaps
148
+ 4. **Visualizations** — bar charts, boxplots, heatmaps, scatter plots — all with one line of code
149
+
150
+ ```bash
151
+ cd examples/full_pipeline
152
+ jupyter notebook full_pipeline_demo.ipynb
153
+ ```
154
+
155
+ The folder also includes `survey_preview.html` — an interactive HTML survey you can open in any browser to see how the questionnaire looks for respondents.
156
+
157
+ ---
158
+
159
+ ## Features
160
+
161
+ | Area | Capabilities |
162
+ | :--- | :--- |
163
+ | **Core** | Variables (nominal/ordinal/interval/ratio), questions (single/multi/open/numeric/likert/matrix/ranking), pages, skip logic (`show_if`/`hide_if`), quotas, validation |
164
+ | **Reporting** | Declarative tables (`FreqTable`, `CrossTable`, `GroupMeanTable`) and charts (`BarChart`, `BoxPlot`, `HeatMap`, `ScatterPlot`) — automatic labels, statistical tests, and metadata awareness |
165
+ | **Scripts** | Inline JavaScript for survey-side behaviour — 7 trigger points |
166
+ | **Frontend** | SurveyJS and React 18 runtimes, dark mode, auto-save, access codes, 6 theme presets |
167
+ | **Backend** | Local SQLite for development, Supabase for production, Google Sheets for collaborative access |
168
+ | **Deploy** | Vercel and Netlify frontends with CSP headers; self-contained HTML bundle for offline use |
169
+ | **Data I/O** | CSV, Excel (.xlsx), SPSS (.sav), Stata (.dta), R (.rda) — round-trip with labels and missing values preserved |
170
+
171
+ ---
172
+
173
+ ## Declarative Reporting API
174
+
175
+ Siamang automatically uses variable metadata (labels, scales, missing values) to produce publication-ready outputs — like SPSS, but in Python:
176
+
177
+ ```python
178
+ data = survey.simulate(n=300)
179
+
180
+ # Tables — automatic labels, tests, and formatting
181
+ data.report.freq("it_role") # frequency table
182
+ data.report.crosstab("gender", "satisfaction", pct="col") # cross-tab + Chi²
183
+ data.report.means("autonomy", by="remote_freq") # means + Kruskal-Wallis
184
+
185
+ # Charts — one line, automatic axis labels
186
+ data.plot.bar("it_role")
187
+ data.plot.boxplot("satisfaction", by="remote_freq", show_points=True)
188
+ data.plot.heatmap(["surv_keystroke", "surv_camera"], by="remote_freq")
189
+ data.plot.scatter("satisfaction", "autonomy", hue="gender")
190
+
191
+ # Export
192
+ data.report.freq("it_role").to_markdown() # Markdown string
193
+ data.report.freq("it_role").to_frame() # pandas DataFrame
194
+ data.report.freq("it_role").to_html() # HTML table
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Deployment
200
+
201
+ ### Local (development)
202
+
203
+ ```bash
204
+ siamang preview my_survey.py # → http://127.0.0.1:8000
205
+ ```
206
+
207
+ ### Cloud — Vercel + Supabase (high concurrency)
208
+
209
+ ```bash
210
+ siamang init # one-time: stores credentials
211
+ siamang deploy my_survey.py --backend supabase --frontend vercel
212
+ ```
213
+
214
+ ### Cloud — Netlify + Google Sheets (lightweight)
215
+
216
+ ```bash
217
+ export SIAMANG_GSHEETS_CREDENTIALS_FILE=./service-account-key.json
218
+ export NETLIFY_AUTH_TOKEN=nfp_...
219
+ siamang deploy my_survey.py --backend gsheets --frontend netlify
220
+ ```
221
+
222
+ Responses are written to a Google Spreadsheet (one row per respondent) via an **Apps Script proxy** that acts as a secure intermediary. The survey is hosted on Netlify CDN with automatic HTTPS and global edge distribution.
223
+
224
+ > **Note:** The Google Sheets backend is currently **experimental** for public web deployments. Browser-to-Sheets writes require an Apps Script Web App URL to avoid exposing credentials. See [`docs/reference/deploy.md`](docs/reference/deploy.md#googlesheetsbackend) for setup instructions.
225
+
226
+ ### Deployment combinations
227
+
228
+ | Use case | Backend | Frontend |
229
+ | :--- | :--- | :--- |
230
+ | Local development / testing | `local` | `local` |
231
+ | Small survey, shared with team | `gsheets` | `netlify` |
232
+ | Production, high concurrency | `supabase` | `vercel` or `netlify` |
233
+ | Offline / air-gapped | `local` | `local` (HTML bundle) |
234
+
235
+ ---
236
+
237
+ ## Project Layout
238
+
239
+ ```
240
+ siamang/
241
+ ├── core/ Variable, Question types, Block, Page, Questionnaire, Expression, Quota, Script
242
+ ├── data/ SurveyData, DataAnalysis, DataProcessing, SurveyTables
243
+ ├── reporting/ Declarative tables (FreqTable, CrossTable, GroupMeanTable) and charts (BarChart, BoxPlot, HeatMap, ScatterPlot)
244
+ ├── frontend/ SurveyJS & React runtimes, bundle builder, UIConfig theme engine, presets
245
+ ├── deploy/ Backends (SQLite, Supabase, Google Sheets), frontends (Vercel, Netlify, local), pipeline orchestration
246
+ ├── cli/ validate, preview, deploy, init
247
+ ├── io/ Import/export for CSV, Excel, SPSS, Stata, R
248
+ └── config/ User configuration (~/.siamang.toml), secrets
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Documentation
254
+
255
+ | Resource | Description |
256
+ | :--- | :--- |
257
+ | [`docs/reference/core.md`](docs/reference/core.md) | API reference — Variable, Expression, all Question types, Page, Questionnaire |
258
+ | [`docs/reference/data.md`](docs/reference/data.md) | API reference — SurveyData, DataAnalysis, DataProcessing, SurveyTables |
259
+ | [`docs/reference/reporting.md`](docs/reference/reporting.md) | API reference — Declarative tables and charts |
260
+ | [`docs/reference/frontend.md`](docs/reference/frontend.md) | API reference — UIConfig, theme presets, runtimes, bundle builder |
261
+ | [`docs/reference/deploy.md`](docs/reference/deploy.md) | API reference — Backends (Local, Supabase, Google Sheets), Frontends (Local, Vercel, Netlify), pipeline |
262
+ | [`examples/full_pipeline/`](examples/full_pipeline/) | Complete worked example: design → deploy → analyze |
263
+
264
+ ---
265
+
266
+ ## Requirements
267
+
268
+ - **Python 3.11+**
269
+ - For cloud deployment (option A): a **Supabase** project and a **Vercel** account
270
+ - For cloud deployment (option B): a **Google Cloud** service account and a **Netlify** account
271
+
272
+ ---
273
+
274
+ ## Dependencies
275
+
276
+ All core dependencies are installed automatically with `pip install siamang`.
277
+
278
+ ### Core (installed automatically)
279
+
280
+ | Package | Version | Purpose |
281
+ | :--- | :--- | :--- |
282
+ | `pandas` | ≥ 2.0 | Data manipulation, SurveyData backbone |
283
+ | `scipy` | ≥ 1.11 | Statistical tests (chi-square, t-test, ANOVA) |
284
+ | `openpyxl` | ≥ 3.1 | Excel (.xlsx) import/export |
285
+ | `pyreadstat` | ≥ 1.2 | SPSS (.sav) and Stata (.dta) import/export |
286
+ | `fastapi` | ≥ 0.110 | Local preview server (`siamang preview`) |
287
+ | `uvicorn` | ≥ 0.29 | ASGI server for local preview |
288
+ | `supabase` | ≥ 2.0 | Supabase backend (Postgres + RLS + Edge Functions) |
289
+ | `requests` | ≥ 2.31 | HTTP client for Netlify/Vercel deployment APIs |
290
+
291
+ ### Charts (optional)
292
+
293
+ ```bash
294
+ pip install siamang[charts]
295
+ ```
296
+
297
+ | Package | Version | Purpose |
298
+ | :--- | :--- | :--- |
299
+ | `matplotlib` | ≥ 3.7 | Chart rendering (`data.plot.bar()`, `.boxplot()`, `.scatter()`, `.heatmap()`) |
300
+ | `seaborn` | ≥ 0.13 | Statistical visualization helpers |
301
+
302
+ Charts are optional — if you only use tables (`data.report.freq()`, `data.report.crosstab()`), matplotlib is not needed. A clear error message will guide you if you try to render a chart without it.
303
+
304
+ ### Google Sheets backend (optional)
305
+
306
+ ```bash
307
+ pip install siamang[gsheets]
308
+ ```
309
+
310
+ | Package | Version | Purpose |
311
+ | :--- | :--- | :--- |
312
+ | `google-auth` | ≥ 2.0 | Service account authentication |
313
+ | `google-auth-httplib2` | ≥ 0.1 | HTTP transport for Google APIs |
314
+ | `google-api-python-client` | ≥ 2.0 | Google Sheets API and Google Drive API client |
315
+
316
+ ### Development
317
+
318
+ ```bash
319
+ pip install siamang[dev]
320
+ ```
321
+
322
+ | Package | Version | Purpose |
323
+ | :--- | :--- | :--- |
324
+ | `ruff` | ≥ 0.4 | Linting and formatting |
325
+ | `mypy` | ≥ 1.10 | Static type checking |
326
+ | `pytest` | ≥ 8.0 | Test runner |
327
+ | `matplotlib` | ≥ 3.7 | Required for chart tests |
328
+ | `seaborn` | ≥ 0.13 | Required for chart tests |
329
+
330
+ ---
331
+
332
+ ## License
333
+
334
+ Siamang is released under the [MIT License](LICENSE). Free for any use —
335
+ academic, commercial, personal.