React Native SDK for Appgram - feature voting, roadmaps, changelogs, help center, support, surveys, blog, and status pages.
npm install @appgram/react-native
# or
yarn add @appgram/react-nativenpm install @react-native-async-storage/async-storage lucide-react-native react-native-svg react-native-markdown-display react-native-render-htmlimport { AppgramProvider, WishList, SupportForm } from '@appgram/react-native'
function App() {
return (
<AppgramProvider
config={{
projectId: 'your-project-id',
orgSlug: 'your-org',
projectSlug: 'your-project',
}}
>
<NavigationContainer>
{/* Your app content */}
</NavigationContainer>
</AppgramProvider>
)
}| Feature | Components | Hooks |
|---|---|---|
| Wishes/Feedback | WishList, WishCard, VoteButton, WishDetailModal, SubmitWishSheet |
useWishes, useVote, useComments |
| Roadmap | RoadmapBoard |
useRoadmap |
| Changelog/Releases | Releases, ReleaseList, ReleaseDetail |
useReleases, useRelease |
| Help Center | HelpCenter, HelpFlowCard, HelpFlowDetail, HelpArticleCard, HelpArticleDetail |
useHelpCenter, useHelpFlow, useHelpArticle |
| Support | SupportForm, FormRenderer |
useSupport, useForm, useFormSubmit |
| Surveys | SurveyForm |
useSurvey, useSurveySubmit |
| Blog | Blog, BlogList, BlogCard, BlogPostDetail |
useBlogPosts, useBlogPost, useBlogCategories, useFeaturedPosts |
| Status Page | StatusBoard |
useStatus |
Complete feature request list with voting, filtering, and built-in submission.
import { WishList } from '@appgram/react-native'
<WishList
title="Feature Requests"
description="Vote on features and submit your ideas"
filters={{ status: 'pending', sort_by: 'votes' }}
showSubmitButton={true}
submitButtonText="Submit Idea"
onWishPress={(wish) => console.log('Selected:', wish)}
onWishSubmitted={(wish) => console.log('Submitted:', wish)}
refreshInterval={30000}
/>Individual wish card for custom layouts.
import { WishCard } from '@appgram/react-native'
<WishCard
wish={wish}
onPress={(wish) => navigation.navigate('WishDetail', { id: wish.id })}
onVote={(wishId) => console.log('Voted:', wishId)}
onCommentPress={(wish) => console.log('Comment on:', wish.id)}
/>Standalone vote button for custom layouts.
import { VoteButton } from '@appgram/react-native'
<VoteButton
wishId={wish.id}
initialVoteCount={wish.vote_count}
initialHasVoted={wish.has_voted}
onVoteChange={(hasVoted, newCount) => updateWish(wish.id, newCount)}
/>Modal sheet for submitting new feature requests.
import { SubmitWishSheet } from '@appgram/react-native'
<SubmitWishSheet
visible={isVisible}
onClose={() => setVisible(false)}
onSuccess={(wish) => console.log('Created:', wish)}
title="Submit a Feature Request"
description="Tell us what you'd like to see"
/>Kanban-style roadmap display.
import { RoadmapBoard } from '@appgram/react-native'
<RoadmapBoard
onItemPress={(item) => console.log('Selected:', item)}
/>Full changelog view with release list and detail.
import { Releases } from '@appgram/react-native'
<Releases
onReleasePress={(release) => navigation.navigate('ReleaseDetail', { slug: release.slug })}
/>List of releases for custom layouts.
import { ReleaseList } from '@appgram/react-native'
<ReleaseList
limit={10}
onReleasePress={(release) => console.log(release)}
/>Single release detail view.
import { ReleaseDetail } from '@appgram/react-native'
<ReleaseDetail
releaseSlug="v1.2.0"
onBack={() => navigation.goBack()}
/>Complete help center with flows and articles.
import { HelpCenter } from '@appgram/react-native'
<HelpCenter
title="Help Center"
onFlowPress={(flow) => navigation.navigate('HelpFlow', { slug: flow.slug })}
onArticlePress={(article) => navigation.navigate('Article', { slug: article.slug })}
/>Single help flow with its articles.
import { HelpFlowDetail } from '@appgram/react-native'
<HelpFlowDetail
slug="getting-started"
onArticlePress={(article) => navigation.navigate('Article', { slug: article.slug })}
onBack={() => navigation.goBack()}
/>Single article content view.
import { HelpArticleDetail } from '@appgram/react-native'
<HelpArticleDetail
slug="how-to-reset-password"
flowId="account-help"
onBack={() => navigation.goBack()}
/>Complete support ticket form.
import { SupportForm } from '@appgram/react-native'
<SupportForm
title="Contact Support"
userEmail="user@example.com"
userName="John Doe"
onSuccess={() => {
Alert.alert('Success', 'Your ticket has been submitted!')
navigation.goBack()
}}
onError={(error) => Alert.alert('Error', error)}
/>Render dynamic forms.
import { FormRenderer } from '@appgram/react-native'
<FormRenderer
formId="contact-sales"
onSuccess={() => console.log('Submitted!')}
/>Interactive survey form.
import { SurveyForm } from '@appgram/react-native'
<SurveyForm
slug="customer-satisfaction"
onSuccess={(response) => console.log('Submitted:', response)}
onError={(error) => console.log('Error:', error)}
/>Full blog with categories and posts.
import { Blog } from '@appgram/react-native'
<Blog
title="Blog"
onPostPress={(post) => navigation.navigate('BlogPost', { slug: post.slug })}
/>List of blog posts with pagination.
import { BlogList } from '@appgram/react-native'
<BlogList
category="announcements"
onPostPress={(post) => console.log(post)}
/>Single blog post content.
import { BlogPostDetail } from '@appgram/react-native'
<BlogPostDetail
slug="introducing-v2"
onBack={() => navigation.goBack()}
/>System status overview.
import { StatusBoard } from '@appgram/react-native'
<StatusBoard
slug="status"
refreshInterval={60000}
/>All hooks are designed for building custom UI. Each hook returns loading state, error handling, and a refetch function.
Fetch and filter feature requests.
import { useWishes } from '@appgram/react-native'
const { wishes, isLoading, error, refetch, setFilters } = useWishes({
filters: { status: 'pending', sort_by: 'votes' },
refreshInterval: 30000,
})Manage voting on wishes.
import { useVote } from '@appgram/react-native'
const { vote, unvote, checkVote, isVoting, error } = useVote()
// Vote on a wish
await vote(wishId, currentVoteCount)
// Remove vote
await unvote(wishId, voteId, currentVoteCount)Fetch and add comments to wishes.
import { useComments } from '@appgram/react-native'
const { comments, isLoading, addComment, isSubmitting, refetch } = useComments({
wishId: 'wish-123',
autoFetch: true,
})
// Add a comment
await addComment('Great idea!', 'John', 'john@example.com')Fetch roadmap columns and items.
import { useRoadmap } from '@appgram/react-native'
const { roadmap, columns, totalItems, isLoading, error, refetch } = useRoadmap({
refreshInterval: 60000,
})Fetch changelog releases.
import { useReleases, useRelease } from '@appgram/react-native'
// List of releases
const { releases, isLoading, refetch } = useReleases({ limit: 10 })
// Single release with features
const { release, features, isLoading, refetch } = useRelease({
releaseSlug: 'v1.2.0',
})Fetch help center content.
import { useHelpCenter, useHelpFlow, useHelpArticle } from '@appgram/react-native'
// Help center overview
const { collection, flows, isLoading } = useHelpCenter()
// Single flow with articles
const { flow, isLoading } = useHelpFlow('getting-started')
// Single article
const { article, isLoading } = useHelpArticle('reset-password', 'account-help')Submit support tickets.
import { useSupport } from '@appgram/react-native'
const { submitTicket, isSubmitting, error, successMessage } = useSupport()
await submitTicket({
subject: 'Help needed',
description: 'I have a question...',
user_email: 'user@example.com',
user_name: 'John',
})Fetch and submit dynamic forms.
import { useForm, useFormSubmit } from '@appgram/react-native'
const { form, isLoading } = useForm('form-id')
const { submitForm, isSubmitting, error } = useFormSubmit()
await submitForm(projectId, 'form-id', { name: 'John', email: 'john@example.com', message: 'Hello!' })Fetch and submit surveys.
import { useSurvey, useSurveySubmit } from '@appgram/react-native'
const { survey, nodes, isLoading } = useSurvey('customer-satisfaction')
const { submitResponse, isSubmitting } = useSurveySubmit({
onSuccess: (response) => console.log('Done!', response),
})
await submitResponse(survey.id, { answers: { q1: 'Great!' } })Fetch blog content.
import { useBlogPosts, useBlogPost, useBlogCategories, useFeaturedPosts } from '@appgram/react-native'
// List with filters and pagination
const { posts, page, totalPages, setPage, setFilters, refetch } = useBlogPosts({
category: 'news',
per_page: 10,
})
// Single post with related posts
const { post, relatedPosts, isLoading } = useBlogPost({ slug: 'hello-world' })
// Categories
const { categories, isLoading } = useBlogCategories()
// Featured posts
const { posts: featured, isLoading } = useFeaturedPosts()Fetch status page data.
import { useStatus } from '@appgram/react-native'
const { data, isLoading, error, refetch } = useStatus({
slug: 'status',
refreshInterval: 60000,
})The SDK automatically adapts to system dark/light mode using the Hazel design system.
<AppgramProvider
config={{
projectId: 'your-project-id',
theme: {
mode: 'system', // 'light' | 'dark' | 'system'
lightColors: {
primary: '#0EA5E9',
background: '#FFFFFF',
foreground: '#0F172A',
},
darkColors: {
primary: '#38BDF8',
background: '#0F172A',
foreground: '#F8FAFC',
},
},
}}
>Use the useAppgramTheme hook to access theme values in custom components.
import { useAppgramTheme } from '@appgram/react-native'
function MyComponent() {
const { colors, spacing, radius, typography, isDark } = useAppgramTheme()
return (
<View style={{ backgroundColor: colors.background, padding: spacing.lg }}>
<Text style={{ color: colors.foreground, fontSize: typography.base }}>
Hello
</Text>
</View>
)
}| Property | Description |
|---|---|
colors |
Color palette (primary, background, foreground, muted, border, error, etc.) |
spacing |
Spacing scale (xs, sm, md, lg, xl, 2xl) |
radius |
Border radius scale (sm, md, lg, xl, full) |
typography |
Font sizes (xs, sm, base, lg, xl, 2xl, 3xl) |
isDark |
Boolean indicating if dark mode is active |
mode |
Current theme mode ('light', 'dark', 'system') |
For advanced use cases, access the API client directly.
import { useAppgramContext } from '@appgram/react-native'
function MyComponent() {
const { client, config, fingerprint } = useAppgramContext()
const fetchData = async () => {
const response = await client.getWishes({ status: 'approved' })
if (response.success) {
console.log(response.data)
}
}
}The SDK is fully typed. Import types as needed:
import type {
Wish,
WishFilters,
Vote,
Release,
ReleaseFeature,
RoadmapData,
RoadmapColumn,
HelpCollection,
HelpFlow,
HelpArticle,
BlogPost,
BlogCategory,
Survey,
SurveyNode,
StatusPageOverview,
Comment,
AppgramConfig,
AppgramTheme,
} from '@appgram/react-native'MIT