softr-vibe-coding 1.10.0 → 1.10.1

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,9 @@ 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.10.1] - 2026-06-12
8
+ - Document useFieldOptions companion-useRecords requirement — the hook only populates once an active useRecords in the same block has loaded the table schema; without it options settles to [] with isLoading false (bites write-only/helper blocks hardest). Add the required companion query to the example, correct the return shape to { options, isLoading } with options { id, label, color }, note the cross-table helper-block pattern, and add a prefer-live-fall-back-to-hardcoded recommendation; bump to 1.10.1
9
+
7
10
  ## [1.10.0] - 2026-06-04
8
11
  - Bundle get-airtable-base CLI script for full base metadata export; document in SKILL.md, airtable.md, fields.md
9
12
 
@@ -108,23 +108,43 @@ var options = (result.data && result.data.pages) ? result.data.pages.flatMap(fun
108
108
  Returns the current option list for any `singleSelect` / `multipleSelects` field — without hardcoding option IDs in your block. Useful when the schema's option list changes (renames, additions, reorders) and you don't want to redeploy the block every time.
109
109
 
110
110
  ```jsx
111
- import { useFieldOptions, q } from "@/lib/datasource";
111
+ import { useFieldOptions, useRecords, q } from "@/lib/datasource";
112
+
113
+ var specSelect = q.select({ status: "Status" });
114
+
115
+ // REQUIRED: a companion records query in the SAME block loads the table schema that
116
+ // useFieldOptions reads from. Without it, useFieldOptions settles to `{ options: [] }`
117
+ // (isLoading false, length 0) even though the field has choices. count: 1 is enough.
118
+ useRecords({ select: specSelect, count: 1 });
112
119
 
113
120
  var statusOptions = useFieldOptions({
114
- select: q.select({ status: "Status" }),
121
+ select: specSelect,
115
122
  field: "status", // the ALIAS from q.select(), NOT the raw field ID
116
123
  });
117
124
 
118
- // statusOptions.options[{ id: "sel...", label: "Active" }, { id: "sel...", label: "Inactive" }]
119
- // Each item has `id` (the option's UUID, used in mutate payloads) and `label` (display string).
125
+ // statusOptions → { options: [...], isLoading: bool }
126
+ // statusOptions.options [{ id: "sel...", label: "Active", color: "greenLight1" }, ...]
127
+ // id — the option's UUID, used in mutate payloads
128
+ // label — display string
129
+ // color — Airtable swatch color name (optional; handy for tinting chips)
120
130
  ```
121
131
 
132
+ **⚠️ Gotcha — requires a companion `useRecords` (verified 2026-06-12).** `useFieldOptions`
133
+ only populates once an active `useRecords` in the same block has loaded that table's schema.
134
+ This bites hardest in **write-only / invisible helper blocks** (the natural home for an
135
+ option-publishing helper) because they otherwise never query records — so `options` stays
136
+ `[]` forever with `isLoading: false`, which looks like "the field has no choices." The fix is
137
+ a throwaway `useRecords({ select, count: 1 })` alongside the `useFieldOptions` call(s); the
138
+ same `select` object can be shared by both. Reuse one `select` for many fields and call
139
+ `useFieldOptions` once per field (alias). Symptom to recognise: hook returns
140
+ `{ options: [], isLoading: false }` while the block is correctly bound to the data source.
141
+
122
142
  **When to use this vs. hardcoding:**
123
143
 
124
- - **Use `useFieldOptions`** when option IDs / labels could change post-deploy — selects with rapidly-evolving lists, user-editable choices, or any case where re-pasting blocks for an option rename is annoying.
125
- - **Hardcode** when the option set is stable and frequently referenced (e.g. a status enum that drives a state machine), so the IDs live in source and rename-safety is enforced by greppable constants.
144
+ - **Use `useFieldOptions`** when option IDs / labels could change post-deploy — selects with rapidly-evolving lists, user-editable choices, or any case where re-pasting blocks for an option rename is annoying. Cross-table case: to render a select field from table B inside a block bound to table A (e.g. an intake form bound to Jobs that needs the Wigs `Color` options), put the `useRecords` + `useFieldOptions` in a hidden helper block bound to table B and publish the options to a `window` global (see [helper-blocks.md](../references/helper-blocks.md)).
145
+ - **Hardcode** when the option set is stable and frequently referenced (e.g. a status enum that drives a state machine), so the IDs live in source and rename-safety is enforced by greppable constants. A robust middle ground: prefer the live options, fall back to a hardcoded list per field so the UI still renders if the helper hasn't published yet.
126
146
 
127
- `useFieldOptions` is the read-side equivalent of using `useLinkedRecords` for foreign records — it abstracts away the field's option store. Items are shaped `{ id, label }` (note: `label`, not `title` like `useLinkedRecords`).
147
+ `useFieldOptions` is the read-side equivalent of using `useLinkedRecords` for foreign records — it abstracts away the field's option store. Items are shaped `{ id, label, color }` (note: `label`, not `title` like `useLinkedRecords`).
128
148
 
129
149
  ## Filtering
130
150
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "softr-vibe-coding",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
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"