A mobile-first web app that lets you photograph second-hand products, generate complete WooCommerce listings with Claude AI, and publish them in seconds — without touching the slow WordPress admin.
Running on Android Chrome. The app lives entirely inside the browser — no native install required.
📱 Camera / gallery
│
▼
Sharp — detect orientation
Portrait → 9:16 → 720×1280
Landscape → 16:9 → 1280×720 (smart attention crop, WebP q80)
Square → 1:1 → 1080×1080
│
▼
WP REST API ──────────────────► WordPress Media Library
/wp-json/wp/v2/media (real attachment ID returned)
│
▼
Claude claude-sonnet-4-6 ──────► Full product listing
researches specs + user notes title / descriptions / SKU / tags / price
+ analyses uploaded photos
│
▼
User reviews & edits
│
▼
WC REST API ───────────────────► WooCommerce product (live instantly)
/wp-json/wc/v3/products handles all DB writes + cache + hooks
┌─────────────────────────────────────────────────────────┐
│ SecondSell App (Railway) │
│ │
│ POST /api/auth/login → cookie-based session auth │
│ POST /api/upload → Sharp + WP REST API │
│ POST /api/ai/describe → Claude claude-sonnet-4-6 │
│ GET /api/products/categories → WC REST API │
│ POST /api/products → WC REST API │
│ GET /api/health → WP/WC reachability check │
│ │
│ public/ (vanilla JS, mobile-first, no bundler) │
└──────────┬──────────────────────────────────────────────┘
│ WP/WC REST API
▼
WordPress + WooCommerce
(images + products)
| Requirement | Notes |
|---|---|
| WordPress 5.6+ | Application Passwords feature |
| WooCommerce 3.7+ | wp_wc_product_meta_lookup table |
| HTTPS on WordPress | Required for Application Passwords |
| Anthropic API key | console.anthropic.com |
git clone <repo> && cd secondsell
npm install- WP Admin → Users → Edit your profile
- Scroll to Application Passwords
- Name:
SecondSell→ Add New Application Password - Copy the generated password — it's shown once
- WP Admin → WooCommerce → Settings → Advanced → REST API
- Add key — Description:
SecondSell, User: admin, Permissions: Read/Write - Copy the Consumer Key and Consumer Secret
cp .env.example .envWP_URL=https://your-wordpress-site.com
WP_USER=your-wp-username
WP_APP_PASSWORD="xxxx xxxx xxxx xxxx xxxx xxxx"
WC_CONSUMER_KEY=ck_...
WC_CONSUMER_SECRET=cs_...
BASIC_AUTH_USER=admin
BASIC_AUTH_PASS="your-app-password"
ANTHROPIC_API_KEY=sk-ant-...Note: If your password contains
#,!, or other shell-special characters, wrap it in double quotes in.env.
npm run dev
# → http://localhost:3000For camera access on iOS/Android, use HTTPS (e.g. ngrok) — browsers require HTTPS for getUserMedia.
- Push to GitHub
- Railway → New Project → Deploy from GitHub repo
- Set all env vars in Railway → Service → Variables
No Railway Volume needed — images live in WordPress's own media library.
/
├── images/ ← screenshots and documentation assets (committed to git)
├── public/ ← frontend (vanilla JS, mobile-first, no bundler)
│ ├── index.html
│ ├── login.html
│ ├── css/style.css
│ └── js/app.js
├── routes/ ← Express route handlers
│ ├── upload.js ← Sharp pipeline + optional background removal
│ ├── ai.js ← Claude claude-sonnet-4-6
│ ├── products.js ← WooCommerce product/category API
│ ├── auth.js ← Login / logout
│ └── health.js ← WP/WC reachability check
├── middleware/auth.js ← HMAC-SHA256 cookie session guard
├── utils/wcApi.js ← WP + WC REST API client
├── server.js ← Express app entry point
└── .env.example ← environment variable template
| Input orientation | Detected by | Cropped to | Output |
|---|---|---|---|
| Portrait (tall) | ratio < 0.80 | 9:16 | 720 × 1280 WebP |
| Landscape (wide) | ratio > 1.25 | 16:9 | 1280 × 720 WebP |
| Square / near-sq | 0.80 – 1.25 | 1:1 | 1080 × 1080 WebP |
- Crop strategy:
sharp.strategy.attention— analyses saliency and entropy to keep the focal point centred. - Never upscaled: small images stay small.
- EXIF rotation applied before any resize.
- WebP quality 80 — typically 40–120 KB per image.
{ "username": "admin", "password": "secret" }Sets ss_session cookie on success.
Returns live WooCommerce categories:
{ "success": true, "categories": [{ "id": 15, "name": "Electronics", "count": 8 }] }Optimise + upload images to WordPress media library.
Request: multipart/form-data, field images, up to 10 files.
Response:
{
"images": [
{
"id": 247,
"url": "https://site.com/wp-content/uploads/2026/03/uuid.webp",
"width": 720,
"height": 1280,
"orientation": "portrait",
"aspect": "9:16",
"sizeKb": 68
}
]
}Generate a product listing with Claude. Passes uploaded image URLs as vision content.
Request:
{
"productName": "Sony WH-1000XM4",
"condition": "good",
"userContext": "Includes case and USB-C cable",
"imageUrls": ["https://..."]
}condition: new | like_new | good | fair | poor
Create a WooCommerce product via REST API.
Request:
{
"title": "Sony WH-1000XM4 Wireless Headphones",
"shortDescription": "Industry-leading ANC, 30h battery.",
"fullDescription": "<h3>Overview</h3><p>…</p>",
"price": "185.00",
"sku": "SH-SONY-WH1000XM4-001",
"quantity": 1,
"categoryId": 15,
"images": [{ "id": 247, "url": "https://…" }],
"tags": ["sony", "headphones"]
}{
"status": "ok",
"wpUrl": "https://site.com",
"wpApi": "reachable",
"wcApi": "configured",
"claude": "configured"
}| Symptom | Cause | Fix |
|---|---|---|
| Login fails | # in password not quoted |
Wrap BASIC_AUTH_PASS in double quotes in .env |
| Upload 401 | Wrong WP_USER / WP_APP_PASSWORD |
Regenerate WordPress Application Password |
| Upload 403 | REST API blocked by security plugin | Wordfence → allow REST API; re-save Permalinks |
| Product 401 | Wrong consumer key/secret | Regenerate WC API key with Read/Write |
| Product 403 | Key is Read-only | Edit key → set Permissions to Read/Write |
| AI fails | Wrong/truncated API key | Copy full key from console.anthropic.com |
| Wrong crop | EXIF not applied | Sharp .rotate() is called first — should be handled |
├── server.js
├── middleware/auth.js HMAC-SHA256 cookie session
├── routes/
│ ├── auth.js Login / logout
│ ├── upload.js Sharp optimise → WP media
│ ├── ai.js Claude description + vision
│ ├── products.js WC categories + product creation
│ └── health.js System status
├── utils/
│ └── wcApi.js WP + WC REST API client
├── public/
│ ├── index.html 4-step mobile UI
│ ├── login.html Login page
│ ├── css/style.css Mobile-first glassmorphism styles
│ └── js/app.js Vanilla JS
├── specs/ Feature specifications
├── CLAUDE.md AI coding guide
├── CONSTITUTION.md Project rules
└── .env.example
- All credentials in environment variables — never in source code
- Cookie session uses HMAC-SHA256 — no plaintext tokens
- WP Application Password is scoped and revocable
- WC API key is scoped to Read/Write products only
- Multer enforces
image/*type and 30 MB size limit - Sharp processes all uploads in memory — raw bytes never written to disk
- API responses never include stack traces
Eduardo Arana & Soda [bot]
MIT
