vybekiit 0.7.16 → 0.7.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +46 -11
- package/dist/global-skills/expo-native-ui/SKILL.md +3 -0
- package/dist/global-skills/expo-native-ui/references/controls.md +2 -0
- package/dist/global-skills/expo-overview/SKILL.md +110 -0
- package/dist/global-skills/expo-overview/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-skill-feedback/scripts/telemetry_common.cjs +6 -6
- package/dist/global-skills/expo-ui/SKILL.md +52 -6
- package/dist/global-skills/expo-ui/references/universal.md +31 -0
- package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/android.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/api.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/best-practices.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/django.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/dotnet.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/elixir.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/flask.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/flutter.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/go.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/ios.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/java.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/laravel.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/next-js.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/nodejs.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/php.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/python.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/react-native.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/react.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/ruby.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/rust.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/usage.md +4 -0
- package/dist/global-skills/instrument-feature-flags/references/web.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-swift.md +0 -1
- package/dist/global-skills/instrument-product-analytics/references/android.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/angular.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/astro.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/django.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/dotnet.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/elixir.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/flask.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/go.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/identify-users.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/ios.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/laravel.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/next-js.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/php.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +52 -5
- package/dist/global-skills/instrument-product-analytics/references/python.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/react-native.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/ruby.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/svelte.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/usage.md +4 -0
- package/dist/global-skills/instrument-product-analytics/references/vue-js.md +4 -0
- package/dist/global-skills/manifest.json +2 -1
- package/dist/global-skills/neon/SKILL.md +2 -2
- package/dist/global-skills/neon-ai-gateway/SKILL.md +13 -13
- package/dist/global-skills/neon-functions/SKILL.md +3 -3
- package/dist/global-skills/neon-functions/references/ai-sdk.md +1 -1
- package/dist/global-skills/neon-object-storage/SKILL.md +1 -1
- package/dist/global-skills/resend/SKILL.md +1 -1
- package/dist/global-skills/resend/references/automations.md +10 -1
- package/package.json +8 -8
package/dist/bin.js
CHANGED
|
@@ -11140,9 +11140,10 @@ var defaultStartDetached = (cwd, bin, args) => {
|
|
|
11140
11140
|
return false;
|
|
11141
11141
|
}
|
|
11142
11142
|
};
|
|
11143
|
+
var claudeTerminalCommand = (appPath, prompt) => `cd ${JSON.stringify(appPath)} && claude ${JSON.stringify(prompt)}; exec "\${SHELL:-/bin/zsh}" -l`;
|
|
11143
11144
|
var openClaudeWithSeed = async (appPath, prompt, platform = process7.platform) => {
|
|
11144
11145
|
if (platform === "darwin") {
|
|
11145
|
-
const shellCommand =
|
|
11146
|
+
const shellCommand = claudeTerminalCommand(appPath, prompt);
|
|
11146
11147
|
const osa = makeExec("osascript");
|
|
11147
11148
|
const result = await osa([
|
|
11148
11149
|
"-e",
|
|
@@ -11190,7 +11191,7 @@ var defaultPnpmCommand = async () => {
|
|
|
11190
11191
|
return null;
|
|
11191
11192
|
};
|
|
11192
11193
|
var wait = async (milliseconds) => await new Promise((resolve19) => setTimeout(resolve19, milliseconds));
|
|
11193
|
-
var
|
|
11194
|
+
var waitForPreview = async (url) => {
|
|
11194
11195
|
const attemptPreview = async (remainingAttempts) => {
|
|
11195
11196
|
try {
|
|
11196
11197
|
const response = await fetch(url, { redirect: "follow" });
|
|
@@ -11242,7 +11243,7 @@ var defaultDeps = () => ({
|
|
|
11242
11243
|
runCommand: defaultRunCommand,
|
|
11243
11244
|
startDetached: defaultStartDetached,
|
|
11244
11245
|
openClaude: (appPath, prompt) => openClaudeWithSeed(appPath, prompt, process7.platform),
|
|
11245
|
-
waitForPreview
|
|
11246
|
+
waitForPreview,
|
|
11246
11247
|
openBrowser: defaultOpenBrowser,
|
|
11247
11248
|
prepareProjectTools: async (appPath) => {
|
|
11248
11249
|
try {
|
|
@@ -11429,6 +11430,7 @@ Creating your first web app at ${appPath}\u2026
|
|
|
11429
11430
|
// src/commands/createUiLibrary.ts
|
|
11430
11431
|
var DEFAULT_UI_LIBRARY_DIR_NAME = "vybekiit-ui-library";
|
|
11431
11432
|
var UI_LIBRARY_GALLERY_URL = "https://ui.vybekiit.com";
|
|
11433
|
+
var UI_LIBRARY_LOCAL_URL = "http://127.0.0.1:3000/en";
|
|
11432
11434
|
var UI_LIBRARY_SEED_PROMPT = `I opened my VybeKiit UI library workspace.
|
|
11433
11435
|
|
|
11434
11436
|
Work ONLY in this folder (the kit workspace). Do not claim the UI library is missing.
|
|
@@ -11552,6 +11554,7 @@ var defaultDeps2 = () => ({
|
|
|
11552
11554
|
isEmptyDir: defaultIsEmptyDir2,
|
|
11553
11555
|
runCommand: defaultRunCommand2,
|
|
11554
11556
|
startDetached: defaultStartDetached2,
|
|
11557
|
+
waitForPreview,
|
|
11555
11558
|
openClaude: (appPath, prompt) => openClaudeWithSeed(appPath, prompt, process8.platform),
|
|
11556
11559
|
openUrl: defaultOpenUrl,
|
|
11557
11560
|
pnpmCommand: defaultPnpmCommand2,
|
|
@@ -11589,7 +11592,11 @@ var formatCreateUiLibraryLines = (result) => {
|
|
|
11589
11592
|
lines.push(" \u2022 Build packages: pnpm build:packages");
|
|
11590
11593
|
}
|
|
11591
11594
|
if (result.devStarted) {
|
|
11592
|
-
|
|
11595
|
+
if (result.localPreviewOpened) {
|
|
11596
|
+
lines.push(` \u2022 Local app opened: ${UI_LIBRARY_LOCAL_URL}`);
|
|
11597
|
+
} else {
|
|
11598
|
+
lines.push(` \u2022 Open your local app: ${UI_LIBRARY_LOCAL_URL}`);
|
|
11599
|
+
}
|
|
11593
11600
|
}
|
|
11594
11601
|
if (result.galleryOpened) {
|
|
11595
11602
|
lines.push(` \u2022 UI gallery opened: ${UI_LIBRARY_GALLERY_URL}`);
|
|
@@ -11627,6 +11634,8 @@ var runCreateUiLibrary = async (args = [], deps = defaultDeps2()) => {
|
|
|
11627
11634
|
depsInstalled: false,
|
|
11628
11635
|
packagesBuilt: false,
|
|
11629
11636
|
devStarted: false,
|
|
11637
|
+
previewReady: false,
|
|
11638
|
+
localPreviewOpened: false,
|
|
11630
11639
|
galleryOpened: false,
|
|
11631
11640
|
claudeOpened: false
|
|
11632
11641
|
};
|
|
@@ -11654,6 +11663,8 @@ Creating UI library kit workspace at ${appPath}\u2026
|
|
|
11654
11663
|
depsInstalled: false,
|
|
11655
11664
|
packagesBuilt: false,
|
|
11656
11665
|
devStarted: false,
|
|
11666
|
+
previewReady: false,
|
|
11667
|
+
localPreviewOpened: false,
|
|
11657
11668
|
galleryOpened: false,
|
|
11658
11669
|
claudeOpened: false
|
|
11659
11670
|
};
|
|
@@ -11679,6 +11690,8 @@ Creating UI library kit workspace at ${appPath}\u2026
|
|
|
11679
11690
|
devStarted = deps.startDetached(appPath, pnpmBin, [...pnpmPrefix, "dev"]);
|
|
11680
11691
|
}
|
|
11681
11692
|
}
|
|
11693
|
+
const previewReady = devStarted ? await deps.waitForPreview(UI_LIBRARY_LOCAL_URL) : false;
|
|
11694
|
+
const localPreviewOpened = previewReady ? await deps.openUrl(UI_LIBRARY_LOCAL_URL) : false;
|
|
11682
11695
|
let galleryOpened = false;
|
|
11683
11696
|
if (inputs.openGallery) {
|
|
11684
11697
|
process8.stdout.write(`
|
|
@@ -11697,6 +11710,8 @@ Opening UI gallery: ${UI_LIBRARY_GALLERY_URL}
|
|
|
11697
11710
|
depsInstalled,
|
|
11698
11711
|
packagesBuilt,
|
|
11699
11712
|
devStarted,
|
|
11713
|
+
previewReady,
|
|
11714
|
+
localPreviewOpened,
|
|
11700
11715
|
galleryOpened,
|
|
11701
11716
|
claudeOpened
|
|
11702
11717
|
};
|
|
@@ -26488,22 +26503,42 @@ var tools = [
|
|
|
26488
26503
|
}
|
|
26489
26504
|
];
|
|
26490
26505
|
var automationProjectRoot2 = () => process.env.VYBEKIIT_PROJECT_ROOT || process.cwd();
|
|
26491
|
-
var
|
|
26506
|
+
var uiCatalogIndexPaths = () => {
|
|
26492
26507
|
const configuredCatalogPath = process.env.VYBEKIIT_UI_CATALOG_PATH;
|
|
26493
26508
|
if (configuredCatalogPath) {
|
|
26494
|
-
return configuredCatalogPath;
|
|
26509
|
+
return [configuredCatalogPath];
|
|
26495
26510
|
}
|
|
26496
|
-
|
|
26511
|
+
const projectRoot = automationProjectRoot2();
|
|
26512
|
+
return [
|
|
26513
|
+
join35(projectRoot, ".vybekiit/agent/ui-catalog-index.json"),
|
|
26514
|
+
join35(projectRoot, "templates/web/.vybekiit/agent/ui-catalog-index.json")
|
|
26515
|
+
];
|
|
26497
26516
|
};
|
|
26498
26517
|
var cachedCatalog;
|
|
26499
26518
|
var loadUiCatalog = async () => {
|
|
26500
|
-
const
|
|
26501
|
-
|
|
26519
|
+
const catalogPaths = uiCatalogIndexPaths();
|
|
26520
|
+
const cached = catalogPaths.find((candidatePath) => cachedCatalog?.path === candidatePath);
|
|
26521
|
+
if (cached !== void 0 && cachedCatalog !== void 0) {
|
|
26502
26522
|
return cachedCatalog.catalog;
|
|
26503
26523
|
}
|
|
26524
|
+
const catalogReads = await Promise.allSettled(
|
|
26525
|
+
catalogPaths.map((candidatePath) => readFile18(candidatePath, "utf8"))
|
|
26526
|
+
);
|
|
26527
|
+
const availableIndex = catalogReads.findIndex(
|
|
26528
|
+
(candidateRead) => candidateRead.status === "fulfilled"
|
|
26529
|
+
);
|
|
26530
|
+
if (availableIndex === -1) {
|
|
26531
|
+
const [firstFailure] = catalogReads;
|
|
26532
|
+
const reason = firstFailure?.status === "rejected" ? firstFailure.reason : "Catalog not found";
|
|
26533
|
+
return { error: reason instanceof Error ? reason.message : String(reason) };
|
|
26534
|
+
}
|
|
26535
|
+
const catalogRead = catalogReads[availableIndex];
|
|
26536
|
+
const catalogPath = catalogPaths[availableIndex];
|
|
26537
|
+
if (catalogRead?.status !== "fulfilled" || catalogPath === void 0) {
|
|
26538
|
+
return { error: "Catalog not found" };
|
|
26539
|
+
}
|
|
26504
26540
|
try {
|
|
26505
|
-
const
|
|
26506
|
-
const catalog = loadCatalog(json);
|
|
26541
|
+
const catalog = loadCatalog(catalogRead.value);
|
|
26507
26542
|
cachedCatalog = { path: catalogPath, catalog };
|
|
26508
26543
|
return catalog;
|
|
26509
26544
|
} catch (error) {
|
|
@@ -9,6 +9,8 @@ license: MIT
|
|
|
9
9
|
|
|
10
10
|
For routes, links, stacks, tabs, modals, sheets, and headers, use the `expo-router` skill.
|
|
11
11
|
|
|
12
|
+
> **Before picking any UI component, check `expo-ui` first.** `@expo/ui` provides native equivalents — BottomSheet, Button, Picker, Slider, Menu, Section, Switch, SegmentedControl, and more — rendered as real SwiftUI on iOS and Jetpack Compose on Android, available in Expo Go on SDK 56+ with no custom build. Load the **`expo-ui`** skill to find the right component before falling back to React Native built-ins or community libraries. This skill (`expo-native-ui`) covers the surrounding structure: Expo Router navigation, layout, styling, and animations.
|
|
13
|
+
|
|
12
14
|
## References
|
|
13
15
|
|
|
14
16
|
Consult these resources as needed:
|
|
@@ -65,6 +67,7 @@ Expo Go supports a huge range of features out of the box:
|
|
|
65
67
|
|
|
66
68
|
## Library Preferences
|
|
67
69
|
|
|
70
|
+
- **For any sheet, picker, slider, toggle, menu, or grouped-form section: use `@expo/ui` (see `expo-ui` skill) before reaching for a React Native built-in or community library** — it renders native SwiftUI/Compose and works in Expo Go on SDK 56+. For grouped/settings-style rows (short, fixed-length), use `@expo/ui`'s `List` + `ListItem`. For large or unknown-length scrolling lists (feeds, search results, catalogs), use `FlatList` or `FlashList` — `@expo/ui`'s `List` is not virtualized.
|
|
68
71
|
- Never use modules removed from React Native such as Picker, WebView, SafeAreaView, or AsyncStorage
|
|
69
72
|
- Never use legacy expo-permissions
|
|
70
73
|
- `expo-audio` not `expo-av`
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Native iOS controls provide built-in haptics, accessibility, and platform-appropriate styling.
|
|
4
4
|
|
|
5
|
+
> **Prefer `@expo/ui` for these controls.** Its `Slider`, `Switch`, `DateTimePicker`, `Menu`, and segmented pickers render as real SwiftUI / Jetpack Compose and follow platform design conventions automatically — recommended over the React Native controls below. See the **`expo-ui`** skill; use the React Native controls below as a fallback when you're not using `@expo/ui`.
|
|
6
|
+
|
|
5
7
|
## Switch
|
|
6
8
|
|
|
7
9
|
Use for binary on/off settings. Has built-in haptics.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: expo-overview
|
|
3
|
+
description: "Framework (OSS). Entry point and router for every Expo or EAS task. Load this skill first — before writing code and before choosing another expo-* / eas-* skill — when the request, PRD, or spec mentions Expo, EAS, Expo Go, or an expo-* package, or the project has an `expo` dependency in `package.json`. Within that gate it also covers app specs and designs to implement (tabs, stacks, maps, lists, navigation, building from a screenshot), and phrasings like 'implement a mobile app', 'make my app look native', 'add navigation', 'fetch some data', 'upgrade my SDK', 'add Expo to my existing native app', 'ship to the App Store', or 'I'm new to Expo, where do I start'. A fully specified request (SDK pinned, libraries named, layout given) still routes through here — the shared setup rules still apply. Do NOT load it when neither signal is present: a bare React Native project with no `expo` dependency is not Expo work. Detects the real goal, routes to the right expo-* / eas-* skill, and owns the shared setup rules."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
license: MIT
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# `expo-overview` — router & shared rules for Expo / EAS
|
|
9
|
+
|
|
10
|
+
## Start Here — read before doing anything
|
|
11
|
+
|
|
12
|
+
**Do not guess the skill from project files alone.** Many Expo goals look similar from
|
|
13
|
+
the filesystem but need different skills.
|
|
14
|
+
|
|
15
|
+
1. **Confirm this is Expo work** — the request mentions Expo, or `package.json` has an
|
|
16
|
+
`expo` dependency. If neither holds, stop: this skill does not apply. A bare React
|
|
17
|
+
Native project with no `expo` dependency is not Expo work.
|
|
18
|
+
2. **Read the user's goal** — what outcome do they want, in plain terms?
|
|
19
|
+
3. **Classify it** using the Skill Map below, translating casual phrasing to a goal.
|
|
20
|
+
4. **Confirm intent** if ambiguous ("Sounds like you want to ship to the stores — that's
|
|
21
|
+
`eas-app-stores`. Right?"), then load that skill's `SKILL.md` and follow it.
|
|
22
|
+
5. **Trust the leaf skill** — it has its own detection logic and steps. Don't improvise.
|
|
23
|
+
|
|
24
|
+
## Skill Map (by goal)
|
|
25
|
+
|
|
26
|
+
Match the goal to a category, then the skill, then load that leaf's `SKILL.md`.
|
|
27
|
+
|
|
28
|
+
**Build the app**
|
|
29
|
+
- `expo-project-structure` — folder layout for a **new** Expo Router project: where screens, components, and config live (never restructure an existing app to match)
|
|
30
|
+
- `expo-native-ui` — screens, styling, semantic colors, native controls, SF Symbols, media, animations, layout
|
|
31
|
+
- `expo-router` — navigation: file-based routes, tabs / stacks / modals / sheets, links, headers
|
|
32
|
+
- `expo-animation` — motion and gestures: Reanimated worklets, Gesture Handler, screen transitions, sheet and press feedback, haptics, and fixing animation that stutters on device
|
|
33
|
+
- `expo-ui` — native UI components via `@expo/ui`: BottomSheet, Picker, Slider, Switch, Menu, Button, FieldGroup (grouped form sections), List / ListItem, and more — real SwiftUI on iOS, Jetpack Compose on Android. The universal layer needs SDK 56+ and runs in Expo Go; the drop-in replacements (`@gorhom/bottom-sheet`, `datetimepicker`, …) and platform-specific layers also exist on SDK 55.
|
|
34
|
+
- `expo-design-system` — one visual source of truth: design tokens (color, spacing, typography, radius, shadow, motion), reusable component conventions, and audits for drift (hardcoded colors, spacing, fonts)
|
|
35
|
+
- `expo-tailwind-setup` — Tailwind / NativeWind styling
|
|
36
|
+
- `expo-data-fetching` — network requests, React Query / SWR, caching, offline, route loaders
|
|
37
|
+
- `expo-dom` — run web code or reuse a web library inside native
|
|
38
|
+
- `expo-web-to-native` — migrate an existing web / React app to a native iOS / Android app
|
|
39
|
+
|
|
40
|
+
> **Component selection rule:** whenever you need a UI component (list rows, bottom sheets, pickers, sliders, menus, buttons, segmented controls, toggles), **consult `expo-ui` first** to check whether `@expo/ui` has a native equivalent before reaching for a React Native built-in or a community library. Native `@expo/ui` components give the best platform fit, and on SDK 56+ the universal ones run in Expo Go with no custom build. Load `expo-ui` alongside `expo-native-ui` for any app that renders lists, detail sheets, or form controls. One exception: `@expo/ui` `List` renders native grouped rows (an iOS Settings screen), **not** a virtualized list — use `FlatList` / `FlashList` for large datasets.
|
|
41
|
+
|
|
42
|
+
**Ship & operate**
|
|
43
|
+
- `eas-app-stores` — build and submit to the App Store / Play Store / TestFlight, versions, and store metadata
|
|
44
|
+
- `eas-hosting` — deploy the web bundle to EAS Hosting; also author Expo Router API routes (`+api.ts` handlers) and their environments / domains
|
|
45
|
+
- `eas-workflows` — EAS Workflow YAML and CI/CD pipelines
|
|
46
|
+
- `eas-simulator` — run and drive the app on a remote iOS / Android simulator on EAS cloud
|
|
47
|
+
- `expo-dev-client` — custom development builds
|
|
48
|
+
- `eas-update-insights` — OTA update health: crash rate, adoption, payload size
|
|
49
|
+
- `eas-observe` — startup / launch / TTI performance with EAS Observe
|
|
50
|
+
|
|
51
|
+
**Extend natively**
|
|
52
|
+
- `expo-module` — native modules and views (Swift / Kotlin) with the Expo Modules API
|
|
53
|
+
- `expo-brownfield` — embed Expo / React Native in an existing native app
|
|
54
|
+
- `expo-app-clip` — iOS App Clip target (AASA, smart app banner)
|
|
55
|
+
|
|
56
|
+
**Maintain & learn**
|
|
57
|
+
- `expo-upgrade` — upgrade the Expo SDK and fix dependency conflicts
|
|
58
|
+
- `expo-examples` — canonical, version-matched integration examples (Stripe, Clerk, Supabase, …)
|
|
59
|
+
- `expo-skill-feedback` — send feedback on an Expo skill or on Expo itself; enable / disable the anonymous usage telemetry
|
|
60
|
+
|
|
61
|
+
### Translating vague asks
|
|
62
|
+
|
|
63
|
+
Some everyday phrasings don't obviously map to a skill name — translate before routing:
|
|
64
|
+
|
|
65
|
+
- "Make it look native" → grouped controls / settings forms = `expo-ui`; screens, styling, animations = `expo-native-ui`; navigation = `expo-router`.
|
|
66
|
+
- "Make the screens consistent" / "clean up the styling" / "set up a theme or design tokens" → `expo-design-system`.
|
|
67
|
+
- "Ship it" / "get an .ipa or .apk" / "release to the stores" → `eas-app-stores` (build + submit, TestFlight, versions, store metadata).
|
|
68
|
+
- "I'm new / where do I start" → scaffold first (see Shared setup rules), then route by goal.
|
|
69
|
+
|
|
70
|
+
## Shared setup rules
|
|
71
|
+
|
|
72
|
+
These apply across every Expo skill, so handle them here once instead of repeating them
|
|
73
|
+
in each leaf.
|
|
74
|
+
|
|
75
|
+
- **No Expo project yet?** Start one the standard way before routing to a feature skill:
|
|
76
|
+
`npx create-expo-app@latest`, laying out folders per `expo-project-structure`. Then
|
|
77
|
+
classify the user's goal and route.
|
|
78
|
+
- **Detect the SDK version** before giving version-specific advice: read the `expo`
|
|
79
|
+
version in `package.json` (and `app.json` / `app.config.{js,ts}`). Many APIs and
|
|
80
|
+
defaults differ by SDK.
|
|
81
|
+
- **Read the docs for that SDK, not `latest`.** Use the version-pinned URL, e.g.
|
|
82
|
+
`https://docs.expo.dev/versions/v56.0.0/sdk/ui/` on SDK 56 instead of
|
|
83
|
+
`https://docs.expo.dev/versions/latest/sdk/ui/` — the `latest` pages track the newest
|
|
84
|
+
SDK and can document APIs the project does not have yet.
|
|
85
|
+
- **Moving to a newer SDK is its own task** — load `expo-upgrade` instead of bumping
|
|
86
|
+
versions by hand.
|
|
87
|
+
- **Managed vs. bare/prebuild**: the presence of committed `ios/` and `android/`
|
|
88
|
+
directories means native projects exist (prebuild or bare). Config-plugin and
|
|
89
|
+
native-setup steps differ — note which one the project is in.
|
|
90
|
+
- **Install packages with `npx expo install <pkg>`**, not raw `npm`/`yarn`/`pnpm add`,
|
|
91
|
+
so versions stay compatible with the project's SDK.
|
|
92
|
+
- **EAS auth & linking** (only needed for build/submit/update/observe/workflows): check
|
|
93
|
+
login with `eas whoami`, log in with `eas login`. A project is linked when
|
|
94
|
+
`extra.eas.projectId` exists in the app config; create it with `eas init` if missing.
|
|
95
|
+
|
|
96
|
+
## When to skip the router hop
|
|
97
|
+
|
|
98
|
+
- Only when the user explicitly named a specific `expo-*` / `eas-*` skill → load that
|
|
99
|
+
skill directly.
|
|
100
|
+
- A fully-specified task (SDK version pinned, file layout given, libraries named) is
|
|
101
|
+
**not** a reason to skip: the shared rules above still apply — check them, then route
|
|
102
|
+
to the matching leaf skill.
|
|
103
|
+
|
|
104
|
+
## Submitting Feedback
|
|
105
|
+
If you encounter errors, misleading or outdated information in this skill, report it so Expo can improve:
|
|
106
|
+
```bash
|
|
107
|
+
npx --yes submit-expo-feedback@latest --category skills --subject "expo-overview" "<actionable feedback>"
|
|
108
|
+
```
|
|
109
|
+
Only submit when you have something specific and actionable to report. Include as much relevant context as possible.
|
|
110
|
+
If an AI agent repeatedly failed or the user had to take over an Expo task, load the expo-skill-feedback skill and follow its eval-candidate flow instead of reusing the command above.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Expo Overview"
|
|
3
|
+
short_description: "Entry point and router for Expo / EAS tasks: load first when the request mentions Expo or the project has an expo dependency, classify the goal, route to the right expo-* / eas-* skill, and apply shared setup rules"
|
|
4
|
+
default_prompt: "Use $expo-overview first when a task mentions Expo, EAS, or an expo-* package, or the project has an `expo` dependency in package.json — even when the stack or SDK version is already fully specified. Classify the user's goal, route to the right expo-* / eas-* skill, and apply the shared environment and setup rules the other Expo skills rely on."
|
|
@@ -13,10 +13,9 @@ const path = require("path");
|
|
|
13
13
|
|
|
14
14
|
const POSTHOG_HOST = "https://us.i.posthog.com";
|
|
15
15
|
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
const POSTHOG_PROJECT_API_KEY = process.env.EXPO_SKILLS_POSTHOG_KEY || "";
|
|
16
|
+
// Telemetry stays disabled unless the buyer explicitly enables it and supplies
|
|
17
|
+
// a project ingestion key. Never bundle a project or personal key in the kit.
|
|
18
|
+
const POSTHOG_PROJECT_API_KEY = process.env.EXPO_SKILLS_POSTHOG_KEY;
|
|
20
19
|
|
|
21
20
|
const SOURCE = "expo-skills";
|
|
22
21
|
const INSTALLATION_ID_PATH = path.join(os.homedir(), ".expo-skills", "installation-id");
|
|
@@ -77,10 +76,11 @@ function telemetryActive() {
|
|
|
77
76
|
return DEFAULT_ON;
|
|
78
77
|
}
|
|
79
78
|
|
|
80
|
-
//
|
|
79
|
+
// A real key ships in this file, so this check passes by default. This guard only
|
|
80
|
+
// makes the scripts inert if someone strips the key (e.g. a fork or private build).
|
|
81
81
|
function telemetryConfigured() {
|
|
82
82
|
const key = String(POSTHOG_PROJECT_API_KEY || "").trim();
|
|
83
|
-
return key.length > 0;
|
|
83
|
+
return key.length > 0 && key !== "phc_REPLACE_ME";
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// Best-effort agent-harness label for the event (default when --agent-harness isn't passed).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: expo-ui
|
|
3
|
-
description: "Framework (OSS). Build native UI with the @expo/ui package: real SwiftUI on iOS and Jetpack Compose on Android
|
|
3
|
+
description: "Framework (OSS). Build native UI with the @expo/ui package: real SwiftUI on iOS and Jetpack Compose on Android. Default to @expo/ui for sheets (BottomSheet), pickers, sliders, toggles, menus, and grouped-form sections — do NOT reach for Reanimated, @gorhom/bottom-sheet, or RN built-in Picker/Switch; use @expo/ui instead. Fall back to RN built-ins only when @expo/ui is missing the component. NOTE: @expo/ui List renders native grouped rows like an iOS Settings screen — it is NOT a virtualized list; use FlatList/FlashList for large datasets. Covers universal components (Host, Column, Row, Button, Text, List, BottomSheet, FieldGroup, Switch, Slider, Picker, Menu), drop-in replacements for RN community libraries, and platform-specific SwiftUI/Jetpack Compose trees. Not for Expo Router navigation, Reanimated, or data fetching."
|
|
4
4
|
version: 1.0.0
|
|
5
5
|
license: MIT
|
|
6
6
|
allowed-tools: "Bash(node *expo-ui/scripts/list-components.js *)"
|
|
@@ -8,9 +8,9 @@ allowed-tools: "Bash(node *expo-ui/scripts/list-components.js *)"
|
|
|
8
8
|
|
|
9
9
|
# Expo UI (`@expo/ui`)
|
|
10
10
|
|
|
11
|
-
`@expo/ui` renders real native UI from React: SwiftUI on iOS, Jetpack Compose on Android.
|
|
11
|
+
`@expo/ui` renders real native UI from React: SwiftUI on iOS, Jetpack Compose on Android. It also ships drop-in replacements for migrating off RN community UI libraries.
|
|
12
12
|
|
|
13
|
-
> These instructions track the latest Expo SDK. The **universal** layer requires **SDK 56
|
|
13
|
+
> These instructions track the latest Expo SDK. The **universal** layer requires **SDK 56+** and works in Expo Go — no custom build needed. Drop-in replacements and the platform-specific layers also exist on SDK 55. For component details on a specific SDK, refer to the Expo UI docs for that version.
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
@@ -18,11 +18,57 @@ allowed-tools: "Bash(node *expo-ui/scripts/list-components.js *)"
|
|
|
18
18
|
npx expo install @expo/ui
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
On SDK 56, `@expo/ui` works in Expo Go, so `npx expo start` runs it directly — no custom build required. On older SDKs, build a dev client first (`npx expo run:ios` / `npx expo run:android`).
|
|
22
|
-
|
|
23
21
|
Every `@expo/ui` tree — universal or platform-specific — must be wrapped in `Host`.
|
|
24
22
|
|
|
25
|
-
##
|
|
23
|
+
## Use @expo/ui by default — don't reach for RN alternatives first
|
|
24
|
+
|
|
25
|
+
**Before using Reanimated, `@gorhom/bottom-sheet`, React Native's built-in `Switch`/`Picker`, or any community UI library for the items below, use `@expo/ui` instead.** Only fall back to RN built-ins when `@expo/ui` is missing the component.
|
|
26
|
+
|
|
27
|
+
| Need | Use |
|
|
28
|
+
|------|-----|
|
|
29
|
+
| Slide-up sheet / bottom sheet | `BottomSheet` from `@expo/ui` — **not** Reanimated or `@gorhom/bottom-sheet` |
|
|
30
|
+
| Grouped native list rows (settings/form-style) | `List` + `ListItem` from `@expo/ui` — **not** `FlatList` (see note below) |
|
|
31
|
+
| Toggle | `Switch` from `@expo/ui` |
|
|
32
|
+
| Slider | `Slider` from `@expo/ui` |
|
|
33
|
+
| Date/time picker | `@expo/ui/community/datetimepicker` |
|
|
34
|
+
| Menu | `Menu` from `@expo/ui` |
|
|
35
|
+
| Form section with label | `FieldGroup` from `@expo/ui` |
|
|
36
|
+
| Collapsible section | `Collapsible` from `@expo/ui` |
|
|
37
|
+
|
|
38
|
+
> **`List` is NOT a virtualized scrolling list.** It renders native grouped table rows — the visual look of an iOS Settings screen or a form section, with disclosure indicators and native row styling. Each `ListItem` is a native node on the JS thread; rows are not recycled. For any list with large or unknown-length data (feeds, search results, catalogs), use **`FlatList`** or **`FlashList`** instead. `List` is the right choice for short, fixed-length groups: a settings screen, a detail panel's rows, a fixed menu.
|
|
39
|
+
|
|
40
|
+
**`BottomSheet` example** (use this for map pin details, action sheets, detail panels — not Reanimated):
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { Host, BottomSheet, Column, Text } from '@expo/ui';
|
|
44
|
+
import { useState } from 'react';
|
|
45
|
+
|
|
46
|
+
export default function MapScreen() {
|
|
47
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<View style={{ flex: 1 }}>
|
|
51
|
+
<MapView onMarkerPress={() => setIsOpen(true)} />
|
|
52
|
+
<Host>
|
|
53
|
+
<BottomSheet
|
|
54
|
+
isPresented={isOpen}
|
|
55
|
+
onDismiss={() => setIsOpen(false)}
|
|
56
|
+
snapPoints={['half', 'full']}
|
|
57
|
+
>
|
|
58
|
+
<Column>
|
|
59
|
+
<Text>Café name</Text>
|
|
60
|
+
<Text>Address</Text>
|
|
61
|
+
</Column>
|
|
62
|
+
</BottomSheet>
|
|
63
|
+
</Host>
|
|
64
|
+
</View>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`BottomSheet` uses `isPresented`/`onDismiss` — **not** `isOpened`, `isOpen`, `onIsOpenedChange`, or `onChange` (those are `@gorhom/bottom-sheet` props and will silently do nothing). `snapPoints` accepts `'half'`, `'full'`, `{ fraction: 0.5 }`, or `{ height: 400 }` and is optional (auto-sizes to content when omitted).
|
|
70
|
+
|
|
71
|
+
## Choosing an approach
|
|
26
72
|
|
|
27
73
|
Work down this list and stop at the first layer that meets the need:
|
|
28
74
|
|
|
@@ -61,6 +61,37 @@ export default function MyInput() {
|
|
|
61
61
|
|
|
62
62
|
Docs — https://docs.expo.dev/versions/latest/sdk/ui/universal/textinput/index.md
|
|
63
63
|
|
|
64
|
+
## BottomSheet
|
|
65
|
+
|
|
66
|
+
`BottomSheet` is a universal slide-up sheet. Control it with `isPresented` / `onDismiss` — **not** `isOpen`, `isOpened`, `onIsOpenedChange`, or `onChange` (those belong to other sheet APIs; the universal `BottomSheet` does not accept them). `snapPoints` is optional and accepts `'half'`, `'full'`, `{ fraction }`, or `{ height }`; when omitted the sheet auto-sizes to its content.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { Host, BottomSheet, Column, Button, Text } from '@expo/ui';
|
|
70
|
+
import { useState } from 'react';
|
|
71
|
+
|
|
72
|
+
export default function MapScreen() {
|
|
73
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Host>
|
|
77
|
+
<Button onPress={() => setIsOpen(true)}>Show details</Button>
|
|
78
|
+
<BottomSheet
|
|
79
|
+
isPresented={isOpen}
|
|
80
|
+
onDismiss={() => setIsOpen(false)}
|
|
81
|
+
snapPoints={['half', 'full']}
|
|
82
|
+
>
|
|
83
|
+
<Column>
|
|
84
|
+
<Text>Sheet content</Text>
|
|
85
|
+
<Button onPress={() => setIsOpen(false)}>Close</Button>
|
|
86
|
+
</Column>
|
|
87
|
+
</BottomSheet>
|
|
88
|
+
</Host>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
> **Don't confuse the universal `BottomSheet` with the drop-in `@gorhom/bottom-sheet` replacement** (`@expo/ui/community/bottom-sheet`). They are different components with different APIs. Use the universal one when building new UI; use the drop-in only when migrating an existing `@gorhom/bottom-sheet` integration. See `./drop-in-replacements.md`.
|
|
94
|
+
|
|
64
95
|
## Confirming the API
|
|
65
96
|
|
|
66
97
|
`@expo/ui` is versioned with the Expo SDK (e.g. `56.0.x` for SDK 56) and its API can change between SDK versions, so the **installed package's TypeScript types (`.d.ts`) are the most reliable source of truth** — they match the version in your project, while the docs track latest. Read the relevant component's `.d.ts` from the installed `@expo/ui` package in `node_modules`. Use the docs as the human-readable reference:
|
|
@@ -143,6 +143,10 @@ Copy page
|
|
|
143
143
|
| [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
|
|
144
144
|
| [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |
|
|
145
145
|
|
|
146
|
+
### Still have questions?
|
|
147
|
+
|
|
148
|
+
Ask PostHog AI
|
|
149
|
+
|
|
146
150
|
### Was this page useful?
|
|
147
151
|
|
|
148
152
|
HelpfulCould be better
|
|
@@ -191,6 +191,10 @@ Copy page
|
|
|
191
191
|
| [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
|
|
192
192
|
| [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |
|
|
193
193
|
|
|
194
|
+
### Still have questions?
|
|
195
|
+
|
|
196
|
+
Ask PostHog AI
|
|
197
|
+
|
|
194
198
|
### Was this page useful?
|
|
195
199
|
|
|
196
200
|
HelpfulCould be better
|
|
@@ -228,6 +228,10 @@ Stale flags are the most common source of unnecessary cost. Beyond cleaning up f
|
|
|
228
228
|
- [Local evaluation](/docs/feature-flags/local-evaluation.md) – server-side evaluation for explicit input control
|
|
229
229
|
- [Bootstrapping](/docs/feature-flags/bootstrapping.md) – having flag values before the page renders
|
|
230
230
|
|
|
231
|
+
### Still have questions?
|
|
232
|
+
|
|
233
|
+
Ask PostHog AI
|
|
234
|
+
|
|
231
235
|
### Was this page useful?
|
|
232
236
|
|
|
233
237
|
HelpfulCould be better
|
|
@@ -291,6 +291,10 @@ Everything on this page works the same way on `6.9.3`. Event capture, the contex
|
|
|
291
291
|
|
|
292
292
|
Later `7.x` releases add what the 6.x line does not receive, such as the Celery integration, tracing header sanitization, and `set_context_device_id`. They also changed the middleware's own captured properties: `7.x` sends the request IP as `$ip`, where `6.9.3` sends it as `$ip_address`, and `7.x` additionally captures `$request_path`, `$raw_user_agent`, and the authenticated user's `email`.
|
|
293
293
|
|
|
294
|
+
### Still have questions?
|
|
295
|
+
|
|
296
|
+
Ask PostHog AI
|
|
297
|
+
|
|
294
298
|
### Was this page useful?
|
|
295
299
|
|
|
296
300
|
HelpfulCould be better
|
|
@@ -764,6 +764,10 @@ By default, the library buffers events before sending them to the `/batch` endpo
|
|
|
764
764
|
|
|
765
765
|
To avoid this, call `await posthog.FlushAsync()` after processing every request by adding it as a middleware to your server. This allows `posthog.Capture()` to remain asynchronous for better performance.
|
|
766
766
|
|
|
767
|
+
### Still have questions?
|
|
768
|
+
|
|
769
|
+
Ask PostHog AI
|
|
770
|
+
|
|
767
771
|
### Was this page useful?
|
|
768
772
|
|
|
769
773
|
HelpfulCould be better
|
|
@@ -44,6 +44,10 @@ Optionally, you might want to enable the [Plug integration](https://hexdocs.pm/p
|
|
|
44
44
|
|
|
45
45
|
For a test environment, you can pass in `test_mode: true` value to the config. This causes events to be dropped instead of sent to PostHog.
|
|
46
46
|
|
|
47
|
+
### Still have questions?
|
|
48
|
+
|
|
49
|
+
Ask PostHog AI
|
|
50
|
+
|
|
47
51
|
### Was this page useful?
|
|
48
52
|
|
|
49
53
|
HelpfulCould be better
|
|
@@ -138,6 +138,10 @@ Everything on this page works the same way on `6.9.3`. Event capture, the contex
|
|
|
138
138
|
|
|
139
139
|
Later `7.x` releases add what the 6.x line does not receive, such as the Celery integration, tracing header sanitization, and `set_context_device_id`. They also changed the middleware's own captured properties: `7.x` sends the request IP as `$ip`, where `6.9.3` sends it as `$ip_address`, and `7.x` additionally captures `$request_path`, `$raw_user_agent`, and the authenticated user's `email`.
|
|
140
140
|
|
|
141
|
+
### Still have questions?
|
|
142
|
+
|
|
143
|
+
Ask PostHog AI
|
|
144
|
+
|
|
141
145
|
### Was this page useful?
|
|
142
146
|
|
|
143
147
|
HelpfulCould be better
|
|
@@ -209,6 +209,10 @@ Copy page
|
|
|
209
209
|
| [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
|
|
210
210
|
| [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |
|
|
211
211
|
|
|
212
|
+
### Still have questions?
|
|
213
|
+
|
|
214
|
+
Ask PostHog AI
|
|
215
|
+
|
|
212
216
|
### Was this page useful?
|
|
213
217
|
|
|
214
218
|
HelpfulCould be better
|
|
@@ -205,6 +205,10 @@ Copy page
|
|
|
205
205
|
| [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
|
|
206
206
|
| [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |
|
|
207
207
|
|
|
208
|
+
### Still have questions?
|
|
209
|
+
|
|
210
|
+
Ask PostHog AI
|
|
211
|
+
|
|
208
212
|
### Was this page useful?
|
|
209
213
|
|
|
210
214
|
HelpfulCould be better
|
|
@@ -143,6 +143,10 @@ Copy page
|
|
|
143
143
|
| [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
|
|
144
144
|
| [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |
|
|
145
145
|
|
|
146
|
+
### Still have questions?
|
|
147
|
+
|
|
148
|
+
Ask PostHog AI
|
|
149
|
+
|
|
146
150
|
### Was this page useful?
|
|
147
151
|
|
|
148
152
|
HelpfulCould be better
|
|
@@ -444,6 +444,10 @@ To improve the reliability of client-side tracking and make requests less likely
|
|
|
444
444
|
- [How to set up Next.js pages router analytics, feature flags, and more](/tutorials/nextjs-pages-analytics.md)
|
|
445
445
|
- [How to set up Next.js A/B tests](/tutorials/nextjs-ab-tests.md)
|
|
446
446
|
|
|
447
|
+
### Still have questions?
|
|
448
|
+
|
|
449
|
+
Ask PostHog AI
|
|
450
|
+
|
|
447
451
|
### Was this page useful?
|
|
448
452
|
|
|
449
453
|
HelpfulCould be better
|
|
@@ -213,6 +213,10 @@ Copy page
|
|
|
213
213
|
| [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
|
|
214
214
|
| [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |
|
|
215
215
|
|
|
216
|
+
### Still have questions?
|
|
217
|
+
|
|
218
|
+
Ask PostHog AI
|
|
219
|
+
|
|
216
220
|
### Was this page useful?
|
|
217
221
|
|
|
218
222
|
HelpfulCould be better
|
|
@@ -184,6 +184,10 @@ Copy page
|
|
|
184
184
|
| [How to do a phased rollout](/tutorials/phased-rollout.md) | Gradually roll out features to minimize risk |
|
|
185
185
|
| [More tutorials](/docs/feature-flags/tutorials.md) | Other real-world examples and use cases |
|
|
186
186
|
|
|
187
|
+
### Still have questions?
|
|
188
|
+
|
|
189
|
+
Ask PostHog AI
|
|
190
|
+
|
|
187
191
|
### Was this page useful?
|
|
188
192
|
|
|
189
193
|
HelpfulCould be better
|