Skip to content

Commit 1d2192b

Browse files
authored
Merge pull request #2 from AppGram/v1
Add Appgram RN skill for skills.sh
2 parents 5f72bb4 + 2bba4d0 commit 1d2192b

File tree

9 files changed

+467
-0
lines changed

9 files changed

+467
-0
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,3 +618,11 @@ import type {
618618
## License
619619

620620
MIT
621+
622+
## Skill install (skills.sh)
623+
624+
Want to reuse this SDK as a Codex/skills.sh skill? The skill lives at `skills/appgram-react-native-sdk`.
625+
626+
- Local install from this repo: `npx skills add . --skill appgram-react-native-sdk`
627+
- From GitHub: `npx skills add https://github.com/<owner>/<repo> --skill appgram-react-native-sdk`
628+
- Peer deps required in consuming projects: `@react-native-async-storage/async-storage`, `lucide-react-native`, `react-native-svg`, `react-native-markdown-display`, `react-native-render-html` (install after `@appgram/react-native`; run `npx pod-install` for iOS).
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Appgram React Native SDK skill (skills.sh)
2+
3+
Use this to pull the SDK guidance into Codex/skills.sh.
4+
5+
Install:
6+
- From this repo root: `npx skills add . --skill appgram-react-native-sdk`
7+
- From GitHub: `npx skills add https://github.com/<owner>/<repo> --skill appgram-react-native-sdk`
8+
9+
What’s inside:
10+
- `SKILL.md` instructions for integrating/maintaining `@appgram/react-native`
11+
- `agents/openai.yaml` display metadata
12+
- references for hooks, components, API client, platform setup, and snippets
13+
14+
Peer deps (for app integrators): `@react-native-async-storage/async-storage`, `lucide-react-native`, `react-native-svg`, `react-native-markdown-display`, `react-native-render-html` (run `npx pod-install` on iOS after installing).
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
name: appgram-react-native-sdk
3+
description: "Integrate or maintain the Appgram React Native SDK (@appgram/react-native): install peers, configure AppgramProvider, use built-in components/hooks for feedback, roadmap, releases, help center, support, surveys, blog, status, chat, apply theming, and run build/lint/docs tasks."
4+
---
5+
6+
# Appgram React Native SDK
7+
8+
## When to use
9+
- You need to embed Appgram feedback/roadmap/changelog/help/support/surveys/blog/status/chat in a React Native app.
10+
- You are wiring Appgram headless hooks into custom UI.
11+
- You are maintaining this SDK: build, lint, docs, publish, or debugging peer/native issues.
12+
13+
## Prerequisites
14+
- React Native ≥0.70, React 18, Metro; iOS requires CocoaPods, Android uses autolinking.
15+
- Peer deps: `@react-native-async-storage/async-storage`, `lucide-react-native`, `react-native-svg`, `react-native-markdown-display`, `react-native-render-html`.
16+
- Install peers after the SDK, then `npx pod-install` for iOS.
17+
18+
## Quick start
19+
- Install: `npm install @appgram/react-native` then peer deps `npm install @react-native-async-storage/async-storage lucide-react-native react-native-svg react-native-markdown-display react-native-render-html`.
20+
- iOS: run `npx pod-install` after installing peers.
21+
- Wrap your app once:
22+
```tsx
23+
<AppgramProvider config={{ projectId: 'YOUR_PROJECT_ID', orgSlug: 'org', projectSlug: 'project', apiUrl: 'https://api.appgram.dev', theme: { mode: 'system' } }}>
24+
{children}
25+
</AppgramProvider>
26+
```
27+
- Use ready UI or headless hooks:
28+
```tsx
29+
<WishList onWishPress={(wish) => console.log(wish)} />
30+
<SupportForm onSuccess={() => Alert.alert('Sent')} />
31+
// Hooks
32+
const { wishes, isLoading, refetch } = useWishes()
33+
const { vote } = useVote()
34+
```
35+
36+
## Feature map (components → hooks)
37+
- Feedback: `WishList`, `WishCard`, `VoteButton`, `WishDetailModal`, `SubmitWishSheet``useWishes`, `useVote`, `useComments`.
38+
- Roadmap: `RoadmapBoard``useRoadmap`.
39+
- Releases/Changelog: `Releases`, `ReleaseList`, `ReleaseDetail``useReleases`, `useRelease`.
40+
- Help Center: `HelpCenter`, `HelpFlowCard`, `HelpFlowDetail`, `HelpArticleCard`, `HelpArticleDetail``useHelpCenter`, `useHelpFlow`, `useHelpArticle`.
41+
- Support & Forms: `SupportForm`, `FormRenderer``useSupport`, `useForm`, `useFormSubmit`.
42+
- Surveys: `SurveyForm``useSurvey`, `useSurveySubmit`.
43+
- Blog: `Blog`, `BlogList`, `BlogCard`, `BlogPostDetail``useBlogPosts`, `useBlogPost`, `useBlogCategories`, `useFeaturedPosts`.
44+
- Status: `StatusBoard``useStatus`.
45+
- Chat: `ChatScreen` (`ChatSource` type available) – pull data via context client as needed.
46+
- Base UI bits: `Button`, `Card`, `Badge`, `Input` for consistent styling.
47+
48+
**Hook pattern:** hooks return data + `isLoading` (and often `error`, `refetch`); many accept `refreshInterval` and filter props (see exported option/result types).
49+
50+
### Props & options details
51+
- Hooks: see `references/hooks.md` (options, return shapes, behaviors like refreshInterval and fingerprinting).
52+
- Components: see `references/components.md` (purpose + key props per component).
53+
54+
## Configuration & theming
55+
- `AppgramProvider.config`:
56+
- `projectId` (required), `orgSlug`/`projectSlug` for routing.
57+
- `apiUrl` override for self-host/staging (default `https://api.appgram.dev`).
58+
- `enableFingerprinting` (default true) uses AsyncStorage + device info for anonymous votes.
59+
- `theme`: `mode` (`light`|`dark`|`system`), optional `lightColors`/`darkColors` partial overrides; defaults from Hazel design system.
60+
- Access context: `useAppgramContext()``{ client, config, fingerprint, theme }`.
61+
- Theming in custom UI: `useAppgramTheme()``{ colors, spacing, radius, typography, isDark, mode }`; palette exports `lightColors`, `darkColors`, scales `spacing`, `radius`, `typography` for reuse.
62+
63+
### Sample themed usage
64+
```tsx
65+
const { colors, spacing, radius } = useAppgramTheme()
66+
return (
67+
<Card style={{ backgroundColor: colors.background, padding: spacing.lg, borderRadius: radius.lg }}>
68+
<WishList submitButtonText=\"Suggest a feature\" />
69+
</Card>
70+
)
71+
```
72+
73+
## API client
74+
- Get the instantiated `AppgramClient` from context: `const { client } = useAppgramContext()`.
75+
- Methods mirror hooks (e.g., `client.getWishes`, `client.vote`, `client.getRoadmap`); responses follow `ApiResponse` / `PaginatedResponse` types exported from `types`.
76+
- Use when you need imperative flows (e.g., prefetch before navigation) or custom caching.
77+
78+
## Local development & maintenance (this repo)
79+
- Install dev deps: `npm install`.
80+
- Lint: `npm run lint`; typecheck: `npm run typecheck`.
81+
- Build package: `npm run build` (builder-bob, outputs to `lib/`); runs automatically on `npm install` via `prepare`.
82+
- Docs: `npm run docs:json` (typedoc) → `docs.json`; `npm run docs:transform` (uses `transform-docs.js`); `npm run docs:build` to do both.
83+
- Publish (when ready): `npm run release` (assumes npm auth + version bump). Keep `react-native-builder-bob` config in `package.json`; build uses `tsconfig.build.json`.
84+
85+
## Platform setup & debugging
86+
- Install order, pod install, Gradle check, cache clears, and platform notes: `references/platform-setup.md`.
87+
88+
## Common recipes
89+
- **Custom vote button:** use `useVote`; pass `onVote` to sync local counts; guard for missing fingerprint by showing a prompt to enable cookies/storage.
90+
- **Support with magic link:** use `useSupport`; call `requestMagicLink(email)` then `verifyToken(token)`; tickets also saved locally (`storedTickets`, `clearStoredTickets`).
91+
- **Embed changelog tab:** stack navigator screen with `Releases`; on press, navigate to detail screen wrapping `ReleaseDetail`.
92+
- **Anonymous wishlist:** keep `enableFingerprinting` on (default); if privacy requires, set false and disable voting UI.
93+
- **Blog index + detail:** `BlogList` for landing; use `useBlogPosts` if you need infinite scroll; route to `BlogPostDetail` on press.
94+
- **Status page banner:** call `useStatus({ slug, refreshInterval: 60000 })` and render a small inline banner with `data.status`.
95+
- See ready-to-paste code in `references/snippets.md`.
96+
97+
## Troubleshooting
98+
- Missing peer deps / native linking: ensure all peers installed; run `npx pod-install` for iOS; clear Metro cache if symbols missing.
99+
- Theming not applying: verify `theme.mode` not overridden by system; pass both light/dark overrides when customizing primary/background/foreground.
100+
- Anonymous voting blocked: set `enableFingerprinting=false` if fingerprint cannot be generated, or ensure AsyncStorage works in environment.
101+
- API errors: confirm `projectId`/slugs and `apiUrl`; use `client` methods to inspect `response.success` and `response.error`.
102+
- Version support: built for React Native ≥0.70 and React 18+. Ensure `react-native-svg` and `lucide-react-native` versions stay compatible.
103+
104+
## References (load on demand)
105+
- Hooks options/returns: `references/hooks.md`
106+
- Components props notes: `references/components.md`
107+
- API client methods + notes: `references/api-client.md`
108+
- Platform setup & debugging: `references/platform-setup.md`
109+
- Practical code snippets: `references/snippets.md`
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface:
2+
display_name: "Appgram RN SDK"
3+
short_description: "Use and maintain the Appgram React Native SDK."
4+
default_prompt: "Use when integrating or maintaining @appgram/react-native: install peers, wrap AppgramProvider, pick components/hooks, theme overrides, and run lint/build/docs tasks."
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# AppgramClient reference (imperative API)
2+
3+
Get client: `const { client } = useAppgramContext()`. Methods return `ApiResponse<T>` unless noted.
4+
5+
## Wishes
6+
- `getPublicWishes(filters?: WishFilters)` → paginated wishes (transforms raw response).
7+
- `getWish(wishId)`
8+
- `createWish({ title, description, author_email?, author_name?, category_id? })`
9+
10+
## Votes
11+
- `checkVote(wishId, fingerprint)`
12+
- `createVote(wishId, fingerprint, voterEmail?)`
13+
- `deleteVote(voteId)`
14+
15+
## Comments
16+
- `getComments(wishId, { page?, per_page? })` → normalizes to `CommentsResponse`.
17+
- `createComment({ wish_id, content, author_name?, author_email?, parent_id? })`
18+
19+
## Roadmap
20+
- `getRoadmapData()` (requires projectId; uses orgSlug/projectSlug when provided).
21+
22+
## Releases / Changelog
23+
- Needs both `orgSlug` and `projectSlug` in provider config.
24+
- `getReleases({ limit? })`
25+
- `getRelease(releaseSlug)`
26+
- `getReleaseFeatures(releaseSlug)`
27+
28+
## Help Center
29+
- `getHelpCollection()``{ collection, flows }`
30+
- `getHelpFlow(slug)`
31+
- `getHelpArticle(slug, flowId)`
32+
33+
## Support
34+
- `uploadFile(file)` → size limit 10MB; returns `{ url, name, size, mime_type? }`.
35+
- `submitSupportRequest(data: SupportRequestInput)`; auto-uploads attachments first.
36+
- `sendSupportMagicLink(email)`
37+
- `verifySupportToken(token)``{ tickets, user_email }`
38+
- `getSupportTicket(ticketId, token)`
39+
- `addSupportMessage(ticketId, token, content)`
40+
41+
## Status
42+
- `getPublicStatusOverview(slug = 'status')`
43+
44+
## Surveys
45+
- `getPublicSurvey(slug)` → includes `nodes`.
46+
- `submitSurveyResponse(surveyId, data)`
47+
- `getPublicSurveyCustomization(surveyId)`
48+
49+
## Forms
50+
- `getForm(formId)` → normalizes portal form shape.
51+
- `trackFormView(formId)` → POST; tolerant of non-JSON responses.
52+
- `submitForm(projectId, formId, data)` → tolerant of empty/non-JSON responses.
53+
54+
## Page data
55+
- `getPageData()` → combined public payload for landing usage.
56+
57+
## Blog
58+
- `getBlogPosts(filters?: BlogFilters)` → paginated transform.
59+
- `getBlogPost(slug)`
60+
- `getFeaturedBlogPosts()`
61+
- `getBlogCategories()`
62+
- `getBlogPostsByCategory(categorySlug, { page?, per_page? })`
63+
- `getBlogPostsByTag(tag, { page?, per_page? })`
64+
- `searchBlogPosts(query, { page?, per_page? })`
65+
- `getRelatedBlogPosts(slug)`
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Components cheat sheet
2+
3+
Use inside `AppgramProvider`. All components are stylable via theme exports or props where noted.
4+
5+
## Feedback / Wishes
6+
- `WishList`: full list + filters; props `title?`, `description?`, `filters?`, `showSubmitButton?`, `submitButtonText?`, callbacks `onWishPress`, `onWishSubmitted`, `onVote`, `onCommentPress`, `refreshInterval?`.
7+
- `WishCard`: single wish card; props `wish`, `onPress`, `onVote`, `onCommentPress`.
8+
- `VoteButton`: standalone vote UI; props `wishId`, `initialVoteCount`, `initialHasVoted`, `onVoteChange`.
9+
- `WishDetailModal`: modal detail w/ comments & votes; props `wishId`, `visible`, `onClose`, `onVote`, `onComment`.
10+
- `SubmitWishSheet`: sheet to create wish; props `visible`, `onClose`, `onSuccess`, `title?`, `description?`.
11+
12+
## Roadmap
13+
- `RoadmapBoard`: Kanban-style columns; props `onItemPress?`, `refreshInterval?`.
14+
15+
## Releases / Changelog
16+
- `Releases`: combined list + detail navigation; `onReleasePress?`.
17+
- `ReleaseList`: list view; props `limit?`, `onReleasePress`.
18+
- `ReleaseDetail`: single release; props `releaseSlug`, `onBack?`.
19+
20+
## Help Center
21+
- `HelpCenter`: flows + articles overview; props `title?`, `onFlowPress`, `onArticlePress`.
22+
- `HelpFlowCard`: summary card; props `flow`, `onPress`.
23+
- `HelpFlowDetail`: flow detail; props `slug`, `onArticlePress`, `onBack?`.
24+
- `HelpArticleCard`: article preview; props `article`, `onPress`.
25+
- `HelpArticleDetail`: article content; props `slug`, `flowId?`, `onBack?`.
26+
27+
## Support & Forms
28+
- `SupportForm`: ticket form; props `title?`, `userEmail?`, `userName?`, `onSuccess`, `onError?`.
29+
- `FormRenderer`: render dynamic form by `formId`; props `formId`, `onSuccess?`, `onError?`.
30+
31+
## Surveys
32+
- `SurveyForm`: interactive survey; props `slug`, `onSuccess`, `onError?`.
33+
34+
## Blog
35+
- `Blog`: full blog view; props `title?`, `onPostPress`.
36+
- `BlogList`: list with pagination/filter; props `category?`, `onPostPress`.
37+
- `BlogCard`: card; props `post`, `onPress`.
38+
- `BlogPostDetail`: article content; props `slug`, `onBack?`.
39+
40+
## Status
41+
- `StatusBoard`: status + incidents; props `slug`, `refreshInterval?`.
42+
43+
## Chat
44+
- `ChatScreen`: chat UI; uses `ChatSource` type; expects messages from Appgram client or custom source.
45+
46+
## Base UI
47+
- `Button`, `Card`, `Badge`, `Input`: Hazel-themed primitives; accept standard RN text/input props plus style overrides.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Hooks cheat sheet
2+
3+
Each hook is headless: returns data, `isLoading`, often `error`, `refetch`, plus setters. Most support `refreshInterval` (ms) and `skip` for lazy load where provided. Use with `AppgramProvider` mounted.
4+
5+
## Feedback / Wishes
6+
- `useWishes(options?: { filters?: WishFilters; refreshInterval?: number; skip?: boolean })`
7+
- Returns `{ wishes, total, page, totalPages, isLoading, error, setFilters(filters), setPage(page), refetch }`
8+
- Includes fingerprint when voting enabled; `setFilters` resets page to 1.
9+
- `useVote({ onVote?, onError? }?)`
10+
- Returns `{ vote(wishId, currentCount), unvote(wishId, voteId, currentCount), checkVote(wishId), isVoting, error }`
11+
- Requires `fingerprint` (default enabled); `checkVote` safe if missing.
12+
- `useComments({ wishId, autoFetch?, refreshInterval? })`
13+
- Returns `{ comments, isLoading, error, isSubmitting, addComment(body, name?, email?), refetch }`
14+
15+
## Roadmap
16+
- `useRoadmap({ refreshInterval? })`
17+
- Returns `{ roadmap, columns, totalItems, isLoading, error, refetch }`
18+
19+
## Releases / Changelog
20+
- `useReleases({ limit?, page?, refreshInterval? })`
21+
- Returns `{ releases, isLoading, error, page, totalPages, setPage, refetch }`
22+
- `useRelease({ releaseSlug, refreshInterval? })`
23+
- Returns `{ release, features, isLoading, error, refetch }`
24+
25+
## Help Center
26+
- `useHelpCenter()``{ collection, flows, isLoading, error }`
27+
- `useHelpFlow(slug)``{ flow, isLoading, error }`
28+
- `useHelpArticle(articleSlug, flowId?)``{ article, isLoading, error }`
29+
30+
## Support & Forms
31+
- `useSupport({ onSuccess?, onError? }?)`
32+
- Returns submission + auth helpers: `{ submitTicket(data), isSubmitting, error, successMessage, clearMessages, requestMagicLink(email), isSendingMagicLink, verifyToken(token), isVerifying, storedTickets, loadStoredTickets, clearStoredTickets }`
33+
- Stores last 50 tickets in AsyncStorage (fallback to in-memory).
34+
- `useForm(formId, { refreshInterval?, skip? }?)`
35+
- `{ form, isLoading, error, refetch }`
36+
- `useFormSubmit({ onSuccess?, onError? }?)`
37+
- `{ submitForm(projectId, formId, payload), isSubmitting, error }`
38+
39+
## Surveys
40+
- `useSurvey(slug, { refreshInterval?, skip? }?)`
41+
- `{ survey, nodes, isLoading, error, refetch }`
42+
- `useSurveySubmit({ onSuccess?, onError? }?)`
43+
- `{ submitResponse(surveyId, payload), isSubmitting, error }`
44+
45+
## Blog
46+
- `useBlogPosts({ category?, per_page?, page?, search?, refreshInterval? }?)`
47+
- `{ posts, page, totalPages, setPage, setFilters, isLoading, error, refetch }`
48+
- `useBlogPost({ slug })``{ post, relatedPosts, isLoading, error }`
49+
- `useBlogCategories()``{ categories, isLoading, error }`
50+
- `useFeaturedPosts()``{ posts, isLoading, error }`
51+
52+
## Status
53+
- `useStatus({ slug, refreshInterval? })`
54+
- `{ data, isLoading, error, refetch }`
55+
56+
## Shared utilities
57+
- `useAppgramContext()``{ client, config, fingerprint, theme }`
58+
- `useAppgramTheme()``{ colors, spacing, radius, typography, isDark, mode }`
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Platform setup & debugging
2+
3+
## Install & link
4+
1) `npm install @appgram/react-native`
5+
2) `npm install @react-native-async-storage/async-storage lucide-react-native react-native-svg react-native-markdown-display react-native-render-html`
6+
3) iOS: `npx pod-install` (or `cd ios && pod install`).
7+
4) Android: open Android Studio/Gradle sync or run `cd android && ./gradlew :app:assembleDebug` once to verify linking.
8+
9+
## Minimum versions
10+
- React Native ≥0.70, React 18.
11+
- react-native-svg ≥13, lucide-react-native ≥0.300.
12+
13+
## Common fixes
14+
- Metro cache: `npm start -- --reset-cache`
15+
- Watchman: `watchman watch-del-all` (if installed)
16+
- Android clean build: `cd android && ./gradlew clean && ./gradlew :app:assembleDebug`
17+
- iOS clean pods: `cd ios && rm -rf Pods Podfile.lock && pod install`
18+
- Hermes mismatch: ensure RN version default Hermes enabled; if disabling Hermes, rebuild pods.
19+
- Missing SVG icons: reinstall `react-native-svg` and `lucide-react-native`, then rebuild pods / Gradle.
20+
21+
## iOS notes
22+
- If using Xcode, ensure the pods integrate with `use_frameworks!` defaults; no extra manual steps needed.
23+
- For simulator fingerprinting issues, reset simulator content or clear AsyncStorage: `xcrun simctl erase all` (destructive) or uninstall the app.
24+
25+
## Android notes
26+
- Ensure `mavenCentral()` is present in `android/build.gradle`.
27+
- If release build crashes on SVG, check ProGuard/R8 rules; typically not needed, but you can keep `-keep class com.horcrux.svg.** { *; }` as a safeguard.
28+
- AsyncStorage failing on Android emulator: wipe data via AVD Manager or reinstall app.
29+
30+
## Web (Expo / RNW)
31+
- Components assume native; hooks can be used in Expo if dependencies are available; check markdown/html render libs compatibility on web.
32+
33+
## Validation checklist before shipping
34+
- Run `npm run lint` and `npm run typecheck`.
35+
- Build once: `npm run build` to ensure bob output.
36+
- For app integrators: verify one happy-path flow per feature (wishlist vote, support submit, survey submit, blog post view, status load) on both platforms.

0 commit comments

Comments
 (0)