A fullβfeatured web application for managing PDFβtoβCSV processing workflows.
It allows users to:
- π Authenticate with Google (Firebase Auth)
- π CRUD tests (name, date, template folder)
- π Upload PDFs, count pages, and convert each page to images
- π Manage folders using the File System Access API (delete old images, copy template folders)
- π Run a Python script with configurable input/output directories
- π Preview the generated CSV and push its data to Firestore
Built with React 18, TypeScript, Firebase (Auth + Firestore), and PDF.js.
- Google SignβIn β secure authentication via Firebase.
- Test CRUD β create, read, update, delete tests with a dashboard.
- PDF processing β upload PDF, detect page count, convert pages to PNG images.
- Folder management β select input/output/templates folders; autoβclean existing images.
- Template system β copy a chosen template subβfolder into the input folder.
- Python integration β run a custom Python command with
--inputDirand--outputDirplaceholders. - CSV preview β display generated CSV data in a table.
- Firestore export β push CSV rows to a subβcollection for permanent storage.
- Settings page β configure folders and Python command.
- TypeScript β fully typed for better developer experience.
- Node.js (v16 or later) and npm / yarn
- A Firebase project with:
- Authentication (Google provider enabled)
- Firestore Database (in test or production mode)
- A Python environment (if you intend to run the actual script)
- A modern browser that supports the File System Access API (Chromiumβbased)
git clone https://github.com/your-username/pdf-test-manager.git
cd pdf-test-managernpm install
# or
yarn installCreate a .env file in the project root with your Firebase configuration:
VITE_FIREBASE_API_KEY=your_api_key
VITE_FIREBASE_AUTH_DOMAIN=your_auth_domain
VITE_FIREBASE_PROJECT_ID=your_project_id
VITE_FIREBASE_STORAGE_BUCKET=your_storage_bucket
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_idNote: If you use Create React App, prefix variables with
REACT_APP_instead ofVITE_.
Open src/firebase/config.ts (or firebase/config.ts) and ensure it reads from import.meta.env (or process.env).
npm run dev
# or
npm startThe app will be available at http://localhost:5173 (Vite) or http://localhost:3000 (CRA).
npm run buildServe the dist (or build) folder with your preferred static server.
- Click βSign in with Googleβ β only authenticated users can access the app.
- Go to Settings (βοΈ).
- Select your Input, Output, and Templates folders using the browserβs folder picker.
- Set your Python command (e.g.,
python3 main.py --inputDir [--inputDir] --outputDir [--outputDir]). - Save settings.
The templates folder should contain subβfolders, each representing a template.
- On the Dashboard, click βNew Testβ.
- Enter a Name, Date, and choose a Template Folder from the dropdown.
- Click Create.
- Open the test detail page.
- Upload a PDF file β the app counts the pages.
- Click βConvert & Prepareβ β this will:
- Ask you to confirm (or reβselect) the input/output/templates folders.
- Delete all existing images (
.png,.jpg,.jpeg) from input and output folders. - Convert each PDF page to a PNG and save them in the input folder.
- Copy the chosen template folder into the input folder.
- On the test detail page, click βRun Pythonβ.
- The app will construct the command with the selected input/output folders and execute it (simulated in this demo; you can replace with an actual API call).
- After completion, the CSV is read from the output folder and displayed.
- Once the CSV is shown, click βPush CSVβ to store each row as a document in a subβcollection under the test document.
- Use the Dashboard to view, open, or delete existing tests.
- Reset a test to draft state at any time.
Follow this visual guide to test the end-to-end PDF processing workflow.
Go to the Settings page and select your local directories. Ensure your Python command uses the exact placeholders ([--inputDir] and [--outputDir]) as shown below:

Go to the Dashboard and click New Test. Fill in the details and choose a template (e.g., sample1).

Open the test you just created and click Select PDF File to upload your scanned OMR sheets.
(A sample PDF is available in this repository at docs/sample_omr.pdf for testing purposes).

Once the PDF is converted, the app will generate a custom Python command with your specific folder paths. Copy this command and run it in your terminal.

Note: The Python script might pause to show debug images of its edge detection and grid alignment. When this happens, click on each image window and press the Q key on your keyboard to continue processing!
After the script finishes successfully in the terminal, click Read Results from Output Folder in the web app to view the generated CSV data.

src/
βββ contexts/
β βββ AuthContext.tsx # Authentication state & methods
β βββ ToastContext.tsx # Toast notification system
βββ firebase/
β βββ config.ts # Firebase initialization
βββ pages/
β βββ Login.tsx # Login page
β βββ Dashboard.tsx # Test list & stats
β βββ Settings.tsx # Folder & command configuration
β βββ TestDetail.tsx # Test workflow (upload, process, preview)
βββ components/
β βββ Navigation.tsx # Top navigation bar
β βββ ProtectedRoute.tsx # Route guard for authenticated users
βββ types/
β βββ index.ts # TypeScript interfaces (Test, Settings, etc.)
βββ utils/
β βββ pdf.ts # PDF page counting
β βββ fileSystem.ts # Folder selection, deletion, copying
β βββ firestore.ts # Firestore CRUD operations
βββ App.tsx # Main App with routing
βββ main.tsx # Entry point
In the Settings page, you can define a Python command. Use --inputDir and --outputDir as placeholders β they will be replaced with the actual folder names when the command is run.
Example:
python3 main.py --inputDir [--inputDir] --outputDir [--outputDir]
- Templates are subβfolders inside your Templates Directory.
- When creating a test, you select one of these subβfolders.
- During the βConvert & Prepareβ step, the entire template folder is copied into the input folder.
- Tests collection: each document stores test metadata (
name,date,templateFolder,status,pdfPages,csvData,csvPushed, etc.). - Settings collection: one document per user (stored under the userβs UID) containing folder names and the Python command.
- CSV rows are stored as separate documents in a subβcollection:
tests/{testId}/csvRows.
| Issue | Solution |
|---|---|
| Folder picker doesn't open | Use a Chromiumβbased browser (Chrome, Edge, Brave). The File System Access API is not supported in Firefox or Safari. |
| PDF pages not counted | Ensure the PDF is not corrupted. The pdf.js library is used; check the browser console for errors. |
| Python command does nothing | This demo simulates execution. To actually run a Python script, you need to implement a backend API endpoint that executes the command securely. |
| Firebase permission errors | Update your Firestore security rules to allow reads/writes for authenticated users. |
| Environment variables not loaded | Prefix variables with VITE_ (for Vite) or REACT_APP_ (for CRA). Restart the dev server after changes. |
Contributions are welcome! Please open an issue or submit a pull request.
- Fork the repository.
- Create a new branch (
git checkout -b feature/amazing-feature). - Commit your changes (
git commit -m 'Add some amazing feature'). - Push to the branch (
git push origin feature/amazing-feature). - Open a Pull Request.
This project is licensed under the AGPL
- Firebase β Authentication & Firestore
- PDF.js β PDF rendering & page counting
- Tailwind CSS β Styling
- Font Awesome β Icons
For questions or feedback, please open an issue on GitHub.
Happy PDF processing! πβ¨


