skills/vendix-zoneless-signals/SKILL.md
Angular 20 zoneless and signals patterns for Vendix frontend: app.config setup, signal inputs/outputs/models, toSignal in facades, CVA rules, audit script usage, and legacy patterns that must not be copied into new code.
npx skillsauth add rzyfront/vendix vendix-zoneless-signalsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
apps/frontend/src/app/app.config.tsapps/frontend/scripts/zoneless-audit.shapps/frontend/src/app/Vendix frontend runs with provideZonelessChangeDetection() in app.config.ts.
NgRx runtime checks explicitly set strictActionWithinNgZone: false.
input(), output(), model(), signal(), computed(), and effect().toSignal(..., { initialValue }) for synchronous reads.value / disabled state in signals.NgZone.run(), markForCheck(), detectChanges(), or sync take(1).subscribe() patterns unless there is a documented and exceptional reason.The repo is largely migrated, but the canonical audit source is zoneless-audit.sh, not a naive “all grep counts must be zero” assumption. The audit script already includes documented exemptions and warning-only checks.
Do not copy remaining legacy patterns just because a few repo exceptions still exist.
Use apps/frontend/scripts/zoneless-audit.sh as the first compliance check. It validates:
@Input/@Output regressionsEventEmitterNgZonemarkForCheck / detectChangesBehaviorSubjecttoSignal without initialValue in facadessubscribe() usagezone.js outside allowed test contextsSome checks are warnings, not hard failures. Follow the script’s logic rather than inventing stricter local grep rules.
if (this.loading) instead of if (this.loading())toSignal() in facades without initialValue when synchronous consumers existmodel() signalform.invalid / form.value / form.status read inside computed() or effect() — these are plain properties, not signals. The computed evaluates once with the initial state and never recomputes when validity changes. Symptom: a "Guardar" button bound to disabled: this.form.invalid inside computed() stays permanently disabled (initial state = invalid because of Validators.required) even after the user fills the form. Fix: bridge form state with toSignal(form.statusChanges.pipe(startWith(form.status)), { initialValue: form.status }), then read the signal inside the computed. Same pattern for form.valueChanges if you need value reactivity.@if, @for, @defer in new templates.async pipe still works, but prefer signal access when synchronous reads or signal composition are clearer.vendix-frontendvendix-angular-formsvendix-frontend-componentvendix-frontend-statedevelopment
Mobile app development rules for Vendix Expo/React Native project. Trigger: When editing, creating, or modifying any file under apps/mobile, or when developing mobile-specific features.
development
Feature gating by store subscription state: global store write guard, AI feature gate, Redis feature resolution, quota consumption, frontend paywall interceptor, banner, and subscription UI states. Trigger: When adding feature gates, paywalls, subscription-based access control, protecting store write operations, AI feature gates, or rollout flags.
testing
SaaS subscription billing for Vendix stores: plan pricing, invoices, Wompi platform payments, manual payments, partner commissions, payouts, proration, and dunning. Trigger: When creating SaaS invoices, working with partner rev-share, margin/surcharge pricing, invoice sequence allocation, partner payout batches, subscription payments, manual payments, or dunning flows.
development
Periodic quota counters with Redis, UTC period keys, Lua-based idempotent AI quota consumption, request-id deduplication, and post-success consumption. Trigger: When building quota counters, enforcing monthly/daily feature caps, or reusing AI quota patterns for uploads, emails, exports, or rate-limited features.