Skip to content

feat(react-native-example): add in-tree example app for @knocklabs/react-native#976

Open
webbjordy wants to merge 4 commits intomainfrom
jw-kno-12856-rn-example-app-scaffold
Open

feat(react-native-example): add in-tree example app for @knocklabs/react-native#976
webbjordy wants to merge 4 commits intomainfrom
jw-kno-12856-rn-example-app-scaffold

Conversation

@webbjordy
Copy link
Copy Markdown

@webbjordy webbjordy commented Apr 22, 2026

Description

Every other client SDK ships with an in-tree example app. React Native didn't — the previous one was removed in #629 and never replaced. That gap was the structural reason developers kept getting stuck on RN setup (KNO-11408) and blocked downstream docs work that needed something to point at. This PR adds a new example at examples/react-native-example/ with the same six screens as the Android (knocklabs/knock-android/knock-example-app/) and iOS (knocklabs/ios-example-app) demos: Startup, Sign in, Main (with the prebuilt NotificationFeed), Compose, Preferences, Tenant switcher.

Bare RN is still the right target for @knocklabs/react-native's audience even though Expo is the React Native default — expo-example covers Expo, this covers bare. The "doesn't run anymore" concern from #629 is real; CI on this workspace is a fast follow-up so it doesn't bit-rot the same way. Docs change in knocklabs/docs to follow.

  • Pinned to RN 0.83.4 to match expo-example and pass manypkg.
  • Push device-token registration is a follow-up. Provider is wired, but APNs and FCM setup needs account-level work.
  • react-native-svg and react-native-get-random-values are direct deps because bare RN's iOS autolinking won't pick up transitive native modules.

Checklist

  • Tests have been added for new features or major refactors to existing features.

No unit tests — examples in this monorepo aren't covered by vitest. Validated by:

  • yarn install, yarn build:packages, and yarn workspace @knocklabs/react-native-example run type:check all pass.
  • Metro bundles via yarn exec react-native bundle --platform ios.
  • pod install autolinks all four native modules.
  • Launched on iPhone 17 Pro simulator. Walked the full flow: sign-in, feed renders with workflows triggered from the dashboard, preferences toggle persists, tenant switcher updates feed scope.

Linear: KNO-12856

webbjordy and others added 2 commits April 22, 2026 15:10
…arn workspace

Adds a bare React Native 0.83.4 app at examples/react-native-example, wired into the monorepo via yarn workspaces. Metro is configured for workspace hoisting (watchFolders + nodeModulesPaths + disableHierarchicalLookup) so the app resolves dependencies from the root node_modules. Versions are aligned with the rest of the repo (react ^19.2.5, babel/runtime ^7.28.6, etc.) per manypkg.

Drops the create-app boilerplate (jest tests, NewAppScreen, the default README) since this app uses vitest at the root and doesn't need its own tests. Prettier is wired to the shared @knocklabs/prettier-config so the source style matches the rest of the monorepo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…d README

Wires up React Navigation v7 native stack with six screens that match the parity spec: Startup, SignIn, Main, MessageCompose, Preferences, TenantSwitcher. Each screen is a real early-stage render that shows the eventual purpose of the screen (form fields for sign-in, channel toggles for preferences, tenant list, etc.) — not a "coming soon" placeholder.

Runtime configuration is hardcoded in src/config.ts behind an AppConfig type with TODO markers per field, matching the pattern used by the Android and iOS demos. Phase 2 will wire the screens to @knocklabs/react-native; Phase 1 keeps the SDK out so the scaffold can be reviewed independently.

README mirrors the expo-example README shape and disambiguates the two: this one demonstrates @knocklabs/react-native in a bare RN context, expo-example demonstrates @knocklabs/expo on Expo-managed.

KNO-12856

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linear
Copy link
Copy Markdown

linear Bot commented Apr 22, 2026

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 22, 2026

⚠️ No Changeset found

Latest commit: a8a7d4d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
javascript-ms-teams-connect-example Ready Ready Preview, Comment Apr 22, 2026 10:41pm
javascript-nextjs-example Ready Ready Preview, Comment Apr 22, 2026 10:41pm
javascript-slack-connect-example Ready Ready Preview, Comment Apr 22, 2026 10:41pm
javascript-slack-kit-example Ready Ready Preview, Comment Apr 22, 2026 10:41pm

Request Review

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

⚠️ JUnit XML file not found

The CLI was unable to find any JUnit XML files to upload.
For more help, visit our troubleshooting guide.

…roid/iOS demos

Adds @knocklabs/react-native as a workspace dependency along with the required peer (react-native-gesture-handler). Wraps the authed stack in KnockProvider + KnockPushNotificationProvider + KnockFeedProvider, gated by a small AuthContext that lifts user identity and tenant scope to the app root. Pre-auth screens (Startup, SignIn) live in a separate stack so the navigator structure makes the auth boundary obvious.

Realigns each screen against the Android (knocklabs/knock-android/knock-example-app) and iOS (knocklabs/ios-example-app) demos for parity:

- Config exports six flat KNOCK_* constants matching Android's Utils.kt shape, plus KNOCK_TENANT_A and KNOCK_TENANT_B for the iOS-style tenant switcher.
- Main embeds the prebuilt <NotificationFeed /> component so the in-app feed renders in real time.
- Compose shows the workflow trigger form and clears the field on send. The server-side trigger pattern is documented inline; clients can't trigger workflows directly because that requires the secret API key.
- Preferences uses usePreferences for live read/write of channel-type preferences and hosts the sign-out action.
- TenantSwitcher offers None / Tenant A / Tenant B; selecting one updates auth state and re-mounts KnockFeedProvider with the new tenant scope.

Knock packages must be built once (`yarn build:packages`) before type-checking or bundling, since the SDK exposes types from dist/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…olinking

@knocklabs/react-native pulls in react-native-svg and react-native-get-random-values as runtime deps. In a yarn workspace, those land in the hoisted root node_modules, and bare RN's iOS autolinking only walks the host app's direct dependencies — so the transitive native modules weren't getting linked into the Pods project. Declaring them explicitly here makes autolinking pick them up alongside react-native-gesture-handler and react-native-screens.

Also includes the regenerated Podfile.lock, Pods-touched Xcode project changes, and the .xcworkspace produced by `pod install`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a8a7d4d. Configure here.


export default function PreferencesScreen() {
const { signOut } = useAuth();
const { preferences, setPreferences, isLoading } = usePreferences();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preferences not scoped to active tenant

Medium Severity

usePreferences() is called without passing the active tenant, so preferences are always fetched and set globally even when a tenant is selected. The README claims the tenant switcher scopes both the feed and preferences, and the usePreferences hook accepts an options parameter with a tenant field. The current auth.tenant from useAuth() is available but never forwarded, causing a mismatch between the feed (which is tenant-scoped via defaultFeedOptions) and the preferences screen.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a8a7d4d. Configure here.

apiKey={KNOCK_API_KEY}
host={KNOCK_HOSTNAME}
user={{ id: auth.userId }}
logLevel="debug"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug log level hardcoded in provider

Low Severity

KnockProvider has logLevel="debug" hardcoded, which will produce verbose console output for anyone running the example. This looks like a development-time setting that was left in. Example apps are the first thing new users clone, and noisy debug logs can be confusing.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a8a7d4d. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant