softr-vibe-coding 1.8.0 → 1.9.0

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ All notable changes to this skill are documented here. Versions follow [Semantic
4
4
 
5
5
  Entries from 1.3.1 onward are generated automatically from git commit subjects between version bumps (see `.github/workflows/publish.yml`). Entries before 1.3.1 were backfilled by hand from the existing commit history.
6
6
 
7
+ ## [1.9.0] - 2026-06-04
8
+ - Bundle get-softr-database CLI script for schema export; document in SKILL.md, softr-database.md, fields.md
9
+ - Bump publish workflow to Node 24-based action majors — actions/checkout@v4 -> @v6, actions/setup-node@v4 -> @v6 (clears the Node 20 deprecation; GitHub forces Node 20 actions to Node 24 on 2026-06-16). No version bump, so this run skips publish.
10
+
7
11
  ## [1.8.0] - 2026-06-04
8
12
  - Expand references/native-chrome-styling.md to the full native shell — add Footer (semantic <footer> target + 160px/overflow-wrap contact-column email-wrap fix), floating "island" header/footer treatment, and Page background (Softr stacks the same fill on html/body/#page-content/inner-wrapper, so paint on html + clear the stack, EXCLUDING the .softr-topbar subtree so the dropdown panel survives) + a Console background-finder snippet; broaden SKILL.md Reference Guides row + README; add anti-patterns row for the page-background stacking; bump to 1.8.0
9
13
 
package/SKILL.md CHANGED
@@ -86,7 +86,7 @@ When the user describes their block, figure out which of these areas apply and a
86
86
 
87
87
  - **Data source type**: Is it Airtable, Softr Database, REST API, or another source? This determines the data fetching approach. **Load the relevant data source guide** from the [datasources/](datasources/) directory before writing code.
88
88
  - **Data source fields**: For Airtable/Softr Database, you need actual field IDs. For REST APIs, you access the raw API response directly. If the user doesn't know field IDs:
89
- - For **Softr Database**, the cleanest path is the **Softr Database MCP server** — ask whether they have it installed (`claude mcp list` shows it as `softr` or similar). If yes, query schema directly with the MCP tools instead of asking for paste-ins. If no, fall back to asking them to paste the `tablespace-with-tables` network response (DevTools -> Network -> filter that string while on Studio's Data tab) — the JSON contains every field ID, type, and dropdown option UUID. Optionally tell them they can install the MCP once with `claude mcp add --transport http softr https://mcp.softr.io/mcp` for future sessions. Full MCP details in [references/softr-database-mcp.md](references/softr-database-mcp.md); fallback paste-in workflows in [datasources/fields.md](datasources/fields.md#field-inspector-block).
89
+ - For **Softr Database**, the cleanest path is the **Softr Database MCP server** — ask whether they have it installed (`claude mcp list` shows it as `softr` or similar). If yes, query schema directly with the MCP tools instead of asking for paste-ins. If no, the next-best option is the bundled **`get-softr-database` CLI script** — tell the user to run `python3 ~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py <database_id>` (it prompts for their Softr API key and exports the full schema to `~/Desktop/softr-database-<id>-<timestamp>.json` — Python stdlib only, nothing to install) and paste the resulting JSON into chat. As a final fallback, ask them to paste the `tablespace-with-tables` network response (DevTools -> Network -> filter that string while on Studio's Data tab) — same JSON content, different acquisition path. Optionally tell them they can install the MCP once with `claude mcp add --transport http softr https://mcp.softr.io/mcp` for future sessions. Full MCP details in [references/softr-database-mcp.md](references/softr-database-mcp.md); CLI script details in [datasources/softr-database.md](datasources/softr-database.md#bundled-cli-script-get-softr-database); fallback paste-in workflows in [datasources/fields.md](datasources/fields.md#field-inspector-block).
90
90
  - For **Airtable** and other sources where empty `q.select({})` works, suggest the Field Inspector block.
91
91
  - **Brand colors**: Already resolved in Step 1 (Detect the brand source). Don't re-ask. The brand source is one of:
92
92
  - **Project's `./DESIGN.md`** (recommended for client work — produced by the `building-design-md` skill)
package/bin/cli.js CHANGED
@@ -10,7 +10,7 @@ var SETTINGS_FILE = path.join(os.homedir(), '.claude', 'settings.json');
10
10
  var PACKAGE_ROOT = path.resolve(__dirname, '..');
11
11
 
12
12
  var SKILL_FILES = ['SKILL.md', 'ui-ux-guidelines.md', 'README.md', 'LICENSE'];
13
- var SKILL_DIRS = ['references', 'datasources'];
13
+ var SKILL_DIRS = ['references', 'datasources', 'tools'];
14
14
 
15
15
  var HOOK_COMMAND = 'npx -y --prefer-online ' + SKILL_NAME + '@latest sync';
16
16
 
@@ -111,15 +111,17 @@ export default function Block() {
111
111
 
112
112
  1. **Softr Database MCP server (recommended for AI-assisted workflows)** -- if you're collaborating with an AI assistant (Claude Code, Claude Desktop, Cursor, ChatGPT, Mistral) to write Vibe Coding blocks, the official Softr MCP server is the cleanest path. The AI calls schema/list-fields tools directly against your workspace and reads back every field's `id`, `name`, `type`, and dropdown option UUIDs -- no copy-paste, no transcription errors. Full setup, scopes, and scope limitations (Softr DB only -- does NOT cover Airtable / external sources) in [../references/softr-database-mcp.md](../references/softr-database-mcp.md).
113
113
 
114
- 2. **Network inspector (full schema in one shot, no MCP needed)** -- in Studio's Data tab with browser DevTools open, filter Network requests by `tablespace-with-tables`. The Response JSON contains every table's complete schema, including:
114
+ 2. **`get-softr-database` CLI script (bundled, no MCP needed)** -- a Python CLI bundled with this skill at `~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py`. Exports the full schema (every table, every field, all dropdown option UUIDs) to `~/Desktop/softr-database-<id>-<timestamp>.json`. Run with `python3 ~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py <database_id>` (prompts for API key) or set `SOFTR_API_KEY=xxx` env var to skip the prompt. Stdlib only, no `pip install`. Best when you want a portable JSON dump for sharing in chat, archiving, or diffing across schema versions. Full usage in [softr-database.md](softr-database.md#bundled-cli-script-get-softr-database).
115
+
116
+ 3. **Network inspector (full schema in one shot, no MCP needed)** -- in Studio's Data tab with browser DevTools open, filter Network requests by `tablespace-with-tables`. The Response JSON contains every table's complete schema, including:
115
117
  - Each field's `id`, `name`, `type`, and `options`
116
118
  - For dropdown / SELECT fields: the full `choices` array with every option's `id` (UUID), `label`, and `color`
117
119
 
118
120
  Use this when scaffolding a block that needs many field IDs at once, or to look up dropdown option UUIDs needed for write payloads. **When working with an AI assistant without the MCP installed**, paste this JSON response into the chat -- second-best way to share accurate field IDs and dropdown UUIDs in one shot.
119
121
 
120
- 3. **Inline in Studio (one field at a time)** -- in the Data tab, click a field's name to open its edit drawer. The field ID appears next to the "Field name" label (e.g. `ID: 37fts`). Fastest for spot-checking a single field.
122
+ 4. **Inline in Studio (one field at a time)** -- in the Data tab, click a field's name to open its edit drawer. The field ID appears next to the "Field name" label (e.g. `ID: 37fts`). Fastest for spot-checking a single field.
121
123
 
122
- 4. **Softr Database REST API with `fieldNames=true`** -- runtime inspection from inside a Vibe Coding block (internal-portal blocks only, since this exposes a PAT in client code):
124
+ 5. **Softr Database REST API with `fieldNames=true`** -- runtime inspection from inside a Vibe Coding block (internal-portal blocks only, since this exposes a PAT in client code):
123
125
 
124
126
  ```jsx
125
127
  import { useEffect, useState } from "react";
@@ -24,11 +24,62 @@ q.select({ name: "First Name" })
24
24
  Find field IDs in this order of preference:
25
25
 
26
26
  1. **Softr Database MCP** (recommended when working with an AI assistant) — the AI calls schema/list-fields tools directly. See [../references/softr-database-mcp.md](../references/softr-database-mcp.md).
27
- 2. **Network inspector** — DevTools -> Network -> filter `tablespace-with-tables` for the full schema including dropdown option UUIDs. Paste the JSON into chat to share with an AI when the MCP isn't installed.
28
- 3. **Inline in Studio** — click a field's name in the Data tab; the ID appears in the field-edit drawer.
27
+ 2. **`get-softr-database` CLI script (bundled)** — a Python CLI bundled with this skill at `~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py`. Exports the full schema (every table, field, dropdown option UUID) to `~/Desktop/softr-database-<id>-<timestamp>.json`. Stdlib only, no `pip install`. See [Bundled CLI script](#bundled-cli-script-get-softr-database) below.
28
+ 3. **Network inspector** — DevTools -> Network -> filter `tablespace-with-tables` for the full schema including dropdown option UUIDs. Paste the JSON into chat to share with an AI when the MCP isn't installed.
29
+ 4. **Inline in Studio** — click a field's name in the Data tab; the ID appears in the field-edit drawer.
29
30
 
30
31
  The generic Field Inspector pattern with empty `q.select({})` does NOT work for Softr Database — see [fields.md](fields.md#field-inspector-block).
31
32
 
33
+ ## Bundled CLI script: `get-softr-database`
34
+
35
+ A Python CLI bundled with this skill that exports a complete Softr Tables database schema (every table, every field, all dropdown option UUIDs) to a timestamped JSON file on your Desktop. Stdlib only — no `pip install` required.
36
+
37
+ **Script location after `npx softr-vibe-coding@latest init`:**
38
+
39
+ ```
40
+ ~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py
41
+ ```
42
+
43
+ **Run it directly:**
44
+
45
+ ```bash
46
+ python3 ~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py <database_id>
47
+ ```
48
+
49
+ It prompts for your Softr API key (input hidden via `getpass`). To skip the prompt entirely, pass via env var:
50
+
51
+ ```bash
52
+ SOFTR_API_KEY=xxx python3 ~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py <database_id>
53
+ ```
54
+
55
+ Run with no args to be prompted for both the database ID and API key.
56
+
57
+ **Output:** `~/Desktop/softr-database-<databaseId>-<YYYYMMDD-HHMMSS>.json` containing:
58
+
59
+ ```json
60
+ {
61
+ "exportedAt": "...",
62
+ "source": "https://tables-api.softr.io/api/v1",
63
+ "databaseId": "...",
64
+ "database": { /* full database metadata */ },
65
+ "tableCount": N,
66
+ "fieldCount": M,
67
+ "tables": [ /* every table with its full fields[] array */ ]
68
+ }
69
+ ```
70
+
71
+ **Optional alias** for a shorter command. Add to your `~/.zshrc` or `~/.bashrc`:
72
+
73
+ ```bash
74
+ alias get-softr-database='python3 ~/.claude/skills/softr-vibe-coding/tools/get-softr-database.py'
75
+ ```
76
+
77
+ After `source ~/.zshrc`, just run `get-softr-database <database_id>` from anywhere.
78
+
79
+ **Get your Softr API key:** Softr workspace settings → API keys → create a new key with read access to the target database.
80
+
81
+ **When to use vs the MCP:** the MCP server is better for AI-assisted workflows (the assistant calls schema tools directly without any user action). This CLI script is better when you want a portable JSON file — for sharing in chat, archiving alongside your project, diffing across schema versions, or pasting a single big blob into Claude. The two approaches don't conflict; many projects use both.
82
+
32
83
  ## Supported Fields
33
84
 
34
85
  | Field Type | Writable | Notes |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "softr-vibe-coding",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Claude Code skill for generating production-ready Softr Vibe Coding blocks (JSX). Installs into ~/.claude/skills/ and auto-updates on each Claude Code session.",
5
5
  "bin": {
6
6
  "softr-vibe-coding": "./bin/cli.js"
@@ -11,6 +11,7 @@
11
11
  "ui-ux-guidelines.md",
12
12
  "references/",
13
13
  "datasources/",
14
+ "tools/",
14
15
  "LICENSE",
15
16
  "README.md",
16
17
  "CHANGELOG.md"
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ get-softr-database
4
+ ==================
5
+ Export a full Softr Tables database **schema** (every table, every field, and all
6
+ of their details) to a timestamped JSON file on your Desktop.
7
+
8
+ What it does
9
+ ------------
10
+ Given a Softr API key and a database ID, it calls two endpoints:
11
+
12
+ GET /api/v1/databases/{id} -> database metadata
13
+ GET /api/v1/databases/{id}/tables -> all tables, each with its full
14
+ `fields` array (type, options,
15
+ choices, formulas, AI settings, ...)
16
+
17
+ and writes the combined result to:
18
+
19
+ ~/Desktop/softr-database-<databaseId>-<YYYYMMDD-HHMMSS>.json
20
+
21
+ Usage
22
+ -----
23
+ get-softr-database # prompts for DB ID, then API key (hidden)
24
+ get-softr-database <database_id> # prompts only for the API key
25
+ SOFTR_API_KEY=xxx get-softr-database <database_id> # fully non-interactive
26
+
27
+ The API key may also be supplied via the SOFTR_API_KEY environment variable, so
28
+ it never has to be typed (or stored) in plain text.
29
+
30
+ Only the Python standard library is used — no `pip install` required.
31
+ """
32
+
33
+ import os
34
+ import sys
35
+ import json
36
+ import getpass
37
+ import datetime
38
+ import urllib.request
39
+ import urllib.error
40
+
41
+ API_BASE = "https://tables-api.softr.io/api/v1"
42
+ TIMEOUT_SECONDS = 60
43
+
44
+
45
+ def api_get(path, api_key):
46
+ """GET a Softr Tables API path and return the parsed JSON body."""
47
+ req = urllib.request.Request(
48
+ API_BASE + path,
49
+ headers={
50
+ "Softr-Api-Key": api_key,
51
+ "Content-Type": "application/json",
52
+ },
53
+ method="GET",
54
+ )
55
+ try:
56
+ with urllib.request.urlopen(req, timeout=TIMEOUT_SECONDS) as resp:
57
+ return json.loads(resp.read().decode("utf-8"))
58
+ except urllib.error.HTTPError as e:
59
+ body = e.read().decode("utf-8", "replace")
60
+ hint = ""
61
+ if e.code in (401, 403):
62
+ hint = "\n (Check that the API key is correct and has access to this database.)"
63
+ elif e.code == 404:
64
+ hint = "\n (Check that the database ID is correct.)"
65
+ raise SystemExit(f"\n[x] HTTP {e.code} on GET {path}\n {body}{hint}")
66
+ except urllib.error.URLError as e:
67
+ raise SystemExit(f"\n[x] Network error on GET {path}: {e.reason}")
68
+ except json.JSONDecodeError:
69
+ raise SystemExit(f"\n[x] Could not parse JSON response from GET {path}")
70
+
71
+
72
+ def prompt_database_id():
73
+ if len(sys.argv) > 1 and sys.argv[1].strip():
74
+ return sys.argv[1].strip()
75
+ try:
76
+ value = input("Softr database ID: ").strip()
77
+ except (EOFError, KeyboardInterrupt):
78
+ raise SystemExit("\n[x] Cancelled.")
79
+ if not value:
80
+ raise SystemExit("[x] No database ID provided.")
81
+ return value
82
+
83
+
84
+ def prompt_api_key():
85
+ value = os.environ.get("SOFTR_API_KEY", "").strip()
86
+ if value:
87
+ return value
88
+ try:
89
+ value = getpass.getpass("Softr API key (input hidden): ").strip()
90
+ except (EOFError, KeyboardInterrupt):
91
+ raise SystemExit("\n[x] Cancelled.")
92
+ if not value:
93
+ raise SystemExit("[x] No API key provided.")
94
+ return value
95
+
96
+
97
+ def output_dir():
98
+ desktop = os.path.join(os.path.expanduser("~"), "Desktop")
99
+ return desktop if os.path.isdir(desktop) else os.path.expanduser("~")
100
+
101
+
102
+ def main():
103
+ database_id = prompt_database_id()
104
+ api_key = prompt_api_key()
105
+
106
+ print(f"\n-> Fetching database {database_id} ...")
107
+ db = api_get(f"/databases/{database_id}", api_key).get("data", {}) or {}
108
+ print(f" Database: {db.get('name', '(unknown)')} "
109
+ f"({db.get('tablesCount', '?')} tables reported)")
110
+
111
+ print("-> Fetching tables and fields ...")
112
+ tables = api_get(f"/databases/{database_id}/tables", api_key).get("data", []) or []
113
+ total_fields = sum(len(t.get("fields", []) or []) for t in tables)
114
+ print(f" Retrieved {len(tables)} tables, {total_fields} fields total.")
115
+
116
+ now = datetime.datetime.now()
117
+ payload = {
118
+ "exportedAt": now.isoformat(timespec="seconds"),
119
+ "source": API_BASE,
120
+ "databaseId": database_id,
121
+ "database": db,
122
+ "tableCount": len(tables),
123
+ "fieldCount": total_fields,
124
+ "tables": tables,
125
+ }
126
+
127
+ stamp = now.strftime("%Y%m%d-%H%M%S")
128
+ filename = f"softr-database-{database_id}-{stamp}.json"
129
+ path = os.path.join(output_dir(), filename)
130
+
131
+ with open(path, "w", encoding="utf-8") as f:
132
+ json.dump(payload, f, indent=2, ensure_ascii=False)
133
+
134
+ print(f"\n[ok] Saved schema to:\n {path}")
135
+
136
+ # Brief per-table summary so the result is readable at a glance.
137
+ if tables:
138
+ print("\n Tables:")
139
+ for t in tables:
140
+ print(f" - {t.get('name', '(unnamed)')}: "
141
+ f"{len(t.get('fields', []) or [])} fields")
142
+
143
+
144
+ if __name__ == "__main__":
145
+ main()