home / skills / maccesar / titanium-sdk-skills / alloy-expert

alloy-expert skill

/skills/alloy-expert

This skill provides complete Titanium Alloy architecture guidance and automated project detection to design, review, and migrate Alloy projects.

npx playbooks add skill maccesar/titanium-sdk-skills --skill alloy-expert

Review the files below or copy the command above to add this skill to your agents.

Files (15)
SKILL.md
10.8 KB
---
name: alloy-expert
description: "Titanium Alloy architecture and implementation expert. Use when designing, reviewing, analyzing, or examining Alloy project structure, creating controllers/views/services, choosing models vs collections, implementing communication patterns, handling memory cleanup, testing, auditing code, or migrating legacy apps. Detects Alloy vs Classic projects automatically."
argument-hint: "[architecture-topic]"
allowed-tools: Read, Grep, Glob, Edit, Write, Bash(git *), Bash(node *)
---

# Titanium Alloy Expert

Complete architectural and implementation guidance for building scalable, maintainable Titanium Alloy applications with PurgeTSS styling.

## Project Detection

:::info AUTO-DETECTS ALLOY VS CLASSIC PROJECTS
This skill automatically detects project type when invoked and provides appropriate guidance.

**Detection occurs automatically** - no manual command needed.

**Alloy project indicators:**
- `app/` folder (MVC structure)
- `app/views/`, `app/controllers/` folders
- `alloy.jmk` or `config.json` files

**Classic project indicators:**
- `Resources/` folder with `app.js` at root
- No `app/` folder structure

**Behavior based on detection:**
- **Alloy detected** → Provides Alloy-specific architecture patterns, MVC folder structure, Backbone.js patterns
- **Classic detected** → Indicates incompatibility, does not suggest Alloy-specific patterns, recommends migration or Classic resources
- **Unknown** → Asks user to clarify project type
:::

## Table of Contents

