From unitism
Use this skill whenever a change is being made to a primary surface in a UNITISM consumer-facing repo (`tennis-miami`, `tennis-miami-web`, `arenna-link`, or future consumer apps on the platform). Primary surfaces include: bottom navigation / tab bar, the first screen shown after login or signup, the onboarding or signup flow's headline / primary CTA, the app store listing copy, the marketing site hero or top-level navigation, the home tab's empty state, and the first push notification copy sent to a new user. Triggers on diffs that add, remove, rename, reorder, or re-label items on these surfaces; on copy changes to hero headlines, CTAs, or onboarding text; on icon or label changes for nav tabs; and on any request phrased as "add X tab", "show Y on home", "rename the Z tab", "change the hero", or similar primary-surface language. Also triggers when a backend or features-only change introduces a new user-facing surface that will need primary-surface placement (e.g., a new entitlement that implies a new tab). The skill checks the change against `_shared/strategy/product-positioning-principles.md`, identifies which product's positioning applies (Tennis Miami → community-first; ARENNA → instructor-first), runs the primary-surface decision test, and outputs a flag-with-reasoning + a suggested non-primary alternative when the change risks shifting the product's perceived category. Do NOT trigger on backend-only changes with no user-visible surface, on internal tooling, on test files, on lockfiles, on changes confined to non-primary surfaces (account/settings/profile sub-views), or on changes to internal product or strategy docs. Engineers can opt out for a single change by saying "skip the positioning check — I've thought about it."
How this skill is triggered — by the user, by Claude, or both
Slash command
/unitism:product-positioning-checkThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A non-engineer recently shipped a change that didn't break the build but did break the product's positioning: wallet and offers were added as bottom-nav tabs in Tennis Miami, shifting the app's first-glance answer from *"community"* to *"marketplace."* The build passed. CI passed. The PR review caught nothing because reviewers checked the code, not the positioning.
A non-engineer recently shipped a change that didn't break the build but did break the product's positioning: wallet and offers were added as bottom-nav tabs in Tennis Miami, shifting the app's first-glance answer from "community" to "marketplace." The build passed. CI passed. The PR review caught nothing because reviewers checked the code, not the positioning.
This skill exists to catch that class of regression. It runs alongside (not instead of) the normal review skills. It does one job: when a primary surface is being touched, evaluate the change against the product's stated positioning principle and either bless it, suggest a non-primary alternative, or flag it for explicit Yuval sign-off.
It is not a gate. It is a second pair of eyes that knows what the product is supposed to be.
This skill reads _shared/strategy/product-positioning-principles.md (in claude_files, sibling to the strategy handoff). That doc names:
If that doc is missing or out of date, STOP and tell the user before proceeding — running the check without a current source of truth produces false confidence. The doc must exist and must have a Status: locked line; if it says "draft" or has no status, treat it as advisory and surface that caveat in the output.
The skill activates when a diff touches a primary surface in a consumer-facing repo. Concretely:
Files / patterns that always trigger (Tennis Miami / Flutter naming, adapt for the actual repo):
bottom_nav, tab_bar, main_navigation, app_shell, root_navigator, home_scaffoldonboarding/, signup/, welcome/, splash/ directories — first-flow surfacesmarketing/, landing/, the website's hero component or top-level layoutapp_store_metadata.json, fastlane/metadata/, play_store/, anything with screenshots / descriptionsDiff patterns that always trigger (regardless of file):
hero_*, headline_*, welcome_*, tagline, app_description, cta_primaryPhrasing in the user's request that always triggers (even if no file pattern matched yet):
<word> tab"<thing> on the home screen"<word> tab"<screen> after login"<feature> to the nav"Things that explicitly DO NOT trigger:
account/, settings/, profile/, wallet/ sub-screens (non-primary by definition)strategy-doc, planned)Determine which positioning applies based on the repo:
| Repo | Product | Positioning |
|---|---|---|
tennis-miami, tennis-miami-web | Tennis Miami (consumer) | community-first |
arenna-link | ARENNA (instructor side of the consumer surface) | instructor-first |
| Future consumer repos | Look up in the principles doc; if missing, STOP |
If the repo isn't in the principles doc's per-product applications section, do not guess. Tell the user the principles doc needs an entry for this product before the check can run.
Read _shared/strategy/product-positioning-principles.md. Confirm:
If any of these are missing, surface that and stop.
For each changed file or diff hunk, classify:
<screen> reachable from the bottom nav, or only from inside another flow?"For each primary-surface change, mentally run the test from the principles doc:
Show the surface to someone who has never used the product. Ask them: "in one sentence, what is this app?" Does the answer match the product's stated positioning?
Concretely, for a nav change:
Compare the change to the explicit anti-pattern list in the principles doc. Examples:
Wallet, Offers, Buy, Shop, Subscribe, Deals)If any anti-pattern matches, the result is a hard fail (not a flag).
The output is structured. Three possible verdicts:
PASS — change does not affect a primary surface, or affects one and the decision test resolves cleanly. One-line emission:
Positioning check: ✅ no impact on primary-surface positioning. (Reason:
<surface>is non-primary / change preserves the community-first answer / etc.)
FLAG — change affects a primary surface and the decision test is arguable. Emit:
Positioning check: ⚠️ this change touches a primary surface. The principle at risk:
<short principle>. The decision test reading: "<what a stranger would say>" — compare to the stated positioning "<what the doc says>". This may be intentional, but it should have explicit sign-off from Yuval before merge. Suggested non-primary alternative:<concrete alternative>.
FAIL — change matches an anti-pattern or the decision test reads clearly wrong. Emit:
Positioning check: ❌ this change conflicts with the locked product positioning. Principle:
<short principle>. What this surface would now answer to a first-time user: "<wrong reading>". What it should answer: "<right reading>". Concrete fix: move<feature>from<primary surface>to<non-primary surface>— e.g.,<example>. The feature is fine; the placement is the issue. See_shared/strategy/product-positioning-principles.mdworked example #1 for the canonical case.
For FLAG and FAIL, always include:
Never just say "this is wrong." Say what is wrong, why per the doc, and where it should live instead.
This skill emits a verdict. It does not block the PR or the commit. The non-engineer skill (non-engineer-frontend-contribution) handles git flow; this one informs the diff. Two reasons:
If the skill keeps producing FAIL on the same kind of change across multiple sessions, that's evidence the principles doc needs an update — surface this once at the end of the verdict, don't repeat it.
Account is fine. Wallet in the nav is not. Know the difference.The principles doc encodes a snapshot of the strategy. Strategy evolves. If the engineer pushes back with a coherent reason — "we're explicitly trying to shift Tennis Miami toward marketplace because the cold-start solved itself" — the right move is:
product-positioning-principles.md first, then this change becomes a clean PASS."_shared/strategy/product-positioning-principles.md — the source of truth this skill reads. Keep it short and current._shared/strategy/ai-strategy-handoff.md — terminology rules and platform context.claude_files/projects/tennis-miami/current-direction-apr2026.md — Tennis Miami's locked business model decisions (separate from primary-surface positioning).non-engineer-frontend-contribution/SKILL.md — the git-flow skill this runs alongside.npx claudepluginhub yuvalklein/unitism-skills --plugin unitismCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.