Full-stack recipe collector: paste any online recipe URL, the backend scrapes and normalizes it, stores it in MariaDB, and the frontend renders a clean, unified view with filtering and deletion.
backend/— Express API, MariaDB pool + scraperfrontend/— vanilla HTML/CSS/JS UI (served by the backend)
- Node.js 20.18.1+ (Cheerio/undici dependency chain requires this)
- MariaDB instance you can reach from where the API runs
cd recipes-app/backendcp .env.example .envand set values:DB_HOST=your_host DB_PORT=your_port DB_USER=your_user DB_PASSWORD=your_password DB_NAME=recipes_app PORT=4000 # or any port you prefer ALLOW_ORIGIN=* # lock down in production- Install deps:
npm install - Start API + static frontend:
npm run dev(ornpm startfor production) - Open
http://localhost:4000to use the app.
The server creates the recipes table on startup if needed.
GET /api/recipes?q=— list recipes (optional search on title/source)GET /api/recipes?archived=true— list archived recipesGET /api/recipes/:id— fetch a recipePOST /api/recipes/import— body{ "url": "https://..." }to scrape + storePUT /api/recipes/:id— edit/update a recipePOST /api/recipes/:id/archive— archive instead of deletePOST /api/recipes/:id/unarchive— restore from archiveGET /api/health— health check
Responses are normalized to a common shape with ingredients/instructions arrays.
- Backend serves the static frontend from
frontend/; deploy the backend container/app and keep env vars pointed at the OSC MariaDB instance. - CORS is permissive by default (
ALLOW_ORIGIN=*). Restrict in production. - Connection pooling is enabled via
mysql2with sensible defaults; tuneconnectionLimitif needed. - If you redeploy or rotate credentials, update the
.envand restart.
- Modern, responsive layout with filter box, delete controls, and a unified detail view.
- Normalized presentation of prep/cook/total time, servings, ingredients, and instructions.
- Works without bundlers; plain HTML/CSS/JS.