Skip to content

NativeScript Skills

npm

Official, code-first Agent Skills for AI coding agents (Claude Code, Cursor, Codex, Copilot, Gemini CLI and any other client of the open standard) working on NativeScript projects. Each skill is a folder with a SKILL.md: a one-line description the agent matches on, then concrete code that has actually run, plus the pitfalls around it.

skills/
├── core/        @nativescript/core fundamentals, runtime quirks, custom views
├── ios/         Apple frameworks from TypeScript
├── android/     android.* from TypeScript, Java interop
├── frontend/    angular/ · vue/ · react/ · svelte/ · solid/
├── ui/          cross-platform UI & motion patterns
├── device/      device capabilities without plugins
├── testing/     tests, simulator/emulator automation, verification
├── tooling/     CLI, bundlers, assets, CI, release
└── plugins/     authoring and packaging NativeScript plugins

Every install door below flattens this to <skills-dir>/<name>/ — the category is for humans and for the listing pages; agents match on the skill name and description.

Install

You use… Install Update
Any agent (Claude Code, Cursor, Codex, Copilot, Gemini, Windsurf, …) npx skills add NativeScript/skills (add --copy to vendor real files, -g for global) npx skills update
Claude Code plugin /plugin marketplace add NativeScript/skills then /plugin install nativescript-skills@nativescript /plugin update nativescript-skills@nativescript
npm, vendored & pinned in your repo npx @nativescript/skills install --agent claude,agents (writes .nativescript-skills.json; --only ios,frontend/angular filters by category or name) npx @nativescript/skills@latest update (check shows stale/modified files)
TanStack Intent npm i -D @nativescript/skills && npx @tanstack/intent@latest install npm update @nativescript/skills
By hand cp -R skills/<category>/<name> <project>/.claude/skills/ (or ~/.claude/skills/) cp again

Details, trade-offs and the release process: docs/DISTRIBUTION.md.

Skills

37 skills in 6 categories. Generated by npm run sync from the skills/ tree and each category's README.

Android native from TypeScript skills/android/

android.view, Canvas, drawables, Choreographer and the Java/Kotlin interop rules the NativeScript Android runtime enforces: @NativeClass placement, typed-array marshalling, Array.create, overload resolution, colour encoding.

Skill Use it when…
ns-android-edge-to-edge an Android bottom tab bar shows a hard color edge above the gesture-nav strip, bottom-docked UI (composer, action bar) hides behind the gesture pill, content collides with the status bar after touching androidOverflowEdge, or Utils.android.setNavigationBarColor / setStatusBarColor appears to do nothing — how @nativescript/core 9.1+ edge-to-edge insets actually work on API 35+, with recipes for seamless bottom bars and docked bottom UI.
ns-android-window-insets showing a fullscreen native modal on Android (view.showModal with fullscreen true) or wiring androidOverflowEdge / androidOverflowInset anywhere — how window insets (status bar / nav bar / IME) flow through @nativescript/core's edge-to-edge system, and the fullscreen-modal trap where unconsumed insets pad every Label (~50dp-inflated text boxes, phantom gaps, invisible emoji, content under the status bar — iOS unaffected).

Core runtime & views skills/core/

@nativescript/core fundamentals that apply to every flavor: custom views and the common/ios/android file split, Property and CSS plumbing, layouts, lifecycle, and JavaScript-runtime quirks (no Intl on iOS, marshalling rules that cut across platforms).

