Skip to content

JawadSher/Paper-Stack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Paper Stack logo

Paper Stack

A polished Expo mobile app for browsing, searching, downloading, and reviewing Pakistani board past papers.

Expo SDK 54 | React Native 0.81 | Supabase | TanStack Query


Overview

Paper Stack is a mobile-first past-paper library built with Expo Router and Supabase. It helps students browse education boards, choose a class and subject, open real PDF papers, search across published papers, bookmark important material, and keep downloaded files available offline.

The app is designed around fast repeated use: board-based browsing, compact paper cards, subject-aware filtering, offline status handling, and native builds that can exercise Android behavior beyond Expo Go.

Features

  • Browse active boards grouped by province from Supabase.
  • View board details with board-specific color theming.
  • Select class levels and subjects through the board/class/subject flow.
  • Fetch live papers from Supabase with board, subject, class, year, and session filters.
  • Open PDF papers in the native viewer when available.
  • Fall back to an external PDF open action if native preview cannot load.
  • Search papers with debounced server-side queries.
  • Bookmark papers and hydrate bookmark metadata from the server.
  • Download papers for offline reading.
  • Restore offline download metadata with local snapshots.
  • Continue browsing recently opened papers.
  • View common questions grouped by chapter.
  • Persist preferences and offline state with Zustand and AsyncStorage.
  • Show loading, empty, offline, and network retry states across data-driven screens.

Tech Stack

Area Technology
App runtime Expo SDK 54, React Native 0.81, React 19
Routing Expo Router
Server data Supabase direct database access
Async state TanStack Query
Local state Zustand
Persistence AsyncStorage
Offline files Expo FileSystem
PDF viewing react-native-pdf with external-open fallback
Styling NativeWind, Tailwind config, custom theme tokens
Icons Lucide React Native
Builds EAS Build

Project Structure

paper-stack/
|-- app/
|   |-- (tabs)/                 # Home, search, downloads, profile
|   |-- (stack)/                # Boards, papers, viewer, bookmarks, questions
|   |-- _layout.tsx             # Root providers, routing, deep links
|   |-- onboarding.tsx
|   `-- splash.tsx
|-- components/
|   |-- browse/                 # Board/class/subject/paper browse UI
|   |-- common/                 # Empty, error, network, skeleton, toast UI
|   |-- home/                   # Home sections and offline shortcut
|   |-- search/                 # Search header, filters, results
|   |-- viewer/                 # PDF viewer, toolbar, download progress
|   `-- ui/                     # Shared primitives
|-- hooks/
|   |-- api/                    # TanStack Query hooks
|   |-- useDownload.ts
|   |-- useBookmark.ts
|   `-- useNetworkStatus.ts
|-- lib/
|   |-- queries/                # Pure Supabase query functions
|   |-- supabase.ts             # Supabase client
|   |-- query-keys.ts
|   `-- offline-files.ts
|-- store/
|   `-- index.ts                # Zustand store
|-- types/
|   `-- index.ts                # Server-aligned app types and mappers
|-- constants/                  # Theme and offline fallback data
|-- supabase/                   # SQL helpers
`-- assets/images/
    `-- icon.png

Data Flow

Paper Stack uses Supabase as the primary source of truth. The query layer is split into pure async functions and React hooks:

Supabase tables
  -> lib/queries/*
  -> hooks/api/*
  -> screens/components

The main data entities are:

  • Board
  • Subject
  • Paper
  • CommonQuestion
  • Download
  • UserPreferences

Database rows are mapped from snake_case Supabase columns into camelCase mobile types in types/index.ts.

Supabase Integration

The Supabase client lives in:

lib/supabase.ts

Environment variables are expected in .env for local development:

EXPO_PUBLIC_SUPABASE_URL=
EXPO_PUBLIC_SUPABASE_ANON_KEY=

Use .env.example as the template. Do not commit real secrets.

For EAS builds, the same variables must be available to the selected build profile. This project currently defines them under the preview and production profiles in eas.json.

Query Layer

Pure query functions live in lib/queries/:

  • boards.ts - board list, grouped boards, board detail
  • subjects.ts - all subjects and board/class subjects
  • papers.ts - paper lists, paper detail, recent papers, search, hydration by IDs
  • questions.ts - common question queries
  • settings.ts - feature flags
  • analytics.ts - view/download analytics RPC calls

React hooks live in hooks/api/ and wrap those functions with TanStack Query keys, caching, loading states, and retry behavior.

Offline Strategy

Downloads are stored as local file records and persisted through Zustand/AsyncStorage. Each download can include a paperSnapshot, so the app can render metadata even when the network is unavailable.

The viewer prefers sources in this order:

  1. Downloaded local file URI
  2. Server pdfUrl
  3. Navigation fallback metadata

The home screen also exposes an offline downloads shortcut when the device is offline.

Getting Started

Prerequisites

  • Node.js 20+
  • npm
  • Expo CLI through npx
  • Android Studio or a physical Android device for native testing
  • Supabase project with the required tables and public read access/RLS policies

Install

npm install

Configure Environment

Create .env in the project root:

EXPO_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-public-key

Run Locally

npx expo start

Expo Go can run most of the app, but native PDF preview is limited. Use a development or preview build for the closest production behavior.

Type Check

npx tsc --noEmit

Android Export Check

npx expo export --platform android --clear

EAS Builds

Build preview APK:

eas build -p android --profile preview

Build production Android App Bundle:

eas build -p android --profile production

The app is configured with:

android.package = com.devjawadsher.paperstack

Important Notes

  • react-native-pdf is not available inside Expo Go. The app includes a fallback UI for Expo Go and slow native PDF loads.
  • Supabase credentials used by EAS must be available at build time because Expo public env values are bundled into the app.
  • constants/boards.ts and constants/subjects.ts are offline fallback data, not the primary source.
  • constants/questions.ts is deprecated reference data and should not be used by new screens.

Roadmap

  • Add real app screenshots to docs/screenshots/ and reference them in this README.
  • Add a Supabase schema migration set for reproducible setup.
  • Add automated smoke tests for the board -> class -> subject -> paper -> viewer flow.
  • Add richer analytics dashboards for paper views and downloads.
  • Improve in-app PDF rendering diagnostics for malformed or restricted PDF URLs.

License

Private project. All rights reserved unless a license is added.

About

PaperStack — A mobile app for Pakistani students to browse, search, and download past year exam papers from all major boards and cities. Features offline access, board/class/subject filtering, and a smart common questions analyzer that highlights the most repeated questions across years. Built with Expo + React Native.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors