Agentero
Connect your own Agent, keep research context in a local Vault. Seamlessly migrate from Zotero, read, understand, link, and reuse your research context.
AI translation
Add notes to a grocery list and track items you forgot
AI summary · website content
ProductivityTypeScript · CSSGitHub @ybaryshevaOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A shared, phone-friendly grocery list for Amazon Fresh and Netcost Market.
/ is the shared page. Anyone with the link can leave a note on an item, add something, or remove an item with its × button. No sign-in. A removed item moves to a Removed card at the bottom of its store tab (with Put back), and is listed in the export as "Removed (don't order)" so Claude knows not to buy it. Removals last for the round only; the item itself isn't changed./edit is where the list is managed: edit items, import a new list, mark it final, copy it for Claude, start a new round./api/export is the read-only order that Claude reads to place the orders.There are no accounts. Anyone with the link can read and write, by design. Writes are rate limited per IP (30 a minute), and pages are marked noindex.
Next.js (App Router, TypeScript), plain CSS, and Upstash Redis from the Vercel Marketplace for storage. Runtime dependencies: next, react, react-dom, @upstash/redis.
npm install
npm run seed # first run only; loads data/seed.json
npm run dev # http://localhost:3000
Without Upstash credentials, local dev stores everything in .data/local-db.json (git-ignored). To use the real store locally instead:
vercel link
vercel env pull .env.local
npm run dev
vercel link then connect the repo under Project, Settings, Git). Pushes to main deploy production.KV_REST_API_URL and KV_REST_API_TOKEN on the project. UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN also work.vercel env pull .env.local && npm run seed. It only writes when the store has never been seeded and has no items. Running it again changes nothing.On Vercel, if the Redis env vars are missing, the API returns a clear "Storage isn't connected" error instead of silently using a file.
The list lives in Redis and changes only through /edit. data/seed.json is a first-run starting point only: the app never reads it, and deploys never reset the list.
On /edit you can:
Paste a JSON array of items:
[
{"store": "Amazon Fresh", "section": "Produce", "name": "Bananas"},
{"store": "Netcost", "section": "Deli", "name": "Doktorskaya", "size": "about 0.5 lb"}
]
store ("Amazon Fresh" or "Netcost"), section, name.id, size, price, imageUrl, sort, active (defaults to true).price is free text up to 40 characters, e.g. "$5.49", "$7.69/lb" or "$6.49/lb sale, reg. $7.69". The server records when each price was set (priceAt); you never send that.id when given, otherwise by store + name (case-insensitive). Matched items keep their id, their photo and price (unless a new imageUrl / price is given) and any note. To clear a price, edit the item on /edit. Unmatched entries become new items. Existing items not in the paste are removed, along with their notes.sort means the order in the pasted array.Entry 4 ("kefir"): same store and name as entry 3.GET /api/export returns JSON:
{
"generatedAt": "2026-10-25T18:10:00.000Z",
"status": "final",
"finalizedAt": "2026-10-25T18:10:00.000Z",
"orders": [
{
"store": "Amazon Fresh",
"items": [{"store": "Amazon Fresh", "section": "Produce", "name": "Blueberries", "size": null, "price": "$4.99", "priceAt": "2026-10-25T21:50:00.000Z", "note": "get 2"}],
"adds": [{"store": "Amazon Fresh", "text": "Milk"}],
"removed": [{"store": "Amazon Fresh", "section": "Meat and fish", "name": "Steak", "size": "about 1.5 lb"}]
},
{"store": "Netcost", "items": [], "adds": [], "removed": []},
{"store": "Either", "items": [], "adds": [{"store": "Either", "text": "Paper towels"}], "removed": []}
]
}
GET /api/export?format=text returns text/plain; charset=utf-8:
Grocery order (status: final, Oct 25, 2026 2:10 PM)
AMAZON FRESH
Produce
- Bananas
- Blueberries ($4.99; note: get 2)
Meat and fish
- Chicken thighs, boneless skinless, about 6 lb (2 packs)
Added
- Milk
Removed (don't order)
- Steak, about 1.5 lb
NETCOST
...
EITHER STORE
- Paper towels
;. Adds go under "Added" in their store; "Either" adds get their own block. Items taken off with × go under "Removed (don't order)" in their store. A store with nothing on it is left out.(status: draft).Cache-Control: no-store, Access-Control-Allow-Origin: *.One hash field per record, so concurrent writes to different items, notes or adds never overwrite each other:
| Key | Type | Contents |
|---|---|---|
g:items | hash | item id → {id, store, section, name, size?, imageUrl?, price?, priceAt?, active, sort} |
g:notes | hash | item id → {text, updatedAt} |
g:adds | hash | add id (client UUID) → {id, store, text, createdAt} |
g:meta | hash | status, finalizedAt, seededAt |
g:removed | hash | item id → {removedAt}: taken off this round's order |
g:rounds | list | newest first: {id, date, notes[{store,item,text}], adds[{store,text}], removed[{store,item}]} |
g:rl:<ip>:<minute> | counter | write rate limit, expires after 70s |
g:items in one MULTI/EXEC transaction, guarded by a fingerprint taken at preview./api routes are force-dynamic and send no-store.price (free text). It shows under the item on both pages in gray italics, under a "Prices are estimates." note, with its "as of" date on /edit, and in the export./edit. It adds the first dollar amount of each item's price; /lb prices are multiplied by the item's listed weight (1 lb if none). Removed items and free-text adds aren't counted./edit, or include price in the JSON you paste into Import.