A full-stack React + Express app that uses OpenAI to extract restaurant menu items from images and PDFs, then exports them as CSV.
npm installCopy .env.example to .env and add your OpenAI API key:
cp .env.example .envEdit .env:
OPENAI_API_KEY=sk-your-actual-openai-api-key
PORT=5000
Alternatively, enter the API key via the Settings page in the UI.
npm run serverServer starts at http://localhost:5000
npm run devFrontend starts at http://localhost:5173
npm start| Variable | Default | Description |
|---|---|---|
OPENAI_API_KEY |
— | Your OpenAI API key (required) |
PORT |
5000 |
Backend server port |
ai-menu-to-csv/
├── server/
│ ├── index.js # Express backend
│ ├── uploads/ # Uploaded files (temp)
│ └── data/
│ ├── history.json # Upload history
│ └── settings.json # App settings
├── src/
│ ├── App.jsx # React app (all pages)
│ ├── main.jsx # Entry point
│ ├── styles.css # All styles
│ └── utils.js # CSV helpers
├── .env # Environment variables
├── .env.example # Example env file
├── package.json
├── vite.config.js # Vite + proxy config
├── index.html
└── README.md
| Method | Route | Description |
|---|---|---|
| GET | /api/health |
Server health check |
| GET | /api/settings |
Get settings |
| POST | /api/settings |
Save settings |
| GET | /api/history |
Upload history |
| DELETE | /api/history/:id |
Delete history entry |
| GET | /api/stats |
Usage statistics |
| POST | /api/upload |
Upload file |
| POST | /api/process |
Process with OpenAI |
- Drag & drop upload — JPG, PNG, WEBP, PDF
- AI extraction — Uses
gpt-4.1-minivia OpenAI Responses API - PDF support — Direct PDF upload + pdf-parse text fallback
- Editable preview table — Edit/delete rows before export
- CSV export — Download or copy to clipboard
- History — Tracks all uploads with status
- Settings — Configure API key, model, limits
- JSON preview — View raw extracted JSON
- Make sure
npm run devis running on port 5173 - Check browser console for errors
- Make sure
npm run serveris running on port 5000 - The Vite proxy forwards
/api/*tohttp://localhost:5000
- Ensure your API key is set in
.envor Settings page - Check you have credits on your OpenAI account
- Model
gpt-4.1-minirequires OpenAI API access
- Enable "PDF fallback" in Settings
- Try converting the PDF to an image (JPG/PNG) instead
- The app has robust JSON parsing with multiple fallback strategies
- If a menu is very complex, try a cleaner image/scan
| Type | MIME | Notes |
|---|---|---|
| JPG/JPEG | image/jpeg | Best results |
| PNG | image/png | Best results |
| WEBP | image/webp | Good results |
| application/pdf | Falls back to text extraction |
Max file size: 10MB (configurable in Settings)