A React-based frontend for classifying playing cards using a serverless TensorFlow endpoint (AWS Lambda/SageMaker). Upload an image of a single card (JPEG/PNG), click Classify, and view the predicted card name and confidence score.
The backend is documented in a sister project, Playing Card Classifier.
- Image upload & preview: drag-and-drop or file picker, with client-side type/size validation (max 15 MB).
- OffscreenCanvas resizing: scales your image to 224 × 224 to match model input and minimize payload.
- Serverless inference: sends base64‑encoded PNG to a Lambda/SageMaker endpoint.
- Abortable requests: cancel long-running classifications with a built‑in timeout or Cancel button.
- Try Again: resets the UI for another classification round.
- Responsive UI: built with React + react‑bootstrap components.
- Node.js >= 14
- npm or yarn
- A deployed TensorFlow classification endpoint (API Gateway + Lambda/SageMaker)
-
Clone the repo
git clone https://github.com/<your‑org>/card-classifier-frontend.git cd card-classifier-frontend
-
Install dependencies
npm install # or yarn install -
Configure your API URL
Create a
.env.development.localfile in the root with your endpoint:REACT_APP_API_BASE_URL=https://<your-api>.execute-api.<region>.amazonaws.com/dev
This file is ignored by Git and overrides any
.envsettings. -
Run in development mode
npm start # or yarn startThe app will open at
http://localhost:3000. -
Build for production
Set your production API URL environment variable before building. CRA injects env variables at build time, so you need to export it in your shell or CI/CD pipeline:
export REACT_APP_API_BASE_URL=https://<your-api>.execute-api.<region>.amazonaws.com/prod npm run build
Your optimized static files land in
build/, ready to host on S3, Netlify, GitHub Pages, etc.
You can host the build/ folder on any static site service. Below are two common approaches.
npm install -g gh-pages
npm run build
gh-pages -d buildThroughout this process, please make sure to replace react-card-classifier.tarterware.com with your website. I started to make tags for these, but then the relationship between S3 and the site would be obscurred. It is assumed that you have a certificate available for the site, as the CloudFront distribution requires one. I already have a cert for *.tarterware.com, so I just reused it.
a. Create the S3 bucket (replace us-east-1 with your region):
aws s3 mb s3://react-card-classifier.tarterware.com --region us-east-1b. Configure it for static website hosting:
The index.html referenced below is the entry point generated by your React build (i.e. build/index.html). S3 will serve that file for any directory root.
aws s3 website s3://card-classifier.tarterware.com \
--index-document index.html \
--error-document index.htmlc. Sync your build output:
aws s3 sync build/ s3://card-classifier.tarterware.com --deleted. Create CloudFront distribution:
Before executing the following, make sure you replace all occurences of <ACCOUNT-ID> with your Amazon account, and <CERTIFICATE-ID> with the certificate ID.
aws cloudfront create-distribution \
--distribution-config file://infra/distribution-config.jsone. Add policy to allow CloudFront to access the bucket:
Before executing the following, make sure you replace with your Amazon account ID, and with the CloudFront Distribution ID.
aws s3api put-bucket-policy --bucket card-classifier.tarterware.com --policy file://infra/bucket-policy.jsonTo fully remove your distribution before re-creating:
-
Disable the distribution (set
Enabled=false).# Fetch current config and ETag ETAG=$(aws cloudfront get-distribution --id <YOUR_DISTRIBUTION_ID> --query ETag --output text) aws cloudfront get-distribution-config --id <YOUR_DISTRIBUTION_ID> > dist-config.json # In dist-config.json, set "Enabled": false at the top-level # Then update: aws cloudfront update-distribution \ --id <YOUR_DISTRIBUTION_ID> \ --if-match "$ETAG" \ --distribution-config file://dist-config.json
-
Wait for the distribution to deploy in a Disabled state (status:
Deployed). You can poll:aws cloudfront get-distribution --id <YOUR_DISTRIBUTION_ID> \ --query "Distribution.Status" --output text
Repeat until it returns
DeployedandDistribution.DistributionConfig.Enabledisfalse. -
Delete the distribution using the latest ETag:
ETAG=$(aws cloudfront get-distribution --id <YOUR_DISTRIBUTION_ID> --query ETag --output text) aws cloudfront delete-distribution \ --id <YOUR_DISTRIBUTION_ID> \ --if-match "$ETAG"
| Variable | Description |
|---|---|
REACT_APP_API_BASE_URL |
Base URL for the prediction endpoint |
/ # Repo root
├── infra/ # Infrastructure-as-code & policies
│ ├── distribution-config.json # CloudFront distribution config
│ ├── bucket-policy.json # S3 bucket policy for OAC
├── build/ # Generated by `npm run build`
├── public/ # CRA public assets
│ └── index.html # HTML template
├── Resources/ # README screenshots and other images
├── src/ # React application source
│ ├── CardClassifier.jsx # Main classifier component
│ ├── App.js # App shell
│ ├── index.js # Entry point (imports global CSS)
│ ├── index.css # Global styles & Bootstrap import
│ └── App.css # Component-specific overrides
├── .env.example # Template for environment variables
├── package.json # npm manifest & scripts
└── README.md # Project documentation
- Spinner not animating: ensure your Bootstrap CSS is imported in
src/index.jsbefore any custom CSS:import "bootstrap/dist/css/bootstrap.min.css"; import "./index.css";
- File picker not clearing: the Try Again button resets the internal state and programmatically clears the file input.
- CORS errors: confirm your API Gateway/CORS settings allow
Content-Type: application/jsonfrom your origin. There are many.
- Fork the repo.
- Create a feature branch (
git checkout -b feature/XYZ). - Commit your changes (
git commit -am 'Add XYZ'). - Push to your branch (
git push origin feature/XYZ). - Open a pull request.
This project is licensed under the MIT License. See LICENSE for details.
Happy classifying!
