尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Know what to ask for, wherever you land — local medicine brand names for travelers
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Know what to ask for, wherever you land. — live at https://rxabroad.vercel.app
Every drug has one international name (its INN) and a different local brand name almost everywhere you go. Rx Abroad covers 82 common medicines across 15 destinations (India is hidden for now). Search a brand, a generic name, or a country to see what to ask for at the pharmacy counter and whether it's OTC, prescription-only, pharmacist-only, controlled, or banned.
Destinations: US, UK, Canada, Germany, France, Mexico, Ethiopia, Japan, Vietnam, Singapore, Morocco, Portugal, Türkiye, Italy, Spain. (India's entries are kept but hidden.)
/?q=claritin&c=JP,FR,
/?s=cough&c=VN)./drug/paracetamol, /country/japan, /symptom/travelers-diarrhea), with its own title and description
for search engines. There is also a sitemap./my-meds). Pick your medicines and a destination to get a printable one-page
card with the local name to ask for and any cautions. Your list is saved only in your browser.npm install
npm run dev # http://localhost:3000
npm run build # every drug, country and symptom page is statically generated
npm run lint
Built with Next.js 16 (App Router), React 19, Tailwind CSS v4 and shadcn/ui
(Radix base, Nova preset). The "passport" theme lives in src/app/globals.css: color tokens for light
(passport paper) and dark (night flight), rubber-stamp status styles, and print rules. Add more shadcn
components with npx shadcn@latest add <name>. There's no backend.
Sign-in uses Clerk (@clerk/nextjs, themed with @clerk/ui's shadcn theme). Signed-in travelers can
save trips (medicines + ordered destinations) to a Neon Postgres database and open them on any device;
while a trip is open, changes autosave. Without an account the travel card still works, stored in the
browser only.
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY) and the Neon DATABASE_URL come from
.env.local locally and from Vercel environment variables when deployed. Never expose CLERK_SECRET_KEY
to client code.src/proxy.ts runs clerkMiddleware(); routes are public, and the trip server actions check the user.db/migrations/*.sql; apply with npm run db:migrate (runs each file once).
trips.user_id is the Clerk user id (user_...). User profiles stay in Clerk (not copied to Neon).src/app/my-meds/actions.ts; every query is scoped to the
signed-in user's id, and input is validated against the real country codes and drug ids.src/app/api/webhooks/clerk/route.ts receives Clerk's user.deleted webhook and
deletes that user's trips (trips have no foreign key to Clerk). Requests are signature-verified with
CLERK_WEBHOOK_SIGNING_SECRET; register the endpoint https://<site>/api/webhooks/clerk (event
user.deleted) in the Clerk Dashboard → Webhooks, and set the secret in Vercel.npx clerk doctor checks the setup; npx clerk config pull shows sign-in settings.public.search_misses (search text and a count only), so the next medicines added are the ones people look for.public.feedback.npm run feedback (last 30 days; -- --days 90 for more).Offline verification. node scripts/verify/run.mjs <US|CA|SG|FR|GB|JP|DE|MX|IT|ES|TR|VN|ET|PT> checks one country's entries against
its official registry and writes the evidence and every mismatch to research/verification/<CC>.json.
That is a dry run; add --write to update drugs.json. Nothing here runs when the site is built or served.
| Country | Registry | What it confirms |
|---|---|---|
| US | RxNorm + openFDA NDC | brand ↔ ingredient, ATC code, OTC / Rx / DEA schedule |
| CA | Health Canada DPD | brand ↔ ingredient, marketed status, schedule |
| SG | HSA register on data.gov.sg | brand ↔ ingredient, GSL / Pharmacy Only / Prescription Only |
| FR | BDPM | brand ↔ ingredient, marketed status, prescription conditions |
| GB | MHRA Products + NHS dm+d | MHRA: brand ↔ ingredient for licensed products. dm+d: legal category (GSL / P / POM) and controlled-drug schedule of packs on the market. dm+d needs a free NHS TRUD account: put the key in .env.local as TRUD_API_KEY. Without it the UK check is brand-only |
| JP | MHLW drug price list | Brand ↔ ingredient for prescription products covered by national insurance, which confirms an Rx status. It has no over-the-counter products, so OTC entries can't be confirmed, and it can't see an OTC twin of an Rx brand. Controlled-drug scheduling is checked by hand against the Narcotics Control Department list |
| DE | AMIce (BfArM) |
Every check is free and needs no key, apart from the UK's legal-status step. --write is deliberately conservative: it never edits brand, status
or note; it attaches verified when the registry confirms the entry; and it raises confidence to high
only when the registry confirms everything the entry claims (brand, ingredient and legal status; for a "sold generic" entry with no brand, ingredient and legal status). An entry marked low that the registry confirms only in part goes to medium, so nothing verified keeps the "unconfirmed" mark. It never lowers confidence. A registry shows that a
product is registered, not that a given pharmacy stocks it. After a run, refresh the report with
node scripts/confidence-report.mjs. To add a country, write an adapter next to the others (open() and
verify()) and register it in run.mjs.
Keeping it current. Registries change (the NHS dictionary weekly, the others every few weeks), so re-run the checks about once a month. A scheduled cloud routine ("Rx Abroad monthly registry check", the 1st of each month) does a dry run and reports what changed at https://claude.ai/code/routines; it can't see the TRUD key, so it skips UK legal status. To update the data yourself:
cd ~/dev/pill-trotter).npm run verify is a dry run of all fifteen checked countries. It changes no data, only the report files in
research/verification/, and takes about half an hour on the first run, most of it Germany, Portugal and Vietnam
(results are cached for a day).npm run verify:write does the same and also updates src/data/drugs.json and the confidence report.research/verification/ and check git diff src/data/drugs.json. The script
never edits brand, status or note: those mismatches are yours to decide.main deploys to Vercel.The UK legal-status step needs a free NHS TRUD account: subscribe to the "NHSBSA dm+d" item and put the key in
.env.local as TRUD_API_KEY=... (the file is git-ignored). Without it a dry run still works but notes that
legal status was skipped, and --write refuses for the UK so it can't overwrite the full check with a partial
one. India has no registry check and is hidden from the site: every abdm.gov.in host, including the Drug Registry, blocks connections from outside India.
The cloud routine runs in the "Default" cloud environment, whose network access is set to Custom so it can reach the
registries: rxnav.nlm.nih.gov, api.fda.gov, health-products.canada.ca, data.gov.sg,
base-donnees-publique.medicaments.gouv.fr, mhraproducts4853.search.windows.net, www.mhlw.go.jp, portal.bfarm.de, auth.bfarm.de, registros.cofepris.gob.mx, api.aifa.gov.it, cima.aemps.es, titck.gov.tr, www.titck.gov.tr, dichvucong.dav.gov.vn, api.eris.efda.gov.et, www.efda.gov.et, extranet.infarmed.pt and www.ammps.gov.ma, plus the default package
list. If a run reports HTTP 403 from a registry, check that list first.
Live lookup. GET /api/rxnorm/resolve?q=<name> (src/app/api/rxnorm/resolve/route.ts, logic in
src/lib/rxnorm.ts) resolves a US medicine name to its ingredients and maps them to formulary drugs through
each drug's rxcui. RxNorm allows browser calls and needs no key, so this route isn't hiding a secret: it
turns three chained requests into one and lets the CDN cache each answer for a day, which is what NLM asks
of API users (limit: 20 requests per second per IP). The search box only calls it when a query has no
local match. The route is excluded from the Clerk matcher in src/proxy.ts, so lookups carry no session.
| Path | What |
|---|---|
src/data/drugs.json | The formulary: 82 drugs × 16 countries (India's entries are kept but hidden from the site: hidden in src/data/countries.ts). A drug's optional kit field puts it in a travel-essentials group (src/data/kit.ts); drugs without one are listed under "Other". Its optional symptoms list says what it is sold for (src/data/symptoms.ts). Edit this to change the data. |
src/data/countries.ts, status.ts, types.ts | Countries (with URL slugs), status labels, types |
src/lib/search.ts | Search matching and country narrowing |
src/components/ | App components (ui/ holds the shadcn components) |
src/app/ | Routes: /, /drug/[id], /country/[slug], /symptom/[slug], /my-meds, /sign-in, /sign-up, sitemap, robots |
src/lib/auth.ts, src/lib/db.ts, db/migrations/ | Clerk user helper, Neon database client, schema |
src/lib/rxnorm.ts, src/app/api/rxnorm/resolve/ | US name lookup through RxNorm |
scripts/verify/ | Registry verifiers: run.mjs, shared lib.mjs, one adapter per country |
scripts/confidence-report.mjs | Rebuilds research/confidence-by-country.md |
research/verification/ | Evidence and mismatches from the last verifier run, per country |
scripts/extract-data.mjs | One-time import from the original single-file prototype |
research/ | Scripts and reports from the original data research (Health Canada DPD, French BDPM, …) |
Each drug in drugs.json looks like this:
{
"id": "paracetamol", "generic": "Paracetamol", "usAlt": "Acetaminophen (APAP) in the US",
"cls": "Analgesic / antipyretic", "atc": "N02BE01", "rxcui": "161",
"countries": {
"FR": { "brand": "Doliprane", "status": "OTC", "confidence": "high", "note": null, "source": null }
}
}
status is one of OTC, RX, MIXED, PHARMACY, CONTROLLED, BANNED, UNCONFIRMED, ASK_GENERIC, UNAVAILABLE (not marketed in that country).confidence is high, medium (shows †), or low (shows ?).rxcui (RxNorm ingredient id) and each entry's optional verified block are written by
scripts/verify/run.mjs. Don't edit them by hand; re-run the verifier instead.The data was imported from the original prototype (then called Pill Trotter), pill-trotter-aug27.html, which has the verified India
research. To check that the import still matches the prototype, run
node scripts/extract-data.mjs --check ~/pill-trotter/pill-trotter-aug27.html.
This is seed data for a prototype, compiled from general pharmacology knowledge. It is not a live regulatory feed. Brand names, availability, and prescription status change, and they vary by region and even by pharmacy. Confirm with a local pharmacist or physician before relying on this while traveling.
This product uses publicly available data from the U.S. National Library of Medicine (NLM), National Institutes of Health, Department of Health and Human Services; NLM is not responsible for the product and does not endorse or recommend this or any other product.
| Brand ↔ ingredient for marketable medicines, and their legal class of sale: pharmacy-only, prescription or narcotic prescription. It has no download, so the check runs about 230 searches on its web form, four at a time; a first run takes several minutes. Nearly every German non-prescription medicine is pharmacy-only, so an "OTC" entry is confirmed when no prescription is needed |
| MX | COFEPRIS medicine register | Brand ↔ ingredient for current registrations, and the legal class of sale (Fracción I to VI: narcotic, psychotropic, prescription, pharmacy-only, free sale). Read from the "Base Completa" spreadsheet; the search form is behind a captcha and is not used. The file may be incomplete and uses local spellings (Elicuis, Jardianz), so a missing brand is reported but proves nothing |
| IT | AIFA medicines database | Brand ↔ ingredient for marketed packs, and the supply class of each: OTC, SOP (no prescription, behind the counter), prescription, or narcotic prescription. Searched by Italian ingredient name, 20 results a page |
| ES | CIMA (AEMPS) | Brand ↔ ingredient for marketed products, and the prescription condition: no prescription, prescription, narcotic or psychotropic. Searched by ATC code |
| TR | TİTCK licensed products list + e-prescription list | Brand ↔ ingredient for licences in force, read from two spreadsheets the agency reissues every week. The e-prescription list gives each pack's prescription type, so a red or green prescription confirms a controlled status. Neither list says whether an ordinary product needs a prescription, so OTC, pharmacist-only and prescription statuses are not compared |
| VN | Drug Administration of Vietnam register | Brand ↔ ingredient for registrations that have not expired. Registrations issued since 2023 are marked non-prescription or prescription, which confirms those two statuses; older ones carry no class. Nothing marks controlled medicines. Searched by ingredient name, in both English and Vietnamese spellings |
| ET | EFDA register + Over-the-Counter Medicines List | Brand ↔ ingredient for approved medicines, from the register's one-file export. Legal status comes from the OTC list (third edition, July 2022): on it means no prescription, anything else needs one. The list is a PDF, so its entries for our medicines are keyed into et-eris.mjs by hand. Each run checks the PDF is unchanged and refuses --write if EFDA has replaced it |
| PT | Infomed (INFARMED) | Brand ↔ ingredient for marketed products, and the dispensing class: no prescription, no prescription but pharmacy only, prescription, or special prescription. It has no download, so the check runs about 330 searches on its web form; a first run takes about 12 minutes. Benzodiazepines are on an ordinary prescription there, so that class does not contradict a controlled entry |
| MA | Liste Marocaine des Médicaments (AMMPS) | Brand ↔ ingredient, and whether a product is on sale ("Commercialisé"). Rows marked "Commercialisé AO" or "Commercialisé Export" don't count. It has no legal class, so status is not checked. A public search page, about 6 minutes uncached |