Skill Use it when…
ns-binding-expressions an XML {{ }} binding throws "Invalid expression syntax", "Disallowed binary operator", or "Invalid converter syntax", when arrow functions in bindings fail, when a binding writes garbage back to the model, or when wiring $value/$parent/$parents/converters — the expression allow-list, the two-way-by-default write-back and its string-substitution hazard, and the silent-global fallback for typo'd names.
ns-color-formats constructing new Color(...) from hex strings, ints, or rgb()/hsl() syntax, reading color.hex / color.argb, or colors come out with wrong alpha — hex STRINGS are RRGGBBAA (alpha last) while argb ints and the 4-arg constructor are alpha-FIRST, .hex drops the alpha when opaque, and short hex doubles each nibble.
ns-http-gotchas Http.getJSON/getString from @nativescript/core resolve happily on a 404/500, reject with a JSON parse error that masks an HTTP error, or when picking between Http.request and fetch — the convenience helpers never check statusCode, error pages become "data", and content conversion is where the rejection actually comes from.
ns-multi-window adopting the NativeScript 9.1 multi-window/NativeWindow model — Application.primaryWindow/activeWindow/getWindows, setWindowContentResolver, openWindow for iPad multi-scene or Android multi-activity, migrating off the deprecated launch event, or per-window orientation()/systemAppearance() — including the Android launchMode manifest requirement openWindow logs about.
ns-navigation-transitions writing or reviewing any Frame.navigate / RouterExtensions.navigate call, when a push/back animation looks flat, janky, or "web-like", or when deciding between animated false, clearHistory, or a custom transition — omit explicit transition options so pages animate with the platform-default navigation transition.
ns-observable-array-change-events handling ObservableArray change events (on('change', ...), ChangedData, args.action/index/addedCount/removed) or when a list misses updates after array.length = n — length assignments emit 'splice' (never add/delete), push reports the pre-push index, setItem's removed holds the old value, and the ObservableArray constructor has a numeric-arity trap.
ns-observable-set-semantics Observable.set() doesn't fire propertyChange, when vm.someProp reads null while vm.get('someProp') works (fromObject accessor gap), when a View's propertyChange listener never fires (views raise textChange/checkedChange-style events instead), or when a listener won't detach or once('tap') keeps firing — set() compares by reference (WrappedValue.wrap is the escape hatch), fromObject only creates accessors for creation-time keys, and comma-joined event names subscribe to nothing.
ns-page-navigation-lifecycle ordering work across Page events (navigatingTo, loaded, navigatedTo, navigatingFrom, unloaded, navigatedFrom), passing context between pages, or controlling the backstack (clearHistory, backstackVisible, canGoBack) — the exact event order, what Frame.topmost().currentPage is at each step, and the backstack rules the framework's own tests assert.
ns-web-globals NativeScript code reaches for a browser/Node global — fetch, AbortController, matchMedia, TextEncoder, crypto, atob, Blob, FormData, localStorage, document — and you need to know what exists, what throws "AbortController is not defined", and what to import instead.
ns-xml-custom-components authoring NativeScript XML — custom components via xmlns, codeFile/cssFile/import attributes, ios:/android: attribute prefixes vs / element blocks — or when decoding a "Building UI from XML." error like "Module not found for element", including why template contents only throw when the template first renders.

iOS native from TypeScript skills/ios/

Driving UIKit, SceneKit, CoreLocation, Metal and other Apple frameworks directly from TypeScript: framework typings, exact selector spelling, delegate classes, render loops, sheets, Liquid Glass.

Skill Use it when…
ns-ios-corespotlight adding CoreSpotlight/system-search indexing to a NativeScript iOS app, when an app freezes or becomes unresponsive shortly after launch/data load, or when a hang report shows the main thread stuck in v8::Locker::Initialize — indexSearchableItems enumerates JS-array adapters on dispatch_apply worker threads and deadlocks the V8 isolate unless you materialize real NSArrays and hop completion handlers back to the main thread.
ns-ios-safe-area-smudge an iOS list shows a random colored streak, stretched dot/pill, or gray band near the bottom edge while scrolling, or a card/list shows an unexplained empty band at its bottom on load — NativeScript's iOS safe-area expansion stretches any small view (dots, hairline dividers, row backgrounds) whose edge lands on the safe-area boundary; fix with iosOverflowSafeArea="false" on the leaves and iosOverflowSafeAreaEnabled="false" on card containers, never on the scroll viewport.
ns-ios-scroll-under-bars a ScrollView/ListView visibly cuts off at a hard line above the tab bar or bottom edge on iOS, when content hides behind a floating/translucent bar with no way to scroll it clear, or when reviewing any iosOverflowSafeArea usage — scroll viewports must extend under floating chrome to the physical screen edge, with clearance padding inside the content.
ns-ios-widgets adding iOS Home Screen widgets, Live Activities, or Dynamic Island UI to a NativeScript app (ns widget ios, WidgetKit, ActivityKit), when a Live Activity never appears or renders empty ("Archive was nil. LiveActivity will be empty"), when a widget shows stale/no data, or when a widget image asset renders blank — App Group data flow, the @objcMembers JS bridge, and the three silent image traps.

Testing & verification skills/testing/

Unit tests (Jest/Vitest) for NativeScript code, end-to-end runners, and driving the iOS simulator / Android emulator from the shell: screenshots, frame-by-frame video checks, taps and swipes, fake location, permission grants, log triage.

