Skip to content

Conventions Registry

Language: JavaScript

A lookup table of settled micro-conventions. One row per settled question, with the answer, evidence, and date settled. A module author scans it in under a minute before inventing a new answer to a solved problem.

Component Tiers

#QuestionSettled answerEvidence
1What tiers does the component library use?Four tiers: atom/, molecule/, composite/, provider/. Atoms compose nothing. Molecules compose atoms only. Composites compose atoms, molecules, and other composites. Providers are context-only, render no visual outputdocs/languages/js/client/components.md - Component Vocabulary
2Where do providers register?Component.provider.[name], matching Component.variant and Component.freeform namespacing. Providers do not count toward the flat top-level key countdocs/languages/js/client/components.md - Provider Set
3What is the exception model?Four buckets: canonical (atom/molecule/composite), provider, structured variant, unstructured freeformdocs/languages/js/client/components.md - Four-Bucket Exception Model

Accessibility

#QuestionSettled answerEvidence
4How are state and value semantics expressed?Through aria-* props, never accessibilityState or accessibilityValue, which React Native Web does not forward to the DOM. accessibilityRole and accessibilityLabel remain correct and are used directlydocs/languages/js/client/components.md - Accessibility Contract
5Where are aria-* props emitted?Through the a11y translator module (a11y.state(), a11y.value(), a11y.relation(), a11y.position()). It is the only module in the package allowed to emit accessibility state/value/relation/position propscomponent/a11y.js
6What about the deprecated no-op props on web?accessibilityHint, accessibilityElementsHidden, importantForAccessibility, accessibilityViewIsModal, AccessibilityInfo.announceForAccessibility, LayoutAnimation are all no-ops on web. Use the aria-* equivalent insteaddocs/languages/js/client/components.md - No-op props on web

Naming

