بنقرة واحدة
paperand-development
Guide for developing and maintaining the Paperand React Native manga reader application
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Guide for developing and maintaining the Paperand React Native manga reader application
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Image caching and storage management with expo-image
Reusable component patterns and styling
URL schemes and deep link handling
Background chapter downloads and offline reading
Common patterns for Expo SDK 54 and React Native development
Paperback-compatible extension runtime and source API
| name | Paperand Development |
| description | Guide for developing and maintaining the Paperand React Native manga reader application |
This skill provides comprehensive guidance for working with the Paperand project - an ad-free manga reader built with Expo and React Native, compatible with Paperback extensions.
Paperand is a cross-platform manga reader app that:
| Technology | Purpose |
|---|---|
| Expo SDK 54 | Development framework |
| React Native 0.81 | Cross-platform mobile development |
| TypeScript | Type-safe JavaScript |
| React Navigation 7 | Navigation library (stack + bottom tabs) |
| AsyncStorage | Persistent local storage |
| expo-image | Optimized image loading with caching |
| WebView | Extension runtime for Paperback sources |
| i18n-js | Internationalization |
paperback-android/
├── App.tsx # Main app entry, providers setup
├── index.ts # Expo entry point
├── app.json # Expo configuration
├── package.json # Dependencies
├── src/
│ ├── components/ # Reusable UI components
│ │ ├── MangaCard.tsx # Manga cover card component
│ │ ├── ChapterListItem.tsx # Chapter list item
│ │ ├── ExtensionRunner.tsx # WebView extension runtime
│ │ ├── PickerModal.tsx # Custom picker modal
│ │ └── ...
│ ├── context/ # React Context providers
│ │ ├── ThemeContext.tsx # Theme management
│ │ └── LibraryContext.tsx # Library & progress state
│ ├── navigation/ # Navigation configuration
│ │ ├── AppNavigator.tsx # Main stack navigator
│ │ └── BottomTabNavigator.tsx # Bottom tab navigation
│ ├── screens/ # App screens
│ │ ├── LibraryScreen.tsx # User library
│ │ ├── DiscoverScreen.tsx # Browse sources
│ │ ├── SearchScreen.tsx # Multi-source search
│ │ ├── MangaDetailScreen.tsx # Manga details & chapters
│ │ ├── ReaderScreen.tsx # Manga reader (core feature)
│ │ ├── DownloadManagerScreen.tsx # Download management
│ │ ├── ExtensionsScreen.tsx # Manage extensions
│ │ └── ...
│ ├── services/ # Core business logic
│ │ ├── sourceService.ts # Extension API bridge
│ │ ├── extensionService.ts # Extension management
│ │ ├── cacheService.ts # Image caching
│ │ ├── downloadService.ts # Chapter downloads
│ │ ├── themeService.ts # Theme file parsing
│ │ ├── i18nService.ts # Internationalization
│ │ ├── updateService.ts # App update checks
│ │ └── ...
│ ├── hooks/ # Custom React hooks
│ ├── types/ # TypeScript type definitions
│ ├── constants/ # App constants
│ └── locales/ # Translation files (17 languages)
├── android/ # Android native code
├── assets/ # Images, icons, fonts
├── plugins/ # Custom Expo config plugins
└── credentials/ # Build credentials
# Install dependencies
npm install
# or
bun install
# Start development server
npx expo start
# Run on Android
npm run android
# Run on iOS
npm run ios
# Run on web
npm run web
The app uses a WebView-based extension runtime (ExtensionRunner.tsx) to execute Paperback-compatible extensions. Extensions are JavaScript bundles that provide manga source implementations.
.pbcolors themesAll business logic is encapsulated in service files:
sourceService.ts - Bridge between app and extensionscacheService.ts - Image caching with configurable limitsdownloadService.ts - Background chapter downloadsi18nService.ts - Multi-language supportStack Navigator (AppNavigator)
├── Bottom Tab Navigator
│ ├── Library
│ ├── Discover
│ ├── History
│ └── More
├── MangaDetail
├── Reader
├── Search
├── Extensions
├── Settings
└── ...
The app supports 17+ languages. Translation files are in src/locales/ as JSON files.
Adding a new translation:
src/locales/ (e.g., de.json)en.jsoni18nService.tsThe app supports custom themes via .pbcolors files (Paperback theme format).
Theme configuration:
themeService.tsThemeContextOn push to main or manual trigger:
# Android APK
eas build --platform android --profile preview
# iOS
eas build --platform ios --profile preview
src/screens/src/screens/index.tssrc/navigation/AppNavigator.tsxsrc/components/src/components/index.tsThemeContext for stylingsrc/services/useTheme())i18n.t('key') for all user-facing stringsconsole.log (visible in Metro bundler)// Theme & Styles
import { useTheme } from '../context/ThemeContext';
// Library & State
import { useLibrary } from '../context/LibraryContext';
// Navigation
import { useNavigation, useRoute } from '@react-navigation/native';
// Components
import { MangaCard, LoadingIndicator, EmptyState } from '../components';
// Services
import { sourceService } from '../services/sourceService';
import { cacheService } from '../services/cacheService';
// i18n
import { i18n } from '../services/i18nService';
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { useTheme } from '../context/ThemeContext';
export function NewScreen() {
const { colors } = useTheme();
return (
<View style={[styles.container, { backgroundColor: colors.background }]}>
{/* Content */}
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
});
// Navigate with params
navigation.navigate('MangaDetail', { manga, sourceId });
navigation.navigate('Reader', { manga, chapter, sourceId });
// Get params
const { manga, sourceId } = useRoute().params;
const { colors, isDark } = useTheme();
// colors.background, colors.text, colors.primary, colors.card, colors.border
// Card style
{ backgroundColor: colors.card, borderRadius: 12, padding: 16 }
// Text styles
{ color: colors.text, fontSize: 16 }
{ color: colors.textSecondary, fontSize: 14 }
// Separator
{ height: 1, backgroundColor: colors.border }
const {
library, // Manga[] - saved manga
favorites, // string[] - favorite manga IDs
readingProgress, // { [mangaId]: { chapterId, page } }
addToLibrary, // (manga) => void
removeFromLibrary, // (mangaId) => void
toggleFavorite, // (mangaId) => void
updateProgress, // (mangaId, chapterId, page) => void
} = useLibrary();
| Key | Type | Description |
|---|---|---|
@library | Manga[] | Saved manga |
@favorites | string[] | Favorite IDs |
@reading_progress | object | Reading positions |
@extensions | Extension[] | Installed extensions |
@settings | object | User settings |
@history | HistoryItem[] | Reading history |
// Get manga list
await sourceService.getDiscoverSection(sourceId, sectionId);
// Search manga
await sourceService.searchManga(sourceId, query);
// Get manga details
await sourceService.getMangaDetails(sourceId, mangaId);
// Get chapters
await sourceService.getChapters(sourceId, mangaId);
// Get chapter pages
await sourceService.getChapterPages(sourceId, chapterId);
try {
const data = await sourceService.getMangaDetails(sourceId, mangaId);
} catch (error) {
console.error('Failed to load manga:', error);
// Show error state or toast
}
expo-image with cachePolicy="memory-disk"FlatList with keyExtractor and getItemLayoutuseMemo/useCallback for expensive operations| Type | Convention | Example |
|---|---|---|
| Screen | *Screen.tsx | LibraryScreen.tsx |
| Component | PascalCase.tsx | MangaCard.tsx |
| Service | *Service.ts | cacheService.ts |
| Hook | use*.ts | useDebounce.ts |
| Context | *Context.tsx | ThemeContext.tsx |
| Types | index.ts | types/index.ts |
| Issue | Solution |
|---|---|
| Extension not loading | Check WebView logs, verify extension URL |
| Images not caching | Check cache size limits in settings |
| Build fails | Run npx expo prebuild --clean |
| Metro bundler stuck | Clear cache: npx expo start -c |
| Android foreground service crash | Check withBackgroundActionsServiceType plugin |
plugins/withBackgroundActionsServiceType.jsapp.json under android.permissionspaperback:// and paperand:// schemesfetch enabledCFBundleLocalizationscom.chiraitori.paperand.ios