Skill Use it when…
ns-trace-debugging debugging layout, binding, navigation, or native lifecycle issues with @nativescript/core Trace and getting no output — Trace.enable() alone prints nothing without addCategories, Trace.categories.All omits Accessibility and BindingError, console lines are prefixed with the category name, and Trace.error() THROWS by default.
ns-unit-testing setting up or running unit tests in a NativeScript app (ns test init, ns test ios/android, vitest.config.mts), migrating off Karma, or hitting runner errors like "No test entrypoint (test.ts or test.js) found", "NativeScript test ... was not bundled", or "NativeScript Vitest worker 0 did not connect" — @nativescript/unit-test-runner v5 runs Vitest 4 specs inside the real iOS/Android runtimes over a WebSocket bridge.

Tooling, build & assets skills/tooling/

The NativeScript CLI, bundlers (@nativescript/vite, @nativescript/webpack), app icons and launch assets, CI pipelines, code signing and release, debugging the build.

Skill Use it when…
ns-file-qualifiers naming platform/size/orientation file variants (page.ios.xml, home.land.css, main.minWH600.xml) or debugging why a variant file is ignored — the supported qualifiers are minWH/minW/minH/land/port/android/ios in that priority order, .land beats .ios, and .tablet/.phone are NOT qualifiers at all (they silently never load).
ns-snippets you need a known-good NativeScript pattern before writing one from scratch, want to share a reusable snippet you just wrote, or are handed a snippets.nativescript.org URL — the public JSON API to search, read, publish (admin-reviewed), and delete NativeScript code snippets, no auth or SDK needed.
ns-uncaught-error-policy a NativeScript app that used to crash on JS errors now silently keeps running (9.1 behavior change), when configuring uncaughtErrorPolicy in nativescript.config.ts, or when removing discardUncaughtJsExceptions — 'report' (the new default) logs and fires Application.uncaughtErrorEvent without crashing, 'throw' restores native crashes for crash reporters, and the key only works at the config's TOP level.

Cross-platform UI & motion skills/ui/

Patterns that look native on both platforms and ship a renderer for each: glass panels, animated sizing, sheets vs. in-page panels, theming, Tailwind/CSS tricks, gesture choreography.

