- Results in groups: شعرا و ادبا (by name or pen name, with years, work counts and a 'search in their
works' link), کتابیں اور ابواب (books/chapters by title), and کلام (content).
- Content pages: numbered pagination (first, last, two either side, gaps) and 'نتائج ۴۱–۶۰ از ۸۱۱۶'.
- Author filter: chips for the authors the results come from, with counts; tick one or several to
narrow; a name box finds any other poet/writer, with the Urdu keyboard and Roman-to-Urdu typing.
The keyboard and Roman typing now work on any input marked data-urdu, not only the search box.
- API: poet=1,2 (several), authors with counts, poets and books on page 1 (api/src/search.ts).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner request. Saved state: filled accent-coloured glyph, bold accent text and border, light accent
tint; the label follows the state on load and on click. The selection menu's phrase option and the
couplet bookmark's label use the same words.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner reference: a Flaticon bookmark pack (similar, not the same). Drawn here, so no third-party
licence or attribution; grey outline when not set, filled brand colour when set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Material Design 'bookmark' / 'bookmark_border' (Apache-2.0) drawn as a CSS mask so it follows the
theme; replaces the 🔖 emoji on bookmark buttons, couplet bookmarks, bookmarked phrases, contents
lists and cards, and the نشانات tab.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner direction: the word collection is separate from bookmarks, and bookmarks use the bookmark
glyph, not hearts.
- 🔖 نشان buttons on poet, book/chapter (new) and poem pages; contents lists and cards show 🔖.
- /library (نشانات): bookmarked poets, books and chapters, poems, couplets, phrases.
- /words (ذخیرۂ الفاظ): the word book on its own page; tabs between the two; header links.
- Word button: 'ذخیرۂ الفاظ میں ڈالیں' (+), 'ذخیرۂ الفاظ میں ہے' (✓) once added.
- API: library kind 'category' (books and chapters) in toggle, state, marks and the list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner request: words are not favourites. The sidebar button reads '+ ذخیرۂ الفاظ میں' and turns
into '✓' once added; the selection menu has '+ لفظ'; the library section is ذخیرۂ الفاظ.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Select any part of a couplet or paragraph and press نشان (selection menu): the phrase is
bookmarked and shown underlined with a small 🔖, also across the two misras; clicking it removes
the bookmark (with a confirmation). Listed in the library as نشان زدہ عبارتیں.
- Contents lists show ♥ on favourite works and 🔖 on works holding bookmarks; book/section cards and
poet cards (home) show 🔖 when they hold any. API: GET /api/library/marks; phrases in state and
library; phrase kind validated against the couplet's text.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Save (♡) poets and works, bookmark (🔖) couplets and paragraphs, save words from the word sidebar
or the selection menu (with the couplet they came from); notes on items.
- /library (میری لائبریری): the reader's name and bio, then favourite poets, works, bookmarked
couplets and saved words, each with its full path (poet » book » section » work) and a link to
the couplet (#cN anchors on poem pages); saved words open the word sidebar.
- API (api/src/library.ts), JSON + Bearer tokens so mobile apps (#44) can use it; deleting an
account deletes its library. Signed-out readers are sent to sign-in.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Readers write their full name and a short bio (Urdu or any text) on /account; the name heads the
account page and the header shows the first name. API: POST /api/auth/profile (trimmed, control
characters dropped, 100 and 1,000 characters).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Roles: reader, mod-l2, mod-l1, admin. Grants: scope (all, poet, book/section with everything in
it, one work) x content (poets, books, works, dictionary) x actions (create, edit, delete,
arrange); dictionary grants are site-wide. can() in api/src/permissions.ts is the one check.
- Admin API and pages: role dropdown on /admin; /admin/user/:id lists a moderator's grants, adds
them (target by poet id or page link) and revokes them; demoting a moderator clears their grants;
grant and revoke go to the audit log.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- API (api/src/admin.ts, admins only): user list and search; password reset generates a temporary
password shown once and ends the user's sessions; disable/enable (ends sessions, blocks sign-in);
roles reader/admin; delete; an admin cannot disable, demote or delete themself. Every action is
written to audit_log (kept when users are deleted).
- First admin from the server: npm run make-admin -- <email> (after signing up).
- Site: /admin (users) and /admin/audit; 'ایڈمن' link in the header for admins.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- API (api/src/auth.ts): scrypt password hashes; random session tokens stored only as SHA-256;
30-day sliding sessions; rate limits on sign-in (per IP and per email) and sign-up; changing the
password signs out other devices; deleting the account removes its data.
- Site: /signup, /signin (returns to the page the reader came from), /account; header link; plain
forms, no JavaScript needed. Session in an HTTP-only, SameSite=Lax cookie (Secure over HTTPS).
- CSRF: Astro's origin check, with the site's hostnames listed (SITE_HOSTS) so its own form posts
pass and other sites' are refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Selecting reading text shows a menu by the selection: معنی (word sidebar, single words),
تلاش (search Divan, phrases quoted), کاپی (text with poet, title and link), شیئر (link to the
page with the selection highlighted via ?hl=; native share sheet where available), قرآن
(tanzil.net), گوگل. Escape or clearing the selection closes it; no layout shift.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Panel folds the extras (more meanings, examples, long etymologies, long word lists). 175 MB in PostgreSQL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- readings: one spelling, different short vowels (ملک: مَلَک، مَلِک، مِلک، مُلک), each with form,
transliteration, IPA, audio and meanings
- always: same consonants with other long vowels (consonant-skeleton regex)
- not found: inflection stems (آنکھوں -> آنکھ, جاتے -> جانا), prefix regex, trigram similarity
- Persian/Arabic words with no Urdu entry: Urdu translations via English first, then English, then
their own language; filler glosses (especially, usually…) dropped
- punctuation, dashes and spaces dropped from selected words and lookup keys; clean titles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- en.wiktionary entries via kaikki.org (meanings, IPA, transliteration, audio, etymology, synonyms)
- ur./fa./ar.wiktionary dumps for meanings in each language (incl. more Urdu entry formats)
- English->Urdu pivot table from Urdu entries' glosses and ur.wiktionary's English entries
- dict-sync.ts: re-imports sources when upstream publishes new files, applies daily recent changes;
run from deploy/sync.sh
- lookups now read the database (2-7 ms) instead of calling Wikimedia live
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Urdu, Persian and Arabic Wiktionaries in that order, each labelled; English meanings, IPA,
transliteration and audio from en.wiktionary; Urdu equivalents pivoted through English when Urdu
Wiktionary has no entry. Cached in PostgreSQL for 30 days. Left panel on wide screens, bottom
sheet on phones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- @fontsource/noto-naskh-arabic and noto-nastaliq-urdu bundled with the site; no Google
Fonts request (Brave Shields blocked it, so the switch had nothing to switch to)
- ?font=nastaliq|naskh sets the reading font (shareable links)
Validated: both fonts render from local files in headless Chromium; no googleapis requests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- poets.pin_order; editorial list in db/featured.sql, applied after every import
- home page shows the pinned row first, like Ganjoor
- Faiz is not included: his work is under copyright until 2035, so not in divan-data
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- web/: server-rendered Astro over the Node API: home (poets by Hijri century), poet
(intro + sections), category (numbered contents), poem (couplets, prev/next, source),
search (paged); Naskh default with Nastaliq toggle, light/dark, Urdu digits, RTL, mobile
- api: section counts include nested categories
- README: how to run v2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>