SurveyJS Skill
You are helping the user with SurveyJS — the JavaScript library that renders forms (called "surveys") from JSON schemas in Angular and React, plus its visual designer (Survey Creator), and its server-side use under Microsoft.ClearScript V8 in .NET.
Pinned versions (do not deviate)
- survey-core:
2.5.20 (UMD bundle typically vendored at <dotnet-project>/JavaScript/survey.core.min.js as an embedded resource)
- survey-react-ui: pair with
2.5.20
- survey-angular-ui: pair with
2.5.20 (peer dep @angular/cdk@^12.0.0, Angular ≥ 12)
- survey-creator-core / -react / -angular: pair with
2.5.20 (commercial license)
If the user is on a newer line and asks about a v3.0 feature (UI Preset Editor, Tailwind/Bootstrap adapters, expression-syntax customization), say so explicitly and offer the closest 2.5.20 equivalent. Don't silently emit code that requires v3.
Reference implementation (keystone context)
This skill assumes the project contains a .NET module (commonly an ABP module) that hosts survey-core inside Microsoft.ClearScript V8 with a sync, JSON-string-in/JSON-string-out bridge. Every server-side SurveyJS task must extend that baseline, not invent a new one.
The module's path varies per checkout — find it by searching for these filenames in the working tree (or ask the user):
V8EnginePool.cs — ConcurrentBag<V8ScriptEngine> pool, flag V8ScriptEngineFlags.DisableGlobalMembers, loads embedded resources in order: survey.core.min.js then surveyjs-validation.js.
JavaScript/surveyjs-validation.js — the JS glue file. The starting point typically exposes only validateSchema(schemaJson) (structural check: page/element non-emptiness). All new server-side capabilities go here, as additional sync functions following the same JSON-string sandwich.
JavaScript/survey.core.min.js — the vendored UMD bundle (target version: 2.5.20).
Entities/FormDefinitions/FormDefinitionManager.cs (or analogous host-side wrapper) — calls engine.Invoke("<glueFn>", argJsonString), deserializes the returned JSON string with System.Text.Json. On failure, throw the project's domain exception (typically an ABP BusinessException with a code like FormErrorCodes.InvalidSchema).
Tests/SurveyJs/SurveyJsValidationManager_Tests.cs — pattern-establishing test, including a 10-task Task.WhenAll concurrent-validation case that proves pool safety.
Read those files when in doubt — they are the contract. When generating new C# host methods or new JS glue functions, mirror this style. If you can't find the module in the working tree, ask the user where it lives or whether to scaffold a new one.
How to route
Identify which domain the user is in and read the matching reference file before drafting code. Do this even if the user's framing is fuzzy — the references contain version-specific detail (deprecated names, exact event payloads, exact value shapes) that you cannot reliably reconstruct from training data alone.
| Domain |
When |
Read |
| Form Library — React |
Embedding <Survey/> in a React app |
references/form-library-react.md |
| Form Library — Angular |
Embedding <survey> in an Angular app |
references/form-library-angular.md |
| Survey Creator (designer) |
Embedding the WYSIWYG builder, customizing toolbox / property grid / tabs / save hooks |
references/creator.md |
| Theming Survey Creator |
Customizing the creator chrome colors / spacing / typography to match a host app (shadcn, Material, custom design system) |
references/creator-theming.md |
| Survey JSON schema |
Authoring or hand-editing survey JSON (questions, pages, panels, validators, triggers, calculatedValues) |
references/schema.md |
| Survey CORE API |
SurveyModel / Question / Serializer / FunctionFactory / settings — anything that's pure model logic |
references/api.md |
| Server-side / V8 ClearScript |
Validating schemas or data on the .NET host, extending surveyjs-validation.js |
references/server-side.md |
| Custom properties / question types |
Serializer.addProperty, ComponentCollection.Instance.add, FunctionFactory.Instance.register |
references/extension.md |
For any task that touches the project's V8 ClearScript validator module (the one that owns V8EnginePool.cs and surveyjs-validation.js), also read references/server-side.md regardless of framing. Bridge-contract alignment is non-negotiable.
Output contract for code generation
When generating SurveyJS code:
- State the framework and package version at the top of the snippet (
// React + survey-react-ui 2.5.20).
- For React surveys: always memoize the model with
useMemo or useState(() => new Model(json)). Recreating it on every render leaks subscriptions and resets user input.
- For Angular surveys: import
SurveyModule from survey-angular-ui; CSS comes from survey-core/survey-core.min.css. Both NgModule and standalone-component setups work — pick based on the user's app.
- For schemas: validate against the canonical JSON Schema at
https://unpkg.com/survey-core@2.5.20/surveyjs_definition.json. Don't invent property names — confirm via references/schema.md or references/api.md.
- For server-side glue: every new function in
surveyjs-validation.js must be sync, accept JSON strings only, return JSON.stringify({ok|isValid, errors, ...}), wrap in try/catch, and not depend on any host object beyond what Survey.* provides. See references/server-side.md for the canonical template.
- For Survey Creator theming: never customize via plain CSS class selectors targeting the v2 (
--sjs2-*) token catalog — they lose to the inline styles syncTheme(DefaultLight) injects during construction. Use creator.applyCreatorTheme(theme) with an ICreatorTheme whose cssVariables keys are v2 (--sjs2-*) tokens, applied before assigning creator.JSON. Legacy (--sjs-*) and component (--ctr-*) tokens are a separate story — those do respond to scoped plain CSS because they aren't inline-injected. See references/creator-theming.md for the full picture.
Anti-patterns to refuse (server-side specifically)
These break the V8 ClearScript bridge contract. If the user asks for them server-side, push back and offer the sync alternative from references/server-side.md.
onServerValidateQuestions — its callback model needs an event-loop pump that ClearScript's sync bridge does not provide. Use a sync SurveyValidator subclass or sync FunctionFactory.Instance.register(name, fn, /*isAsync*/ false) instead.
choicesByUrl / choicesLazyLoad — these issue XMLHttpRequest/fetch at runtime; both are unguarded in the bundle (will throw ReferenceError). Either pre-resolve choices on the .NET side and inject them, or run the stripChoicesByUrl(schemaJson) preprocessor before new Survey.Model(schema).
- Async
FunctionFactory entries — FunctionFactory.Instance.register(name, fn, /*isAsync*/ true) returns via this.returnResult(value), which never resolves under ClearScript. Convert async rules to sync by prefetching dependencies into dataJson before calling the glue.
survey.startTimer() — uses setInterval. SurveyTimer's interval calls are inside start()/stop(), not at module load, so the bundle imports cleanly — but never call startTimer server-side.
onAfterRender* events / popup / focus / scroll APIs — DOM-only, will throw.
storeDataAsText: false for file questions — the .NET host can't resolve the URL identifier from a file question; either accept the data-URL form or pre-resolve.
survey.data = X on a partial host payload — wholesale replace, drops defaults. Use survey.mergeData(patch) instead.
Conditional logic keys reference (cite from memory only when confident)
These keys exist in 2.5.20 (confirmed by grep on the bundle). defaultValueIf and valueExpression do NOT exist in 2.5.20 — they are future/proposed.
- Boolean (ConditionRunner):
visibleIf, enableIf, requiredIf, setValueIf, resetValueIf, choicesVisibleIf, choicesEnableIf, rowsVisibleIf, columnsVisibleIf
- Value-producing (ExpressionRunner):
defaultValueExpression, setValueExpression, runExpression, totalExpression, expression
- Survey-level:
navigateToUrlOnCondition, completedHtmlOnCondition, triggers[].expression, calculatedValues[].expression, bindings
Built-in question types (21 total)
boolean, checkbox, comment, dropdown, tagbox, expression, file, html, image, imagepicker, matrix, matrixdropdown, matrixdynamic, multipletext, panel, paneldynamic, radiogroup, rating, ranking, signaturepad, text. All 21 are model-load DOM-clean in 2.5.20 (validators, expressions, value shapes all run server-side under V8). At render time, signaturepad needs canvas and file needs File/FileReader — neither blocks headless validation.
Value shapes and per-type config detail: see references/schema.md.
Built-in validators
numeric, text, email, regex, expression, answercount. Each validator's JSON shape, options, and validate(value, owner) signature are in references/api.md. notificationType (error|warning|info) added in 2.3.8 and present in 2.5.20 — warning/info don't block submission.
When you finish a task
If you generated server-side glue, remind the user that:
- The new function must be added to the
surveyjs-validation.js glue file in the project's V8 ClearScript module.
- A C# wrapper in the form-domain manager should rent an engine,
Invoke the function, deserialize the JSON string, and return the engine to the pool.
- The integration tests should grow a 10-task concurrent test for the new function, mirroring the existing concurrent-validation case.
- The engine pool already loads survey-core once per engine — no rebuild needed.
If the project does not yet contain a V8 ClearScript module of this shape, surface that explicitly and ask whether to scaffold a new one or stop.
Source: mssalkhalifah/agent-skills — distributed by TomeVault.
1---2name: surveyjs3description: Use this skill whenever the user works with SurveyJS — the JSON-driven form/survey library. Trigger on mentions of SurveyJS, Survey Creator, survey-core, survey-react-ui, survey-angular-ui, survey-creator-* packages, `new Survey.Model`, or survey JSON schemas. Also trigger when authoring or debugging survey JSON (questions, calculatedValues, triggers, visibleIf/enableIf/requiredIf, choicesByUrl, paneldynamic, matrix), customizing Survey Creator (toolbox, property grid, tabs, save hooks), registering custom types or functions via Serializer/ComponentCollection/FunctionFactory, or running survey-core server-side under Microsoft.ClearScript V8 in .NET (schema/data validation, extending surveyjs-validation.js, XMLHttpRequest errors from the bundle). Trigger even on plain-language framings ("multi-page form", "form designer", "calculated field") when SurveyJS or its packages are named. Do NOT trigger for generic form libs (react-hook-form, ajv), other survey vendors (SurveyMonkey, Typeform), or unrelated UI.4---56# SurveyJS Skill78You are helping the user with **SurveyJS** — the JavaScript library that renders forms (called "surveys") from JSON schemas in Angular and React, plus its visual designer (Survey Creator), and its server-side use under Microsoft.ClearScript V8 in .NET.910## Pinned versions (do not deviate)1112- **survey-core**: `2.5.20` (UMD bundle typically vendored at `<dotnet-project>/JavaScript/survey.core.min.js` as an embedded resource)13- **survey-react-ui**: pair with `2.5.20`14- **survey-angular-ui**: pair with `2.5.20` (peer dep `@angular/cdk@^12.0.0`, Angular ≥ 12)15- **survey-creator-core / -react / -angular**: pair with `2.5.20` (commercial license)1617If the user is on a newer line and asks about a v3.0 feature (UI Preset Editor, Tailwind/Bootstrap adapters, expression-syntax customization), say so explicitly and offer the closest 2.5.20 equivalent. Don't silently emit code that requires v3.1819## Reference implementation (keystone context)2021This skill assumes the project contains a .NET module (commonly an ABP module) that hosts `survey-core` inside Microsoft.ClearScript V8 with a sync, JSON-string-in/JSON-string-out bridge. **Every server-side SurveyJS task must extend that baseline, not invent a new one.**2223The module's path varies per checkout — find it by searching for these filenames in the working tree (or ask the user):2425- `V8EnginePool.cs` — `ConcurrentBag<V8ScriptEngine>` pool, flag `V8ScriptEngineFlags.DisableGlobalMembers`, loads embedded resources in order: `survey.core.min.js` then `surveyjs-validation.js`.26- `JavaScript/surveyjs-validation.js` — the JS glue file. The starting point typically exposes only `validateSchema(schemaJson)` (structural check: page/element non-emptiness). All new server-side capabilities go here, as additional sync functions following the same JSON-string sandwich.27- `JavaScript/survey.core.min.js` — the vendored UMD bundle (target version: 2.5.20).28- `Entities/FormDefinitions/FormDefinitionManager.cs` (or analogous host-side wrapper) — calls `engine.Invoke("<glueFn>", argJsonString)`, deserializes the returned JSON string with `System.Text.Json`. On failure, throw the project's domain exception (typically an ABP `BusinessException` with a code like `FormErrorCodes.InvalidSchema`).29- `Tests/SurveyJs/SurveyJsValidationManager_Tests.cs` — pattern-establishing test, including a 10-task `Task.WhenAll` concurrent-validation case that proves pool safety.3031Read those files when in doubt — they are the contract. When generating new C# host methods or new JS glue functions, mirror this style. If you can't find the module in the working tree, ask the user where it lives or whether to scaffold a new one.3233## How to route3435Identify which domain the user is in and read the matching reference file before drafting code. Do this even if the user's framing is fuzzy — the references contain version-specific detail (deprecated names, exact event payloads, exact value shapes) that you cannot reliably reconstruct from training data alone.3637| Domain | When | Read |38|---|---|---|39| **Form Library — React** | Embedding `<Survey/>` in a React app | `references/form-library-react.md` |40| **Form Library — Angular** | Embedding `<survey>` in an Angular app | `references/form-library-angular.md` |41| **Survey Creator (designer)** | Embedding the WYSIWYG builder, customizing toolbox / property grid / tabs / save hooks | `references/creator.md` |42| **Theming Survey Creator** | Customizing the creator chrome colors / spacing / typography to match a host app (shadcn, Material, custom design system) | `references/creator-theming.md` |43| **Survey JSON schema** | Authoring or hand-editing survey JSON (questions, pages, panels, validators, triggers, calculatedValues) | `references/schema.md` |44| **Survey CORE API** | SurveyModel / Question / Serializer / FunctionFactory / settings — anything that's pure model logic | `references/api.md` |45| **Server-side / V8 ClearScript** | Validating schemas or data on the .NET host, extending `surveyjs-validation.js` | `references/server-side.md` |46| **Custom properties / question types** | `Serializer.addProperty`, `ComponentCollection.Instance.add`, `FunctionFactory.Instance.register` | `references/extension.md` |4748For any task that touches the project's V8 ClearScript validator module (the one that owns `V8EnginePool.cs` and `surveyjs-validation.js`), also read `references/server-side.md` regardless of framing. Bridge-contract alignment is non-negotiable.4950## Output contract for code generation5152When generating SurveyJS code:53541. **State the framework and package version** at the top of the snippet (`// React + survey-react-ui 2.5.20`).552. **For React surveys**: always memoize the model with `useMemo` or `useState(() => new Model(json))`. Recreating it on every render leaks subscriptions and resets user input.563. **For Angular surveys**: import `SurveyModule` from `survey-angular-ui`; CSS comes from `survey-core/survey-core.min.css`. Both NgModule and standalone-component setups work — pick based on the user's app.574. **For schemas**: validate against the canonical JSON Schema at `https://unpkg.com/survey-core@2.5.20/surveyjs_definition.json`. Don't invent property names — confirm via `references/schema.md` or `references/api.md`.585. **For server-side glue**: every new function in `surveyjs-validation.js` must be sync, accept JSON strings only, return `JSON.stringify({ok|isValid, errors, ...})`, wrap in `try/catch`, and not depend on any host object beyond what `Survey.*` provides. See `references/server-side.md` for the canonical template.596. **For Survey Creator theming**: never customize via plain CSS class selectors targeting the v2 (`--sjs2-*`) token catalog — they lose to the inline styles `syncTheme(DefaultLight)` injects during construction. Use `creator.applyCreatorTheme(theme)` with an `ICreatorTheme` whose `cssVariables` keys are v2 (`--sjs2-*`) tokens, applied **before** assigning `creator.JSON`. Legacy (`--sjs-*`) and component (`--ctr-*`) tokens are a separate story — those *do* respond to scoped plain CSS because they aren't inline-injected. See `references/creator-theming.md` for the full picture.6061## Anti-patterns to refuse (server-side specifically)6263These break the V8 ClearScript bridge contract. If the user asks for them server-side, push back and offer the sync alternative from `references/server-side.md`.6465- **`onServerValidateQuestions`** — its callback model needs an event-loop pump that ClearScript's sync bridge does not provide. Use a sync `SurveyValidator` subclass or sync `FunctionFactory.Instance.register(name, fn, /*isAsync*/ false)` instead.66- **`choicesByUrl` / `choicesLazyLoad`** — these issue `XMLHttpRequest`/`fetch` at runtime; both are unguarded in the bundle (will throw `ReferenceError`). Either pre-resolve choices on the .NET side and inject them, or run the `stripChoicesByUrl(schemaJson)` preprocessor before `new Survey.Model(schema)`.67- **Async `FunctionFactory` entries** — `FunctionFactory.Instance.register(name, fn, /*isAsync*/ true)` returns via `this.returnResult(value)`, which never resolves under ClearScript. Convert async rules to sync by prefetching dependencies into `dataJson` before calling the glue.68- **`survey.startTimer()`** — uses `setInterval`. SurveyTimer's interval calls are inside `start()`/`stop()`, not at module load, so the bundle imports cleanly — but never call `startTimer` server-side.69- **`onAfterRender*` events / popup / focus / scroll APIs** — DOM-only, will throw.70- **`storeDataAsText: false` for `file` questions** — the .NET host can't resolve the URL identifier from a file question; either accept the data-URL form or pre-resolve.71- **`survey.data = X` on a partial host payload** — wholesale replace, drops defaults. Use `survey.mergeData(patch)` instead.7273## Conditional logic keys reference (cite from memory only when confident)7475These keys exist in 2.5.20 (confirmed by grep on the bundle). **`defaultValueIf` and `valueExpression` do NOT exist** in 2.5.20 — they are future/proposed.7677- Boolean (ConditionRunner): `visibleIf`, `enableIf`, `requiredIf`, `setValueIf`, `resetValueIf`, `choicesVisibleIf`, `choicesEnableIf`, `rowsVisibleIf`, `columnsVisibleIf`78- Value-producing (ExpressionRunner): `defaultValueExpression`, `setValueExpression`, `runExpression`, `totalExpression`, `expression`79- Survey-level: `navigateToUrlOnCondition`, `completedHtmlOnCondition`, `triggers[].expression`, `calculatedValues[].expression`, `bindings`8081## Built-in question types (21 total)8283`boolean`, `checkbox`, `comment`, `dropdown`, `tagbox`, `expression`, `file`, `html`, `image`, `imagepicker`, `matrix`, `matrixdropdown`, `matrixdynamic`, `multipletext`, `panel`, `paneldynamic`, `radiogroup`, `rating`, `ranking`, `signaturepad`, `text`. **All 21 are model-load DOM-clean** in 2.5.20 (validators, expressions, value shapes all run server-side under V8). At render time, `signaturepad` needs canvas and `file` needs File/FileReader — neither blocks headless validation.8485Value shapes and per-type config detail: see `references/schema.md`.8687## Built-in validators8889`numeric`, `text`, `email`, `regex`, `expression`, `answercount`. Each validator's JSON shape, options, and `validate(value, owner)` signature are in `references/api.md`. `notificationType` (`error`|`warning`|`info`) added in 2.3.8 and present in 2.5.20 — `warning`/`info` don't block submission.9091## When you finish a task9293If you generated server-side glue, remind the user that:94951. The new function must be added to the `surveyjs-validation.js` glue file in the project's V8 ClearScript module.962. A C# wrapper in the form-domain manager should rent an engine, `Invoke` the function, deserialize the JSON string, and return the engine to the pool.973. The integration tests should grow a 10-task concurrent test for the new function, mirroring the existing concurrent-validation case.984. The engine pool already loads survey-core once per engine — no rebuild needed.99100If the project does not yet contain a V8 ClearScript module of this shape, surface that explicitly and ask whether to scaffold a new one or stop.101102---103> Source: [mssalkhalifah/agent-skills](https://github.com/mssalkhalifah/agent-skills) — distributed by [TomeVault](https://tomevault.io).104<!-- tomevault:4.0:skill_md:2026-06-15 -->