Skill Use it when…
ns-code-built-view-styling building views in TypeScript with new Label()/new StackLayout() (RootLayout overlays, programmatic dialogs/toasts) or when such a view renders unstyled or ignores dark mode — Tailwind utility classes can be purged when they appear only in code, and dark mode needs an explicit Application.systemAppearance() check.
ns-css-keyframes a CSS @keyframes animation animates nothing, snaps back at the end, or ignores animation-direction alternate / animation-play-state — only 12 properties (+transform) are animatable and everything else is silently dropped, fill-mode forwards is required to keep the end state, a unitless animation-delay is seconds, and keyframes under a non-matching @media come back null.
ns-css-selectors a NativeScript CSS rule silently doesn't apply and you're asking "does NativeScript support this selector?" — the supported selector set (:not/:is/:where/:pressed/:hovered/@media/attribute operators), :where()'s zero specificity, bare [attr] selectors matching nothing, per-declaration (not per-block) error recovery, and the className-swap stale-background workaround.
ns-css-variables-calc using var(--x, fallback) or calc() in NativeScript CSS, when view.width reads back as a unit object instead of a number, or when a calc() mixing px and % never evaluates — the var() fallback truth table, the unit-dependent return shapes of calc(), and percent values being fractions (50% parses to value 0.5).
ns-formatted-string-spans mixing styles inside one Label/Button via FormattedString and Span, when a span's colour never applies, or when label.text stops updating after formatted text was shown — setting text while formattedText is set is a silent no-op, the span colour property is color (there is no working foregroundColor), Span.text collapses only the first newline/tab, and a span becomes tappable just by adding a linkTap listener.
ns-gridlayout-spec-strings writing GridLayout rows/columns spec strings ("auto, , 2"), hitting "Cannot parse item spec from string" or "itemSpec is already added to GridLayout", or when a grid column/row silently renders as a 1dp hairline — fr and % units parseInt to garbage without erroring, 'auto' is case-sensitive (Auto throws), numbers are dip not px, grid.rows is write-only, and gap only works on FlexboxLayout.
ns-input-accessory-dialogs a @nativescript/input-accessory docked composer bar floats ON TOP of a page sheet, alert, or popover on iOS, fails to reappear after a modal, or reappears on its own — the bar lives in the keyboard's own window (UITextEffectsWindow), which UIKit z-orders above sheet presentations, so it must be suspended on dialog open and restored on close.
ns-keyboard-input the iOS/Android keyboard covers a text input, when building a chat/composer/search bar docked to the keyboard, or when choosing between @nativescript/iqkeyboardmanager and @nativescript/input-accessory — the decision framework, the docked-composer implementation (TextView not TextField, tab-bar exclusion rule), and the verification workflow.
ns-line-height multi-line Labels show huge gaps between wrapped lines, text looks fine single-line but wrong wrapped, or when configuring @nativescript/tailwind typography — CSS line-height in NativeScript means ADDITIVE space between lines (iOS paragraphStyle.lineSpacing, Android setLineSpacing), not the web's total line box, so web values like 24 or 1.5 inject giant or no-op spacing.
ns-listview-recycling a ListView janks or stutters while scrolling, an itemTemplates template never applies, analytics or side effects in itemLoading fire far too often, or when writing itemLoading handlers / itemTemplateSelector / refresh() — the args.view recycling contract (only create when absent), the selector's silent fallback to the default template on unknown keys, and why refresh() re-fires itemLoading for every item.
ns-root-css-classes writing platform-, device-, orientation-, or theme-conditional CSS without JS branching — the framework stamps ns-root/ns-modal, ns-android/ns-ios/ns-visionos, ns-phone/ns-tablet, ns-portrait/ns-landscape, ns-dark/ns-light, ns-ltr/ns-rtl plus a per-SDK class like ns-ios-17 on every root view; modals get ns-modal instead of ns-root, and neither ns-dark nor ns-light exists on iOS 12 and below.
ns-root-layout-overlays building in-app overlays, toasts, popups, or bottom sheets without a native modal — getRootLayout().open with shadeCover and enter/exit animations, close/closeAll/bringToFront, and the traps — getRootLayout() returns the FIRST registered RootLayout (not the topmost), every method rejects its promise on misuse ("View ... has already been added to the root layout"), and open() zeroes the view opacity before animating.
ns-tabview-lazy-loading initializing per-tab work in a TabView (data fetches or loaded/unloaded handlers on tab content) behaves differently per platform, or a heavy neighbouring tab slows first paint — Android preloads one off-screen tab by default (its content fires loaded for tabs the user never opened) while iOS cannot preload; androidOffscreenTabLimit = 0 normalizes both.
ns-top-nav adding a screen header, back button, or top-bar actions, or when a page's header looks non-native, misaligned, or shows a phantom app-name toolbar on Android — decide between the native ActionBar and a synthetic layout-built header, then implement it with the NavigationButton/ActionItem platform asymmetries handled (iOS tap never fires; Android font:// icons rasterize at CSS font-size).
ns-touch-animations adding any tappable UI (buttons, pills, chips, cards), reviewing touch/press animation code, or tuning tap feel — enable TouchManager.enableGlobalTapAnimations once instead of wiring per-view touch handlers or manual scale animations, opt views out with ignoreTouchAnimation (singular — the plural is silently ignored), and override per-view with the touchAnimation property.
ns-view-animations calling view.animate() / createAnimation().play(), hitting "Animation is already playing.", "Animation cancelled.", "cannot animate height on root view" or "Animating property 'X' is unsupported", or when a cancelled animation's promise never settles on iOS — the two rejection shapes, synchronous validation throws, absolute (not relative) transforms, and the per-platform cancel asymmetry.

Quality

  • npm run lint — Agent Skills spec lint plus the tree rules (depth, naming, uniqueness, category READMEs, one eval task per skill); npm run validate — TanStack Intent's validator; npm run sync:check — generated manifests match the tree. All run in CI.
  • evals/ — a skillgrade suite: one realistic task per skill, executable graders where the code can run headless, and a check that the agent actually discovered the skill among all of them. See evals/README.md; the latest local run is summarised in docs/EVALUATION.md.

Contributing

npm run new <category> <ns-name> scaffolds skills/<category>/<ns-name>/SKILL.md and prints the eval task stub to add to evals/tasks.mjs. Then npm run sync and npm run check. The full guide — where a skill goes, naming, what a good SKILL.md and a good eval task look like — is in CONTRIBUTING.md.

License

Apache-2.0 © NativeScript

About

Official Agent Skills for AI coding agents (Claude Code, Cursor, Codex, Copilot, Gemini CLI and any other client of the open standard) working with NativeScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages