build-quick-design-calculator
Skill11 starsChanged 33 days agoMITView on GitHub
Use when building, editing or debugging a SkyCiv Quick Design calculator — the config.json / calculate.js / ui.js / docs.md / s3d_integration.js 'calc pack' uploaded to the SkyCiv Build Your Own Calculator builder. Covers the config.json input-form schema (number, dropdown, section, table, canvas, div elements, visible_variables show/hide logic, settings), the calculate.js contract and its server-side globals (REPORT, ReportHelpers, SVGCreator, SectionProps, Database, requireUtil, callQDCalculator, logger, warn, ERROR), the results object and PASS/FAIL utility boxes, report and MathJax formula writing, automatic metric/imperial conversion, SVG graphics in ui.js, and batch S3D integration. Trigger even without the words 'Quick Design' — e.g. 'build my own engineering calculator', 'make a web calculator for this design check', 'my calc pack report won't render', 'add an input to the config', 'my formula prints NaN'. NOT for calling an existing published calculator by UID over REST — that is run-quick-design.
- Installs packages
In this repository17 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- analysis-resultsSkill
- baseplateSkill
- cloudcad-apiSkill
- foundation-apiSkill
- load-combinationsSkill
- load-gen-apiSkill
- qa-engineerSkill
- rendererSkill
- run-quick-designSkill
- s3d-apiSkill
- s3d-appsSkill
- schema-agentSkill
- section-selectorSkill
- skill-writerSkill
- skyciv-api-v3Skill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 207
All write into the global REPORT.
- Very specific: line 324
calculate.jsmust beasync: if you await anything (Database.*, callQDCalculator).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Build a Quick Design Calculator
SkyCiv Quick Design turns a small bundle of files — a calc pack — into a hosted calculation
tool. SkyCiv generates the UI from your config.json, runs calculate.js on its servers, and
handles reporting, units, PDF export, batch runs and (optionally) Structural 3D integration.
Prerequisite / boundary: this skill is for authoring a calculator. The pack is uploaded as a folder at platform.skyciv.com/quick-design?uid=build (Build Your Own Calculator → Upload Code). No API key, session or
{ auth, options, functions }envelope is involved —skyciv-api-v3does not apply. To call an already-published calculator by UID over REST, userun-quick-design.
Calc pack layout
| Path | Purpose |
config.json | Required. Metadata + every input variable; the UI form is generated from it. A minimal pack is just this plus calculate.js. |
calculate.js | Required. Server-side logic: takes the input JSON, writes the report, returns { report, results }. |
ui.js | Client-side; draws into the canvas/div elements declared in the config. |
docs.md | Documentation tab — overview, assumptions, changelog. |
s3d_integration.js | Puts the calculator in Structural 3D, batch-running over model members. |
renderer.js | Adds a SkyCiv 3D Renderer panel. |
utils/*.js | Shared modules via requireUtil('name.js'). Must use module.exports. |
json/*.json, csv/*.csv | Lookup data via requireJSON() / requireCSV(). |
images/* | Served from the pack; reference as /name.png. |
metric/ or imperial/ | Manual dual-unit packs only — see Units. |
test_files/Test N/ | Builder regression tests: input.json + expected_return.json. |
unit_tests/**/*.test.js | Local Jest tests over utils/; not uploaded. |
Build workflow
- Nail the inputs first. Each
input_variableskey is both a form field and a destructured variable incalculate.js— that key is the contract between the two files. If a required engineering input is missing (site data, design code, material grade), ask rather than inventing a default. - Write
calculate.js— destructure, compute, report as you go, return{ report, results }. Then addui.js,docs.md, andtest_files/Test N/pairs plus Jest tests overutils/. - Upload and run as a Draft, reading the log panel for
logger()output. Adds3d_integration.jslast, if it should batch-run over an S3D model.
config.json
{ "meta": { }, "input_variables": { }, "settings": { } }meta
Required: name, short_description, long_description, tags (comma-separated), access
("public" / "private" — keep private until published), and contact (only its email is
mandatory; also takes name, role, company, logo, custom_header_html). Optional:
default_unit_system ("metric" / "imperial", enables automatic conversion — see
Units) and s3d_integrated. The templates also carry category: "analysis", which isn't
in the published meta table — safe to include, don't rely on it.
settings (optional, top level)
Report-level switches — report_heading, include_input_table, split_input_table_by_headings,
include_summary_table, include_marketing, disable_batch_run, beta_calculation,
show_analysis_loader, and skip_rounding (turn on while QA'ing, so values match a hand calc).
Full list in quick-design-config.md.
input_variables elements
Order in the JSON = order on the form. Each key is the variable name passed to calculate.js.
type | Notes |
number | units, symbol (MathJax), default, min, max, step, integer, nullable, class. |
text, checkbox | default. |
dropdown, radio | options: [{ name, value, selected }]; dropdown also multiple, nullable. |
section | Section-library dropdown: country, library, shape (string or array), shape_label_append, custom_option, default. |
s3d_section | S3D only — passes the model's section object through. |
table | Spreadsheet popup: table.columns[] with cell_type input_text/dropdown/checkbox, plus min_rows, max_rows, default_data, pagination. |
button | Needs an id to bind to in ui.js. |
heading, subheading | collapsed: true starts folded. |
image | src (URL or /name.png), width, qd_center. |
canvas, div | Empty graphic target with an id; div + qd_center: true is the usual choice for SVG. |
message_banner | Banner you write into from ui.js. |
Modifier keys on any input: hidden, hidden_all, disabled, s3d_only, hide_in_s3d,
disable_in_s3d, exclude_from_input_table, highlight_row, hide_units_label, batch_skip,
display_units, label_table, info_table, and combine_with (+ combined_label,
combined_tooltip) to pair two fields on one row. Validation against another input: greater_than,
less_than, greater_than_or_equal, less_than_or_equal, equal_to.
Show/hide logic
visible_variables on a dropdown, checkbox or radio drives the rest of the form. Keys are the
option value; for checkboxes they are literally checked / unchecked.
"calculate_deflection": {
"type": "checkbox", "label": "Calculate Deflection", "default": false,
"visible_variables": {
"checked": [["show", "E"], ["show", "I_z"]],
"unchecked": [["hide", "E"], ["hide", "I_z"]]
}
}Targets: "all", an input key, or a CSS class (".circular-input", matching an input's class).
Minimal complete config
{
"meta": {
"name": "Simply Supported Beam", "short_description": "UDL beam actions.",
"long_description": "Peak reaction and moment for a UDL on a simple span.",
"tags": "beam, analysis", "access": "private", "default_unit_system": "metric",
"contact": { "name": "SkyCiv", "email": "support@skyciv.com" }
},
"input_variables": {
"ui_div": { "type": "div", "id": "ui-div", "qd_center": true },
"geometry": { "type": "heading", "label": "Geometry" },
"L": { "type": "number", "label": "Span", "symbol": "L", "units": "m", "default": 6 },
"w": { "type": "number", "label": "UDL", "symbol": "w", "units": "kN/m", "default": 2 }
}
}calculate.js
The matching logic file — destructure the same keys, compute, report, return:
module.exports = async function (input_json) { // async only if you await
let { L, w } = input_json; // keys come from input_variables
ReportHelpers.printInputSummary();
const M = ReportHelpers.formula({
formula: "M = w * Math.pow(L, 2) / 8",
variables: { w, L: { value: L, unit: "m" } },
units: "kN-m", dec_places: 2, intermediate_result: true, reference: "Statics"
});
return {
report: REPORT,
results: {
actions: { label: "Design Actions", units: "heading" },
M: { label: "Peak Moment", value: M, units: "kN-m" },
ur: { label: "Bending Utility", value: M / 120, units: "utility" }
}
};
};input_json also carries a platform-injected project_details object (company, name, designer,
id, client, notes) — ignore it unless the report needs it.
Server-side globals
| Global | Use |
REPORT | REPORT.block.new(title, size) / .addCalculation() / .addResult() / .finish(), REPORT.section.break(). |
ReportHelpers | High-level report writing — see Reporting. |
PrettyPrint.pretty_print | .print(), .prettyResults(value, units, sig_figs), .numberWithCommas(). |
SVGCreator | Build an SVG string and print it into the report. |
SectionProps | ISectionProperties(d, b, t_f, t_w, r, region) etc → A, Cy/Cz, I, Z, S, J, Iw, shear areas. region: AS (default), EN, US, CA. |
Database | await Database.getSection(JSON.stringify([country, library, shape, name]), unit_system), .getShapesList(), await Database.getMaterial([...]). |
config_json | Your own config, e.g. config_json['L']['units']. |
requireJSON / requireUtil / requireCSV | Load from json/, utils/, csv/; nested paths work. Parse CSV with CSV.csvToJSON() / CSV.csvToNestedJSON(). |
callQDCalculator | await callQDCalculator(uid, input_obj) — chain another published calculator. |
state | Shared mutable object, readable/writable from any utils/ module. |
logger / logVariables | logger("E = " + E), logVariables({shape, alloy, Mz}) → builder log panel. |
warn / ERROR | warn(msg, add_block_to_report, reference); return ERROR(msg, title) to fail cleanly. |
Output object
{ report: REPORT, results: {...} }, optionally plus s3d_model (offers an "open in S3D" link),
summary_report_settings, and settings (note_style, show_log, show_feedback). Each result
accepts label, value, units, results_label, info, note, hidden, paid_only,
standout, round, integer, hide_in_s3d, s3d_symbol/s3d_info, batch_symbol/batch_info.
Special units values change the rendering:
units | Renders as |
"utility" | PASS/FAIL box: < 0.95 green PASS, 0.95–1.0 orange WARN, >= 1 red FAIL. |
"utility_status" | The value with an adjacent PASS/FAIL tag. |
"utility_boolean" | PASS when value = 1, FAIL when 0. No warn state. |
"heading" | Group heading in the results panel (label only, no value). |
"custom_box" | Free text — add "color": "#289DCC"; "warning_box" is the pre-styled variant. |
"error", "price", "price_euro" | Error box; currency values. |
Brand colors: red #DB2828, green #21BA45, orange #F2711C.
Reporting
All write into the global REPORT. Signatures and screenshots: quick-design-reporting.md.
- Structure —
heading(text, size, ref),pageBreak(),subBreak(),padding(), andcustomFullBlock({ title, content })(buildcontentfrom the*HTML()variants). - Maths —
formula({ formula, variables, units, dec_places, intermediate_result, reference, compact, print_result_as_utility, expected_result })is the workhorse: it evaluates the expression, prints equation → substitution → result, and returns the number.printMathjax(expr, left, right)covers whatformula()can't (braces,min/max,\\sqrt).round(value, dp)is NaN-safe and returns a number.convert(value, from, to)converts units. - Text and results —
print(left, body, right)(HTML,[math]…[math],**bold**),lineResult(label, symbol, value, ref, result),printStatus(ratio, use_existing_block)/printCustomStatus(text, use_block, color)for PASS/FAIL chips,messageBox(),list(). - Data and graphics —
quickTable(rows, options)withmerge_left/merge_up,widths,text_aligns,cell_backgrounds(+tableColorCritical()/tableColorUtility());drawGraph({...})for SFD/BMD-style plots (nested sub-array = step change);image({ src }). - Summary report —
addKeyImage()andaddIntermediateResults(), configured viasummary_report_settingsin the output object.
Units
Automatic (preferred). Set meta.default_unit_system to "metric" or "imperial". The platform
converts inputs, results and report units — including mm^2 / mm^3 superscripts — and
calculate.js always receives the declared base system. Per-input overrides: convert_to,
converted_default, converted_step. Use these exact unit strings, or conversion silently fails:
| Quantity | Metric | Imperial |
| Length | mm, cm, m | in, in, ft |
| Force | kN | kip |
| Moment | kN-m | kip-ft |
| Stress / pressure | Pa, kPa, MPa | psi, psi, ksi |
Manual. Omit default_unit_system and add a metric/ or imperial/ folder with its own
config.json + calculate.js; json/ and utils/ are shared, ui.js/docs.md/renderer.js may
be either. Only worth it when the two systems need different logic or reporting.
ui.js — live graphics and dynamic form control
Re-run client-side on every input change. Two equivalent ways to read the form, both current:
var input = SKYCIV_DESIGN.generateInput(true); // converted to the base unit system
var labels = SKYCIV_DESIGN.generateInput(false); // raw, as displayed — for dimension text
// equivalent, and what the shipped templates use:
// var input = SKYCIV_DESIGN.designConfig.getInput();For dual-unit calculators compute from the converted values, label with the displayed ones, and
branch on SKYCIV_DESIGN.units.getCurrentUnitSystem() == 'imperial'.
Draw with SVGCreator into a div whose id matches the config: initialize({ total_height,
total_width, center }) → addRect/addLine/addCircle/addText/dimLineDrawer → endSVG() →
getSVGHtml() into innerHTML. Size everything off jQuery('#ui-div').width() so it scales;
assets/example-project/ui.js is a complete worked load diagram to copy. For loads, bolts, axes,
concrete sections and steel profiles, see the SVG and section docs in the reference table.
SKYCIV_DESIGN.ui.helpers.* drives the form — setInputValues(obj), showInput/hideInput/
setInputDisabled, updateDropdownValues, updateMin/updateMax/updateStep, updateLabel/
updateTooltip/updateImage, table column/cell enable-disable, async getSection/getMaterial/
getSectionTree/getMaterialTree, and wasInputChanged(key) so you redraw only what changed.
Full list: quick-design-ui-helpers.md.
s3d_integration.js — batch-run over a Structural 3D model
module.exports = function (s3d_model, analysis_results) { ... } returns an array of input
objects, one per member, each run through calculate.js. Throw if !analysis_results or no
members qualify. Iterate s3d_model.elements (UI format) and convert every value from
s3d_model.settings.units. A complete integration is three pieces: this file, a hidden
analysis_results custom_object input plus hide_in_s3d on the manual loads in config.json,
and a calculate.js that prefers analysis_results over the manual loads. Load
references/s3d-integration.md before writing any of it. It covers helpers, units, load-combination
choice, sign conventions, section shapes, testing and a checklist. Its official counterpart,
quick-design-s3d.md, has an outdated example.
Testing
Platform regression tests — test_files/Test 1/, Test 2/, … each holding input.json (a full
input JSON as the calculator receives it, including project_details) and expected_return.json
(the expected results object). The builder replays these against the pack. Add a case per branch —
each dropdown option, each visible_variables path — and regenerate expectations whenever the
results object changes.
Jest unit tests — move the maths into utils/*.js with module.exports, then
npm install --save-dev jest, add "test": "jest" to package.json, and write *.test.js under
unit_tests/. Cover boundaries, sign changes, division by zero and very large/small inputs.
Passing tests prove the code, not the engineering.
Gotchas
^is XOR in JavaScript, not a power operator. It silently produces garbage both inReportHelpers.formula()strings and in plain JS. UseMath.pow(x, n)(or**outsideformula()).- Never
throw new Errorincalculate.js—return ERROR(msg, title)instead. The opposite applies ins3d_integration.js, wherethrow new Error(...)is how you report an unsolved model or no eligible members. ReportHelpers.formula()can't handle{}and must not be wrapped in[math][math]tags; either stops it evaluating. UseprintMathjax()orREPORT.block.addCalculation().- Escape backslashes in MathJax strings —
'\\frac{a}{b}', not'\frac{a}{b}'. QD's MathJax renders/as\\, so followquick-design-reporting.md, not upstream MathJax docs. ui.jsmust usevarat top level —let/constthrow console errors because the file is re-executed on every input change. They're fine inside functions.- Rebind buttons defensively —
jQuery("#reset").unbind("click").click(...), or handlers stack up. - Setting a dropdown from
ui.jsre-triggersui.js— setwindow.SKIP_UI_UPDATE = truearound the update, or it loops. s3d_integration.jsuses the UI model format —s3d_model.elements, nots3d_model.members. The most common integration bug.- Unit strings are matched literally —
"kN-m"converts,"kNm"/"kn-m"/"kN.m"do not. Same formm^4-style superscripts. calculate.jsmust beasyncif youawaitanything (Database.*,callQDCalculator). Forgetting yieldsundefined/[object Promise]results rather than an error.- A
canvas/dividinconfig.jsonmust matchgetElementByIdinui.js, and must exist ininput_variables, or the graphic never appears. calculate.jsruns on SkyCiv's servers — no browser console.logger()andlogVariables({...})write to the builder's log panel; use them liberally.assets/example-project/sample outputs are off by 1000 onPeak_Moment(9000 vs 9 kN-m for w = 2 kN/m, L = 6 m) and label momentskNm, notkN-m. Use it as a structural template only.
Reference documentation
Bundled under assets/documentation/. Load one only when you reach that step.
| Load when… | File (assets/documentation/… unless references/) |
Any config.json field | quick-design-config.md |
calculate.js — output object, PrettyPrint, errors, logging | quick-design-calculate.md |
| Report formatting — blocks, formulas, tables, graphs, status, summary | quick-design-reporting.md |
| Metric/imperial or a dual-unit pack | quick-design-units.md |
ui.js, or driving the form from it | quick-design-ui.md, quick-design-ui-helpers.md |
| SVG — basics, then loads/bolts/axes/concrete sections | quick-design-svg.md, quick-design-svg-extended.md |
| A steel section profile, or properties of a custom shape | quick-design-sections.md, quick-design-section-props.md |
| Sections or materials from the SkyCiv database | quick-design-sb-integration.md |
Structural 3D integration (s3d_integration.js) | references/s3d-integration.md first, then quick-design-s3d.md for helper output shapes |
| The 3D renderer | quick-design-renderer.md |
requireUtil / requireJSON / requireCSV | quick-design-advanced.md |
| Chaining a published calculator, or batch-run columns | quick-design-integrating-qds.md, quick-design-batch.md |
| Jest unit tests, or a chart | quick-design-unit-testing.md, quick-design-chartjs.md, quick-design-plotlyjs.md |
| The overall file map or publishing info | quick-design.md |
Starter code: assets/project-template/ (skeleton) and assets/example-project/ (complete beam
calculator with test_files/ examples).
Cross-links
run-quick-design— call a published calculator by UID over REST.s3d-api—s3d_modelschema, fors3d_integration.jsand for returnings3d_model.analysis-results— theanalysis_resultsobject's shape.section-selector—country/library/shapefor asectioninput.renderer— the viewer used byrenderer.js.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