- [Titanium Alloy Expert](#titanium-alloy-expert)
  - [Project Detection](#project-detection)
  - [Table of Contents](#table-of-contents)
  - [Workflow](#workflow)
  - [Quick Start Example](#quick-start-example)
  - [Code Standards (Low Freedom)](#code-standards-low-freedom)
  - [PurgeTSS Rules (Low Freedom)](#purgetss-rules-low-freedom)
  - [Quick Decision Matrix](#quick-decision-matrix)
  - [Reference Guides (Progressive Disclosure)](#reference-guides-progressive-disclosure)
    - [Architecture](#architecture)
    - [Implementation](#implementation)
    - [Quality \& Reliability](#quality--reliability)
    - [Performance \& Security](#performance--security)
    - [Migration](#migration)
  - [Specialized Titanium Skills](#specialized-titanium-skills)
  - [Guiding Principles](#guiding-principles)
  - [Response Format](#response-format)

---

## Workflow

1. **Architecture**: Define structure (`lib/api`, `lib/services`, `lib/helpers`)
2. **Data Strategy**: Choose Models (SQLite) or Collections (API)
3. **Contracts**: Define I/O specs for cross-layer communication
4. **Implementation**: Write XML views + ES6+ controllers
5. **Quality**: Testing, error handling, logging, performance
6. **Cleanup**: Implement `cleanup()` pattern for memory management

## Quick Start Example

Minimal example following all conventions:

**View (views/user/card.xml)**
```xml
<Alloy>
  <View class="m-2 rounded-xl bg-white shadow-md">
    <View class="horizontal m-3 w-screen">
      <Label class="fa-solid fa-user text-2xl text-blue-500" />
      <Label id="name" class="ml-3 text-lg font-bold" />
    </View>
    <Button class="mx-3 mb-3 h-10 w-screen rounded-md bg-blue-600 text-white"
      title="L('view_profile')"
      onClick="onViewProfile"
    />
  </View>
</Alloy>
```

**Controller (controllers/user/card.js)**
```javascript
const { Navigation } = require('lib/services/navigation')

function init() {
  const user = $.args.user
  $.name.text = user.name
}

function onViewProfile() {
  Navigation.open('user/profile', { userId: $.args.user.id })
}

function cleanup() {
  $.destroy()
}

$.cleanup = cleanup
```

**Service (lib/services/navigation.js)**
```javascript
exports.Navigation = {
  open(route, params = {}) {
    const controller = Alloy.createController(route, params)
    const view = controller.getView()

    view.addEventListener('close', function() {
      if (controller.cleanup) controller.cleanup()
    })

    view.open()
    return controller
  }
}
```

## Code Standards (Low Freedom)

- **NO SEMICOLONS**: Let ASI handle it
- **MODERN SYNTAX**: `const/let`, destructuring, template literals
- **applyProperties()**: Batch UI updates to minimize bridge crossings
- **MEMORY CLEANUP**: Every controller with global listeners MUST have `$.cleanup = cleanup`
- **ERROR HANDLING**: Use AppError classes, log with context, never swallow errors
- **TESTABLE**: Inject dependencies, avoid hard coupling

## PurgeTSS Rules (Low Freedom)

:::danger CRITICAL: Platform-Specific Properties Require Modifiers
Using `Ti.UI.iOS.*` or `Ti.UI.Android.*` properties WITHOUT platform modifiers causes cross-platform compilation failures.

**Example of the damage:**
```tss
// ❌ WRONG - Adds Ti.UI.iOS to Android project
"#mainWindow": {
  statusBarStyle: Ti.UI.iOS.StatusBar.LIGHT_CONTENT  // FAILS on Android!
}
```

**CORRECT - Always use platform modifiers:**
```tss
// ✅ CORRECT - Only adds to iOS
"#mainWindow[platform=ios]": {
  statusBarStyle: Ti.UI.iOS.StatusBar.LIGHT_CONTENT
}
```

**Properties that ALWAYS require platform modifiers:**
- iOS: `statusBarStyle`, `modalStyle`, `modalTransitionStyle`, any `Ti.UI.iOS.*`
- Android: `actionBar` configuration, any `Ti.UI.Android.*` constant

**Available modifiers:** `[platform=ios]`, `[platform=android]`, `[formFactor=handheld]`, `[formFactor=tablet]`, `[if=Alloy.Globals.customVar]`

**For more platform-specific patterns, see** [Platform Modifiers (purgetss)](skills/purgetss/references/platform-modifiers.md) or [Platform UI guides (ti-ui)](skills/ti-ui/references/platform-ui-ios.md).
:::

| WRONG                          | CORRECT             | Why                           |
| ------------------------------ | ------------------- | ----------------------------- |
| `flex-row`                     | `horizontal`        | Flexbox not supported         |
| `flex-col`                     | `vertical`          | Flexbox not supported         |
| `p-4` on View                  | `m-4` on children   | No padding on containers      |
| `justify-*`                    | margins/positioning | Flexbox not supported         |
| `items-center` (for centering) | layout + sizing     | Different meaning in Titanium |
| `rounded-full` (for circle)    | `rounded-full-12`   | Need size suffix (12×4=48px)  |
| `border-[1px]`                 | `border-(1)`        | Parentheses, not brackets     |

**Note on `w-full` vs `w-screen`:**
- `w-full` → `width: '100%'` (100% of parent container) - exists and valid
- `w-screen` → `width: Ti.UI.FILL` (fills all available space) - use for full-width elements

## Quick Decision Matrix

| Question                           | Answer                                                         |
| ---------------------------------- | -------------------------------------------------------------- |
| How to create a new Alloy project? | **`ti create -t app --alloy`** (not `--classic` + `alloy new`) |
| Where does API call go?            | `lib/api/`                                                     |
| Where does business logic go?      | `lib/services/`                                                |
| Where do I store auth tokens?      | Keychain (iOS) / KeyStore (Android) via service                |
| Models or Collections?             | Collections for API data, Models for SQLite persistence        |
| Ti.App.fireEvent or EventBus?      | **Always EventBus** (Backbone.Events)                          |
| Direct navigation or service?      | **Always Navigation service** (auto cleanup)                   |
| Manual TSS or PurgeTSS?            | **Always PurgeTSS utility classes**                            |
| Controller 100+ lines?             | Extract logic to services                                      |

## Reference Guides (Progressive Disclosure)

### Architecture
- **[Structure & Organization](references/alloy-structure.md)**: Models vs Collections, folder maps, styling strategies, automatic cleanup
- **[ControllerAutoCleanup.js](assets/ControllerAutoCleanup.js)**: Drop-in utility for automatic controller cleanup (prevents memory leaks)
- **[Architectural Patterns](references/patterns.md)**: Repository, Service Layer, Event Bus, Factory, Singleton
- **[Contracts & Communication](references/contracts.md)**: Layer interaction examples and JSDoc specs
- **[Anti-Patterns](references/anti-patterns.md)**: Fat controllers, flexbox classes, memory leaks, direct API calls

### Implementation
- **[Code Conventions](references/code-conventions.md)**: ES6 features, PurgeTSS usage, accessibility
- **[Controller Patterns](references/controller-patterns.md)**: Templates, animation, dynamic styling
- **[Examples](references/examples.md)**: API clients, SQL models, full screen examples

### Quality & Reliability
- **[Testing](references/testing.md)**: Unit testing, mocking patterns, controller testing, test helpers
- **[Error Handling & Logging](references/error-handling.md)**: AppError classes, Logger service, validation

### Performance & Security
- **[Performance Patterns](references/performance-patterns.md)**: ListView, bridge optimization, memory management, lazy loading
- **[Security Patterns](references/security-patterns.md)**: Token storage, certificate pinning, encryption, OWASP
- **[State Management](references/state-management.md)**: Centralized store, reactive patterns, synchronization

### Migration
- **[Migration Patterns](references/migration-patterns.md)**: Step-by-step guide for modernizing legacy apps

## Specialized Titanium Skills

For specific feature implementations, defer to these specialized skills:

| Task                                                  | Use This Skill |
| ----------------------------------------------------- | -------------- |
| PurgeTSS setup, advanced styling, animations          | `purgetss`     |
| Location, Maps, Push Notifications, Media APIs        | `ti-howtos`    |
| UI layouts, ListViews, gestures, platform-specific UI | `ti-ui`        |
| Alloy CLI, configuration files, debugging             | `alloy-howtos` |
| Alloy MVC complete reference                          | `alloy-guides` |
| Hyperloop, native modules, app distribution           | `ti-guides`    |

## Guiding Principles

1. **Thin Controllers**: Max 100 lines. Delegate to services.
2. **Single Source of Truth**: One state store, not scattered Properties.
3. **Always Cleanup**: Every listener added = listener removed in `cleanup()`.
4. **Never Block UI**: All API/DB calls are async with loading states.
5. **Fail Gracefully**: Centralized error handling with user-friendly messages.

## Response Format

**For Architecture Questions:**
1. Decision: What should be done
2. Justification: Technical rationale
3. Structure: File and folder placement
4. Contract: Clear I/O specification

**For Implementation Tasks:**
1. Code First: Show implementation immediately
2. Minimal Comments: Explain only the "Why" for complex logic
3. No Explanations: Deliver exactly what was asked concisely

Overview

This skill is a Titanium Alloy architecture and implementation expert for designing, reviewing, analyzing, and migrating Alloy projects. It auto-detects Alloy vs Classic projects and adapts guidance accordingly. Use it to create controllers, views, services, styling (PurgeTSS), and memory-cleanup patterns. Advice focuses on scalable, testable, and maintainable Alloy code.

How this skill works

The skill scans your project structure to detect Alloy indicators (app/, app/controllers/, app/views/, alloy.jmk or config.json) and Classic indicators (Resources/, app.js). For Alloy projects it returns actionable architecture patterns, folder structure recommendations, controller/service examples, and PurgeTSS rules. For Classic projects it highlights incompatibilities and recommends migration steps or Classic-specific resources. Unknown projects prompt a clarification request.

When to use it

  • Designing app architecture, folder layout, and service boundaries
  • Reviewing controllers/views/services for maintainability and memory leaks
  • Choosing between Models (SQLite) and Collections (API) for data strategy
  • Implementing communication patterns, navigation, and automated cleanup
  • Migrating legacy Classic apps to Alloy or auditing migration risks

Best practices

  • Favor thin controllers (≤100 lines); extract business logic to lib/services
  • Always implement cleanup() on controllers that register global listeners
  • Use PurgeTSS utilities; apply platform modifiers for Ti.UI.iOS/Ti.UI.Android properties
  • Use Navigation service for routing to centralize open/close and auto-cleanup
  • Inject dependencies and avoid hard coupling for testability

Example use cases

  • Create a Navigation service that opens controllers and invokes controller.cleanup on close
  • Convert a large controller to a service + small view/controller pair to reduce lines and improve tests
  • Audit project for PurgeTSS mistakes (platform constants used without modifiers) and fix TSS selectors
  • Decide Models vs Collections for a feature: choose Models for local SQLite persistence, Collections for API-driven data
  • Migrate a Classic Resources/ app.js app to Alloy by mapping views/controllers and extracting services

FAQ

How does project detection work?

It checks for app/ folders and alloy.jmk/config.json to identify Alloy; Resources/ and root app.js indicate Classic; if neither is present it asks you to confirm.

What if my controller has global listeners?

Add a cleanup() that removes listeners and call $.destroy(); assign $.cleanup = cleanup and ensure Navigation service invokes it on view close.