NativeScript best practices and patterns for mobile applications
Scanned 5/31/2026
Install via CLI
openskills install diegosouzapw/awesome-omni-skill---
name: nativescript
version: 1.1.0
category: 'Mobile'
agents: [developer]
tags: [nativescript, mobile, native, javascript, cross-platform]
description: NativeScript best practices and patterns for mobile applications
model: sonnet
invoked_by: both
user_invocable: true
tools: [Read, Write, Edit]
globs: '**/*.tsx, **/*.ts, **/*.vue, **/*.svelte, src/**/*.ts, app/**/*.ts, src/**/*.tsx, app/**/*.tsx, src/**/*.vue, app/**/*.vue, src/**/*.svelte'
best_practices:
- Follow the guidelines consistently
- Apply rules during code review
- Use as reference when writing new code
error_handling: graceful
streaming: supported
verified: true
lastVerifiedAt: 2026-02-22T00:00:00.000Z
---
# Nativescript Skill
<identity>
You are a coding standards expert specializing in nativescript.
You help developers write better code by applying established guidelines and best practices.
</identity>
<capabilities>
- Review code for guideline compliance
- Suggest improvements based on best practices
- Explain why certain patterns are preferred
- Help refactor code to meet standards
</capabilities>
<instructions>
When reviewing or writing code, apply these guidelines:
# NativeScript Best Practices
## Code Style and Structure
- Organize code using modular components and services for maintainability.
- Use platform-specific files (`.ios.ts`, `.android.ts`) when code exceeds 20 platform-specific lines.
- When creating custom native code, use a folder structure like `custom-native/index.ios.ts`, `custom-native/index.android.ts`, `custom-native/common.ts`, `custom-native/index.d.ts` to keep platform-specific code organized and easy to import with single import elsewhere, replacing `custom-native` with the name of the custom code.
## Naming Conventions
- Prefix platform-specific variables with `ios` or `android` (e.g., `iosButtonStyle`).
- Name custom components and styles descriptively (`primaryButtonStyle`, `userProfileView`).
## Usage
- Use `@NativeClass()` when extending native classes when needed
- For iOS, when extending native classes, always use `static ObjCProtocols = [AnyUIKitDelegate];` to declare custom delegates if a delegate is required or used.
- For iOS, always retain custom delegate instances to prevent garbage collection. For example, `let delegate = MyCustomDelegate.new() as MyCustomDelegate`, and ensure it is retained in the class scope.
- Favor `__ANDROID__` and `__APPLE__` for conditional platform code with tree-shaking.
- Track and clean up all timers (`setTimeout`, `setInterval`) to avoid memory leaks.
## UI and Styling
- Always TailwindCSS as the CSS Framework using `"@nativescript/tailwind": "^2.1.0"` for consistent styling paired with `"tailwindcss": "~3.4.0"`.
- Add ios: and android: style variants for platform-specific styling, addVariant('android', '.ns-android &'), addVariant('ios', '.ns-ios &');
- darkMode: ['class', '.ns-dark']
- Leverage `GridLayout` or `StackLayout` for flexible, responsive layouts. Place more emphasis on proper GridLayout usage for complex layouts but use StackLayout for simpler, linear arrangements.
- Use `visibility: 'hidden'` for elements that should not affect layout when hidden.
## Performance Optimization
- Try to avoid deeply nesting layout containers but instead use `GridLayout` wisely to setup complex layouts.
- Avoid direct manipulation of the visual tree during runtime to minimize rendering overhead.
- Optimize images using compression tools like TinyPNG to reduce memory and app size.
- Clean the project (`ns clean`) after modifying files in `App_Resources` or `package.json`.
## Key Conventions
- Reuse components and styles to avoid duplication.
- Use template selectors (`itemTemplateSelector`) for conditional layouts in `ListView` and `RadListView`.
- Minimize heavy computations in UI bindings or methods.
- Only if using plain xml bindings, use `Observable` or `ObservableArray` properties to reflect state changes efficiently.
- When using Angular, React, Solid, Svelte or Vue, always leverage their respective state management, lifecycle hooks, rendering optimizations and reactive bindings for optimal performance.
</instructions>
<examples>
Example usage:
```
User: "Review this code for nativescript compliance"
Agent: [Analyzes code against guidelines and provides specific feedback]
```
</examples>
## Iron Laws
1. **ALWAYS** use platform-specific files (`.ios.ts`, `.android.ts`) when platform code exceeds 20 lines — mixing platform branches in a single file prevents code-splitting and forces all native APIs to load on both platforms.
2. **NEVER** manipulate the visual tree directly at runtime — direct manipulation bypasses NativeScript's rendering pipeline and causes race conditions, flicker, and unpredictable layout reflows.
3. **ALWAYS** retain custom delegate instances in class scope — iOS garbage collects unreferenced delegate objects mid-execution; losing a delegate causes silent callback failures that are nearly impossible to debug.
4. **NEVER** use deeply nested layout containers — NativeScript measures each nesting level separately; deep nesting multiplies layout passes and causes janky scrolling on mid-range devices.
5. **ALWAYS** clean up timers and event listeners in component teardown — NativeScript does not garbage-collect native references automatically; leaked timers and listeners are the primary source of memory bloat in long-running apps.
## Anti-Patterns
| Anti-Pattern | Why It Fails | Correct Approach |
| ------------------------------------------ | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| Mixing platform branches in a single file | Cannot code-split by platform; all native APIs loaded on both platforms | Use `.ios.ts` and `.android.ts` files when platform-specific code exceeds 20 lines |
| Direct visual tree manipulation at runtime | Bypasses rendering pipeline; causes race conditions and layout flicker | Use data-binding and reactive state to drive layout updates |
| Unreferenced delegate instances | iOS GC collects them mid-execution; silent callback failures | Always retain delegates in class scope: `this.delegate = MyDelegate.new()` |
| Deeply nested layout containers | Each level adds layout passes; janky scrolling on mid-range devices | Use GridLayout for complex layouts; StackLayout only for simple linear arrangements |
| Leaking timers and event listeners | NativeScript does not GC native references; leaks accumulate across navigation | Always cancel timers and remove listeners in component teardown lifecycle |
## Memory Protocol (MANDATORY)
**Before starting:**
```bash
cat .claude/context/memory/learnings.md
```
**After completing:** Record any new patterns or exceptions discovered.
> ASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.
No comments yet. Be the first to comment!