#QuestionSettled answerEvidence
7Carbon Switch vs React Native SwitchCarbon's becomes ContentSwitcherItem. React Native's on/off toggle concept becomes ToggleSettled in the component library's own docs
8Carbon ProgressIndicator vs ProgressBarCarbon's multi-step stepper becomes ProgressSteps. The determinate bar becomes ProgressBarSettled in the component library's own docs
9Build a Superloom-owned composite identifier string, and read it backcreate[Thing]Id / parse[Thing]Id. parse returns an Object, never a positional arrayauth.createAuthId/parseAuthId, contact-phone.createPhoneId/parsePhoneId (D3)
10Render one logical value into a different notation of that same value, and read it backformat[Standard] / parse[Standard]. Always returns a String. The output carries the same information as the input; only the notation changes. If the inputs are several independent facts rather than one value plus render modifiers, this is not format - see row 20All 4 format* functions return String (D8b)
11Decompose an external format that has no build directiondisjoin[Thing]utils.disjoinUrl, utils.disjoinPathname (D3)
12Verbs never to use for the aboveconstruct*, deconstruct*1 live violation across 65 modules, and it is private (D2)
20Assemble several independent parts into a new composite artifactbuild[Artifact]. Returns whatever shape the artifact is: String for a text artifact (buildQuery), Object for a structured one (buildResponseEnvelope). Distinguished from row 10 by whether the inputs are one value plus render modifiers (format) or several independent facts (build)8 distinct functions, 26 occurrences (D8b)
21Does is* return a bare Boolean or an envelopeBare Boolean, always. Bad input throws TypeError; an operation that can fail at runtime is get, not is. See function-naming.md - Return Shape by Verb Class15 bare, 8 enveloped
22Does has* differ from is*has* is a pure in-memory existence check returning a bare Boolean, same throw rule as is*. An existence check that can fail at runtime is getRecordExists with an envelope, not has*. See function-naming.md - Confusable Pairs4 has* functions, all touching storage engines, migrated to getRecordExists*
23Does get* return a bare value or an envelopeBare value when the call cannot fail for any reason other than "not found"; envelope when I/O can fail. See function-naming.md - Return Shape by Verb Class41 enveloped, 7 bare (all 7 pure computation or field reads, already correct)
24create* versus generate*create* produces a resource or durable identity; generate* produces a fresh derived value with no persistence; build* composes several independent parts. See function-naming.md - Confusable PairscreateAddress renamed to buildAddress (composes fields, no persistence, no identity)
25delete / remove / clear / cleanupdelete removes from a persistent store; remove takes an item out of an in-memory collection; clear wipes an entire collection; cleanup removes expired or stale items. See function-naming.md - Confusable PairsdropCollection renamed to deleteCollection (same operation as deleteTable)
26set / update / writeset overwrites a slot; update mutates part of a record; write is the domain-neutral "put a record" verb. Domain-specific verbs that carry a semantic write does not are kept. See function-naming.md - Confusable PairsaddLog kept (append semantic); split recorded as Exceptions
27Config key casingSCREAMING_SNAKE_CASE for all data keys, including nested. PascalCase for injected live objects only. See function-naming.md - Config Key Casing4 patterns unified: PascalCase (kept for live objects), SCREAMING, lowercase, nested-lowercase
28validateCurrencyCode return shape{ valid, reason }, matching the adapter validator contract. The prior false | Array shape inverted truthiness against every other validatormoney.validateCurrencyCode
29Noun-first function namesBanned. The verb goes first. commandBuilderForAddRecord becomes buildAddRecordCommand; commandAddRecord becomes runAddRecordCommand. See function-naming.md - Naming Shape Rules12 noun-first command* names migrated
30xToY conversion namesBanned. The direction determines the verb: format for rendering to a notation, parse for reading back. See function-naming.md - Banned Verbshelper-time xToY names migrated
31Verb-in-the-middle namesBanned. The verb goes first; the object is the parameter. absenteeKeysCheckObject becomes checkAbsenteeKeys. See function-naming.md - Naming Shape Rulesutils verb-in-the-middle names migrated
32Error catalog prefixEvery error type string carries the module prefix. NOT_IMPLEMENTED becomes HTTP_GATEWAY_NOT_IMPLEMENTEDhttp-gateway
33found versus exists in KV envelopesUnify on exists. See function-naming.md - Return Shape by Verb Classlocalstorage and mmkv
34Banned verbs with zero usesread, ensure, transform are banned from new code. Each has a settled alternative in function-naming.md - Banned Verbs0 uses across 65 modules at settlement time; ESLint rule added
35validate / assert / check splitAlready consistent. validate* = config/contract validation; assert* = throws TypeError on programmer error; check* = domain logic. Documented in function-naming.md, not migratedVerified consistent across all modules
36Sync suffix, instance/options params, _ModuleName helpers, async:yes/no accuracyAlready 100% consistent. Sync suffix only when both variants exist; instance first for I/O; options for function options; _ModuleName for private helpers. Documented in function-naming.md, not migratedVerified consistent across all modules
37What is the top isolation boundary called?tenant_id, in every module. Never scope, never org_id, never workspace_id. A single-tenant deployment uses the reserved literal 'system', never the empty stringauth partition key; logger leading index column
38What does scope mean?An OAuth permission set carried in a token, per RFC 6749. Reserved. It is never a tenancy or namespace fieldverify and logger both vacated the word
39What is a composite-key segment with no domain meaning called?namespace. Used when a key segment groups records but is not the tenant and the module places no constraint on what it holdsverify.namespace
40What characters may an identifier that reaches a wire format contain?Any, when the format is parsed by fixed-width right-anchored segments. A reserved character is justified only when relaxing it would break a correctness property such as prefix-query isolation, never merely to make parsing easier. When a separator is needed for composite internal keys, prefer a non-printable control character (\u001F, ASCII Unit Separator) that cannot appear in any human-readable identifier, over a printable character that requires a caller-facing constraintauth.parseAuthId accepts a UUID; composite keys use \u001F as separator, following distinct-queue-store-dynamodb
41What are the two identifier parameters of a cache entry?namespace for the group and cache_code for the entry within it. The word key is not used, because it already means three different things across backends (a flat string in Valkey, a partition plus sort pair in DynamoDB, _id in MongoDB). namespace maps to the Valkey key segment, the DynamoDB partition key, and the MongoDB _id prefix; cache_code maps to the Valkey key suffix, the DynamoDB sort key, and the MongoDB _id suffixcache module and its store adapters

Config Keys

#QuestionSettled answerEvidence
13A duration config keyAlways carries a unit suffix, _MS or _SECONDS11 distinct keys with, 4 without (D4)
14The local-testing override key for a cloud serviceExactly ENDPOINT at the config layer. A prefixed form is an environment variable name, not a config key9 occurrences, 0 prefixed (D5)
16Inject a driver into a store adapterLib.[Family] picked from shared_libs. Family-generic key when the API is interchangeable (Lib.SQL), backend-specific when it is not (Lib.MongoDB)Already doctrine in module-structure.md; row exists so the lookup succeeds
17Pass a live object through configNever. A lib_* config key is a deprecated shapeAlready doctrine in module-structure.md

Time and Expiry

#QuestionSettled answerEvidence
42Compose an absolute expiry timestamp (entry TTL, lock TTL)From instance['time'] (unix seconds, captured at request start), never wall clock. Every read inside one request then agrees on what is expiredcache-store-dynamodb setCache/setCacheLock/isExpired, cache memory-store fake
43Measure elapsed duration inside a request (retry loop, poll deadline)Deltas of Lib.Utils.getUnixTimeInMilliSeconds(). instance['time'] is frozen at request start and cannot measure itcache.waitForLockAndFetch, nosql-aws-dynamodb-admin.waitForTableActive
44Read the current clockThrough Lib.Utils.getUnixTimeInMilliSeconds() or Lib.Utils.getUnixTime(). Raw Date.now() is not written directly, except where no Lib is in scopehelper-instance initialize - "Set initiation timestamps using Lib.Utils (DRY - not raw Date.now)"

Connection Lifecycle

#QuestionSettled answerEvidence
45Where does teardown for a shared resource live?addProcessCleanupRoutine, and the deployment decides when it runs via CLOSE_ON_CLEANUPdocs/languages/js/server/connection-lifecycle.md - Three Lifetimes
46Where does teardown for a request-owned resource live?addInstanceCleanupRoutine, and it runs every request via runInstanceCleanupdocs/languages/js/server/connection-lifecycle.md - Three Lifetimes
47How does a module choose its runtime profile?It does not. The entry point supplies CLOSE_ON_CLEANUP; the module receives the lifecycle APIdocs/languages/js/server/connection-lifecycle.md - Deployment Policy
48May the background-routine gate have a timeout?No. Abandoning in-flight work can lose durable state or leave a state transition incompletedocs/languages/js/server/connection-lifecycle.md - Cleanup Order

Testing

#QuestionSettled answerEvidence
15How to test a module that fronts a cloud serviceA local equivalent in Docker, never the real service. pretest runs docker compose down -v first, dummy credentials in the test script, 127.0.0.1:PORT:PORT binding22 compose files, 0 cloud-credentialed suites (D6)

Return Shapes

#QuestionSettled answerEvidence
18Name the count field an operation returnsThe past participle of that operation's own verb: clear returns cleared_count, remove* returns removed_count, stopAll returns stopped_count, a delete or cleanup returns deleted_countD8. One outlier recorded in Exceptions
19Name a plural payload in an envelopeFor the collection it holds: records, keys, values, resultsD8

Token Contract

#QuestionSettled answerEvidence
48Who owns the token contract?The Themer package (@superloomdev/js-client-helper-themer). Themer.getContract() lists every token, its group, its tier, and its value type. No component library invents a token namedocs/languages/js/client/theming.md - The token contract
49How does a component system validate its tokens?Themer.validateContract(built, { required, supported }). Missing required tokens throw TypeError; unsupported provided tokens warn. Both lists are exported datadocs/languages/js/client/components.md - Theme Token Contract
50May a theme value carry a unit string?No. Theme values are unit-free numbers or color strings. The engine attaches units at emit time. '0.875rem', '2vw', '70ms' are invalid; validateContract reports CONTRACT_INVALID_VALUEdocs/languages/js/client/theming.md - Units and platforms
51Is SCREAMING_SNAKE_CASE used for theme tokens?No. SCREAMING_SNAKE_CASE is for config keys only. Theme tokens use lowercase dot notation (color.interactive, spacing.spacing_05)docs/languages/js/client/theming.md - The token contract; row 27 for config keys

Exceptions

An undocumented exception is a defect. Each is named with its disposition.

ExceptionRowDisposition
SERVER_SELECTION_TIMEOUT13Drift, unify on next touch of that module
NETWORK_TIMEOUT13Drift, unify on next touch
ADMIN_WAIT_TIMEOUT13Drift, unify on next touch
DEFAULT_VISIBILITY_TIMEOUT13Drift, unify on next touch
clearIdleHandlers returns removed_count18Drift, unify on next touch. cleared_count is the rule-conformant name
canonicalize in contact-email9-12Permanent. Established term of art for email normalization; renaming a published public function buys nothing
addLog versus writeRecord / setSession26Permanent. addLog carries an append semantic that writeLog loses. The "put a record" family is not unified; each domain-specific verb reads correctly in its own domain
send in emailnewPermanent. Established term of art for email dispatch; every email library uses send. Not write (no persistence) or run (not an engine command)
sign and verify verbsnewPermanent. Cryptographic signing and verification are distinct from generate (no crypto), build (no signature), check (no crypto), and validate (config-time). sign returns { success, token, error }; verify returns { success, data, error }. Both throw TypeError on bad input or missing secret

Released under the MIT License.