Adapt to NGM Index v2 + rebrand to the Jawafdehi identity - #21
Conversation
The backend now emits one consolidated manuscript per logical document with a roled `links` array (RAW/ALTERNATE/SOURCE_PAGE/MARKDOWN), a `document_id`, and a `source_type`; the old `url`/`file_name` remain as a back-compat alias. - Extend the Manuscript type with links/document_id/source_type and add fileLinks/linkByRole/primaryUrl/extFromUrl helpers that fall back to the legacy `url` (so old index snapshots still render during rollout). - Press releases: drop the client-side group-by-press_id (the backend now consolidates); render each release's attachments from `links`, plus a transcript (MARKDOWN) and Source (SOURCE_PAGE) link when present. De-dup by press_id is kept only to tolerate legacy snapshots. - Court orders: one row per case, rendering all its file links. - Kanun Patrika / CIAA reports: read links via primaryUrl. Typecheck + lint clean (only pre-existing exhaustive-deps warnings). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Align ngm.jawafdehi.org with the Jawafdehi brand and streamline the experience.
Brand design system:
- index.css tokens recolored to brand navy #0E1F3A / crimson #B5242C / warm white,
brand font stack (Helvetica/Arial/Noto Sans Devanagari), navy-tinted shadows.
- Replace every generic-blue literal (App.css + inline styles across the pages and
components) with brand tokens; hero gradient is navy -> crimson.
Identity:
- Navy header with the Jawafdehi wordmark (logo-dark.svg) + an "NGM · Nepal
Governance Modernization" tag, crimson active-nav underline, and a brand footer
("A project of Jawafdehi", CC BY-NC 4.0).
- Landing rebuilt: brand hero + eyebrow, FAQ-aligned About copy, clear entry cards.
IA simplification:
- Drop the Archive's redundant "CIAA Cases Dataset" and "Court Cases" tabs (they
duplicated the dedicated /dataset and /search pages); the Archive is now the
document datasets only. Nav: Home · Court Cases · Archive · CIAA Cases · Status.
Typecheck + production build clean; lint 0 errors (only pre-existing deps warnings).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 16 minutes and 10 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ngm-frontend | 75e8534 | Commit Preview URL Branch Preview URL |
Jun 26 2026, 03:55 AM |
There was a problem hiding this comment.
Code Review
This pull request updates the application's design system to align with the Jawafdehi brand identity, introducing a new color palette, typography, and layout adjustments. It also implements support for NGM Index v2 by introducing structured manuscript links and refactoring the navigation. The review feedback highlights opportunities to further align legacy hardcoded background colors with the new design system variables, fix WCAG accessibility issues regarding low text contrast on disabled buttons, and add defensive checks to prevent potential runtime crashes from malformed API payloads or undefined properties.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| background: '#f0f4ff', | ||
| borderRadius: '12px', | ||
| marginBottom: '1.5rem', | ||
| border: '2px solid #bfdbfe' | ||
| border: '2px solid var(--border-cool)' |
There was a problem hiding this comment.
The background color #f0f4ff is a hardcoded light blue from the legacy theme. To align with the new Jawafdehi brand identity and design system, this should be replaced with the var(--bg-tint) CSS variable.
| background: '#f0f4ff', | |
| borderRadius: '12px', | |
| marginBottom: '1.5rem', | |
| border: '2px solid #bfdbfe' | |
| border: '2px solid var(--border-cool)' | |
| background: 'var(--bg-tint)', | |
| borderRadius: '12px', | |
| marginBottom: '1.5rem', | |
| border: '2px solid var(--border-cool)' |
| background: !loading && caseNumber.trim() ? 'var(--navy)' : 'var(--border-cool)', | ||
| color: 'white', |
There was a problem hiding this comment.
When the search button is disabled, its background is set to var(--border-cool) (a very light gray, #DCE2EA), but the text color remains white. This results in a contrast ratio of 1.36:1, which is extremely low and violates WCAG accessibility standards. Setting the text color to var(--text-secondary) when disabled will ensure proper readability.
| background: !loading && caseNumber.trim() ? 'var(--navy)' : 'var(--border-cool)', | |
| color: 'white', | |
| background: !loading && caseNumber.trim() ? 'var(--navy)' : 'var(--border-cool)', | |
| color: !loading && caseNumber.trim() ? 'white' : 'var(--text-secondary)', |
| function fileLinks(m: Manuscript): SourceLink[] { | ||
| const roled = (m.links ?? []).filter((l) => l.role === 'RAW' || l.role === 'ALTERNATE'); | ||
| if (roled.length > 0) { |
There was a problem hiding this comment.
Add a defensive check to ensure that elements within m.links are not null or undefined before accessing their role property. This prevents potential runtime crashes if the API returns malformed link arrays.
| function fileLinks(m: Manuscript): SourceLink[] { | |
| const roled = (m.links ?? []).filter((l) => l.role === 'RAW' || l.role === 'ALTERNATE'); | |
| if (roled.length > 0) { | |
| function fileLinks(m: Manuscript): SourceLink[] { | |
| const roled = (m.links ?? []).filter((l) => l && (l.role === 'RAW' || l.role === 'ALTERNATE')); |
| function linkByRole(m: Manuscript, role: LinkRole): string | undefined { | ||
| return m.links?.find((l) => l.role === role)?.link; |
There was a problem hiding this comment.
Add a defensive check to ensure that elements within m.links are not null or undefined before accessing their role property.
| function linkByRole(m: Manuscript, role: LinkRole): string | undefined { | |
| return m.links?.find((l) => l.role === role)?.link; | |
| function linkByRole(m: Manuscript, role: LinkRole): string | undefined { | |
| return m.links?.find((l) => l && l.role === role)?.link; |
| function extFromUrl(u: string): string { | ||
| return u.match(/\.([A-Za-z0-9]+)(?:[?#]|$)/)?.[1]?.toUpperCase() || 'FILE'; |
There was a problem hiding this comment.
If u is undefined, null, or not a string, calling u.match will throw a runtime TypeError. Adding a defensive type guard makes this helper robust against unexpected API payloads.
function extFromUrl(u: string | undefined | null): string {
if (!u || typeof u !== 'string') return 'FILE';
return u.match(/\.([A-Za-z0-9]+)(?:[?#]|$)/)?.[1]?.toUpperCase() || 'FILE';
| const key = hasValidPressId ? `press:${parsed}` : `file:${item.url}`; | ||
| const existing = byPressId.get(key); | ||
| if (!existing) { | ||
| byPressId.set(key, { ...item }); | ||
| } else { | ||
| existing.links = [...fileLinks(existing), ...fileLinks(item)]; | ||
| } |
There was a problem hiding this comment.
Using item.url as the key for grouping can fail for NGM Index v2 manuscripts that only carry the links array and omit the legacy url property, causing them to group under "file:undefined". Using primaryUrl(item) is much more robust. Additionally, updating the map value by creating a new object rather than mutating existing in-place is a cleaner, safer pattern.
const key = hasValidPressId ? `press:${parsed}` : `file:${primaryUrl(item)}`;
const existing = byPressId.get(key);
if (!existing) {
byPressId.set(key, { ...item });
} else {
byPressId.set(key, {
...existing,
links: [...fileLinks(existing), ...fileLinks(item)]
});
}
| background: '#f0f4ff', | ||
| borderRadius: '12px', | ||
| marginBottom: '1.5rem', | ||
| border: '2px solid #bfdbfe' | ||
| border: '2px solid var(--border-cool)' |
There was a problem hiding this comment.
The background color #f0f4ff is a hardcoded light blue from the legacy theme. To align with the new Jawafdehi brand identity and design system, this should be replaced with the var(--bg-tint) CSS variable.
| background: '#f0f4ff', | |
| borderRadius: '12px', | |
| marginBottom: '1.5rem', | |
| border: '2px solid #bfdbfe' | |
| border: '2px solid var(--border-cool)' | |
| background: 'var(--bg-tint)', | |
| borderRadius: '12px', | |
| marginBottom: '1.5rem', | |
| border: '2px solid var(--border-cool)' |
| background: courtFilters.selectedCourt && !isLoading ? 'var(--navy)' : 'var(--border-cool)', | ||
| color: 'white', |
There was a problem hiding this comment.
When the search button is disabled, its background is set to var(--border-cool) (a very light gray, #DCE2EA), but the text color remains white. This results in a contrast ratio of 1.36:1, which is extremely low and violates WCAG accessibility standards. Setting the text color to var(--text-secondary) when disabled will ensure proper readability.
| background: courtFilters.selectedCourt && !isLoading ? 'var(--navy)' : 'var(--border-cool)', | |
| color: 'white', | |
| background: courtFilters.selectedCourt && !isLoading ? 'var(--navy)' : 'var(--border-cool)', | |
| color: courtFilters.selectedCourt && !isLoading ? 'white' : 'var(--text-secondary)', |
Pairs with the backend NGM Index v2 change (Jawafdehi/ngm#88). Two parts; check the Cloudflare branch preview for the visual.
1. Adapt index consumption to consolidated manuscripts
The backend now emits one consolidated manuscript per logical document with a roled
linksarray (RAW/ALTERNATE/SOURCE_PAGE/MARKDOWN), adocument_id, and asource_type; the oldurl/file_nameremain as a back-compat alias.Manuscripttype extended; helpersfileLinks/linkByRole/primaryUrl/extFromUrlfall back to the legacyurl, so old index snapshots still render during rollout.press_id(the backend consolidates now); render each release's attachments fromlinks, plus a Transcript (MARKDOWN) and Source (SOURCE_PAGE) chip when present. De-dup bypress_idkept only to tolerate legacy snapshots.primaryUrl.2. Rebrand to the Jawafdehi identity + simplify the IA
index.cssretokenized to brand navy#0E1F3A/ crimson#B5242C/ warm white + the brand font stack; every generic-blue literal (CSS + inline styles) swept to brand tokens; hero gradient navy→crimson.logo-dark.svg) + an "NGM · Nepal Governance Modernization" tag, crimson active-nav underline, and a brand footer ("A project of Jawafdehi · CC BY-NC 4.0"). Landing rebuilt with a brand hero + FAQ-aligned copy./datasetand/searchpages). Nav is now Home · Court Cases · Archive · CIAA Cases · Status.Verification
tsc -b+vite buildclean; eslint 0 errors (only pre-existingexhaustive-depswarnings).Follow-ups (not in this PR)
document_id.🤖 Generated with Claude Code