Skip to content

feat(narratives): PR 1 - Core Shell, Routing, and Branding#363

Open
ddebasmita-lab wants to merge 13 commits into
datacommonsorg:mainfrom
ddebasmita-lab:custom-dc
Open

feat(narratives): PR 1 - Core Shell, Routing, and Branding#363
ddebasmita-lab wants to merge 13 commits into
datacommonsorg:mainfrom
ddebasmita-lab:custom-dc

Conversation

@ddebasmita-lab

Copy link
Copy Markdown

This Pull Request introduces the initial structure and core layout shell for the new Narratives custom web interface under the /narratives folder. This is the first PR in a phased sequence to set up the Custom Data Commons narratives tool.

Key Additions:
Project Scaffolding: Configured React + TypeScript + Vite setup under narratives/ with strict type checking enabled ("strict": true in tsconfig.json).
Google Development Standards: Followed Google HTML/CSS and TypeScript styling guidelines (including block-wrapped control statements, clean import aliasing, and standard self-closing tags).
Branding & Design System: Integrated a BrandingProvider to dynamically fetch and inject instance-specific customization (e.g. brand-primary colors, brand font families, custom logos) as CSS variables.
Layout & Navigation: Implemented the base application shell (App.tsx), responsive sidebar/header components, and a lightweight hash-based router (useHashRoute).
Git Protection: Configured project-specific .gitignore and .dockerignore files to prevent committing local terraform caches, .tfvars config files, and generated build folders.

Files Included in this Phase:
narratives/tsconfig.json & vite.config.ts
narratives/index.html & package.json
Core shell components: Header.tsx, Sidebar.tsx, App.tsx
Configs and hooks: navConfig.ts, useHashRoute.ts, BrandingContext.tsx, useBranding.ts

@ddebasmita-lab ddebasmita-lab requested a review from a team as a code owner June 11, 2026 12:46
@google-cla

google-cla Bot commented Jun 11, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request scaffolds a new React application under the narratives directory, integrating Data Commons web components, Tailwind CSS, and custom branding contexts. Key feedback highlights a security vulnerability where the GEMINI_API_KEY is exposed to the client-side bundle, which should instead be handled on the server side. Additionally, the reviewer noted that the hash router should strip query parameters to prevent routing failures, the dynamic branding colors and fonts should be properly registered in Tailwind's theme configuration and typography tokens, and the header logo should be updated to use the dynamic branding context rather than hardcoded values.

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.

Comment thread narratives/src/hooks/useHashRoute.ts
Comment thread narratives/vite.config.ts Outdated
Comment thread narratives/src/index.css
Comment thread narratives/src/index.css
Comment thread narratives/src/components/Header.tsx Outdated
@ddebasmita-lab

Copy link
Copy Markdown
Author

@beets please review this PR when you get a chance!

@beets beets left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi!

Thanks for putting this together, the structure looks clean and organized. And welcome to the repo!

Since this is an initial PR, expect more comments that aim to ensure we are set up well for future iterations.

1. Getting the project to compile (Stubs)

Currently, the build fails because App.tsx and Sidebar.tsx import several files that aren't present in the PR yet (like DataAgent, MetricsPage, and ChatSessionContext).

  • Suggestion: Please add simple placeholder/stub files for these imports so the project compiles. This will allow reviewers to run the project locally and verify the shell layout.

2. Code Quality & Formatting (DX)

To maintain code consistency, it would be helpful to set up linting and formatting. Please also adhere to the Google Typescript guidelines.

  • Suggestion: Consider configuring ESLint/Prettier, or Biome (similar to the setup in dataweaver).

3. Testing Coverage

As this is a new project, establishing a testing pattern early is important.

  • Suggestion: Please add a basic testing setup (e.g., Vitest) and include a simple unit test for one of the hooks (like useHashRoute) to set a baseline for future contributions.

4. Project Documentation (README)

  • Suggestion: Please add a basic README.md in the narratives directory explaining the project at a high-level, how to install dependencies, run the development server, and build the project.

5. Naming & Style Guide Compliance

  • Default Exports: The Google TypeScript Style Guide discourages default exports (Section 3.3.4) to ensure import consistency. Consider switching App, Header, and Sidebar to named exports.
  • Constants: Global constants like navConfig should use UPPER_SNAKE_CASE (e.g., NAV_CONFIG).
  • Variable Names: Avoid single-letter parameter names like b in applyCssVars (useBranding.ts). Rename it to branding or config to be more descriptive. These should also be in camelCase.
  • UI strings: Prefer Sentence case over Title Case where possible.

6. Documenting Exported APIs (JSDoc)

To make the codebase easier to maintain, it is a good practice to document all exported symbols (interfaces, types, functions, and components) using JSDoc.

  • Suggestion: Please add JSDoc comments to your exported interfaces (like Branding, NavItem) and functions (like useBranding, useHashRoute, Header, etc.).
  • Example:
    /**
     * Configuration options for branding the instance.
     */
    export interface Branding {
      /** The name of this Data Commons instance displayed in the header. */
      instance_name?: string;
      ...
    }
    This helps other developers (and IDE auto-complete) understand the purpose of these structures without reading the implementation.

7. CSS: Avoid Arbitrary Values in Tailwind (Best Practices)

  • Observation: In Header.tsx, you used several arbitrary/hardcoded values (like w-[1px] for a divider, and mt-[2px] on the Chevron icon).
  • Educational Note: One of Tailwind's strengths is the out-of-the-box design system which promotes consistent spacing and widths. Using arbitrary bracketed values like [1px] or [2px] is usually reserved for edge-cases or custom branding elements.
  • Suggestion: You can use standard Tailwind classes here:
    • Replace w-[1px] with w-px (Tailwind's built-in 1px width).
    • Replace mt-[2px] with mt-0.5 (Tailwind's 0.5 unit corresponds to 0.125rem or 2px).
    • For the h-[3px] active indicator line, if a 2px (h-0.5) or 4px (h-1) border works, it is better to use those to maintain consistent line weights. If 3px is strictly required, keeping h-[3px] is fine!

Comment thread narratives/src/App.tsx Outdated
Comment thread narratives/src/App.tsx
Comment thread narratives/src/App.tsx Outdated
Comment thread narratives/src/App.tsx Outdated
Comment thread narratives/src/components/Sidebar.tsx
Comment thread narratives/src/config/navConfig.ts
Comment thread narratives/src/hooks/useBranding.ts Outdated
Comment thread narratives/src/hooks/useBranding.ts
Comment thread narratives/src/hooks/useBranding.ts
Comment thread narratives/src/types/data-commons-elements.d.ts

@juliawu juliawu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ddebasmita-lab! Nice to e-meet you. I'm handling reviews while @beets is out of office.

Thank you for the updates! The changes so far are already much improved, and the README.md you added plus the extra files to allow for running locally were immensely helpful!

I've taken a look and left some comments, mainly around formatting. Comments tagged with [Suggestion] are minor changes I'd suggest, but don't block this PR. Comments tagged with [Can leave for followup PR] are changes that need to be implemented, but for the sake of time, can be left as a followup after this series of PRs are approved and merged. Please leave a TODO if you're leaving it for later.

To make sure we're all on the same page, we're trying to codify our code style standards in this PR. If you have access to a Coding AI Agent, you might try feeding the AGENTS.md file in that link to the agent to help you make the code styling adjustments quickly.

Here are my overall comments:
(1) Per the style guide, please rename the files to:

  • Use snake_case for file names.
  • Use category-first naming.

(2) [Can leave for followup PR] Extract the inline styling in the react components

  • There's a lot of inline styling in the react components in the components/ folder. Let's extract out the styling-related constants and inline style={} objects into a template/theme file that would be easy for a new user to update to their liking.

As always, feel free to ask questions if anything is unclear. I'm excited to see this come together!

Comment on lines +1 to +3
// Typed access to the Custom Data Commons observation endpoints.
// We use these directly so charts render inside our own Recharts layer —
// no DC web components, full Figma fidelity.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For all file description comments (both here and in all files in this PR), use

/**
 *
 */

style multiline comments instead.

// We use these directly so charts render inside our own Recharts layer —
// no DC web components, full Figma fidelity.

export type SeriesPoint = { date: string; value: number };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per Google TypeScript style guide, let's make SeriesPoint, SeriesResponse, and PointResponse an interface instead of a type.

Comment on lines +34 to +64
function buildSeriesUrl(
variableDcids: string[],
entityDcids: string[],
): string {
const u = new URL("/api/observations/series", ORIGIN);
for (const v of variableDcids) {
u.searchParams.append("variables", v);
}
for (const e of entityDcids) {
u.searchParams.append("entities", e);
}
return u.toString();
}

function buildPointUrl(
variableDcids: string[],
entityDcids: string[],
date: string,
): string {
const u = new URL("/api/observations/point", ORIGIN);
for (const v of variableDcids) {
u.searchParams.append("variables", v);
}
for (const e of entityDcids) {
u.searchParams.append("entities", e);
}
if (date) {
u.searchParams.set("date", date);
}
return u.toString();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use more descriptive variable names than u, v, and e. This will improve the readability of your code. I'd suggest something like:
u -> url
v -> variableDcid
e -> entityDcid

e in particular should get renamed because in typescript it's commonly used for "error" or "event" objects, so we don't want to overload its meaning.

Comment on lines +91 to +94
// Time-series shape (line/bar over time, single place per variable):
// pivots the API response into one row per date, with each variable as a
// column. Variables that don't have a value on a given date are omitted
// from that row.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this function and all subsequent functions, convert the // to a /** */ style JSDoc comment.

return u.toString();
}

export async function fetchSeries(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a JSDoc comment to fetchSeries() and fetchPoint() as well. In general, we want a JSDoc for all exported functions.

Comment on lines +58 to +60
// Split a string into a mixed array of text fragments and CitationChip
// elements, matching `[N]` where N is 1-99. Handles multiple adjacent
// citations like `[1] [2]` or `[1][2]`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, convert this comment to a JSDoc format docstring

"#9334E6",
];

export default function ChartTile({ config, provenance }: ChartTileProps) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and for the rest of the exported components in this file:

(1) Please add a fileoverview and a JSDoc docstring

(2) Please use named exports

export function ChartTile(...)

Comment on lines +234 to +237
// ───────────────────────────────────────────────────────────────
// Recharts renderers
// ───────────────────────────────────────────────────────────────

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Can leave for a followup PR] This file is currently very, very big. Let's split this into multiple files.

I'd recommend something like:
charts/ (new subfolder)

  • chart_tile.tsx (holds the main TileChart grid component)
  • chart_card.tsx (holds the CardChart component)
  • chart_graph.tsx (holds the Recharts GraphChart component)
  • skeleton_chart.tsx (holds the loading SkeletonChart component)
  • message_chart.tsx (holds the error/empty MessageChart)
  • utils.tsx (holds any shared helper functions)
  • contstants.tsx (holds shared styling configuration constants)

It's currently a little hard to tell what the intended hierarchy for all these components is. Therefore, use your best judgment and feel free to use a different grouping if you feel it makes more sense.

const FONT_LABEL =
'"Google Sans Text", "Google Sans", Inter, system-ui, sans-serif';

export default function AnswerPanel({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(1) Please add a fileoverview and a JSDoc docstring

(2) Please use named exports

export function AnswerPanel(...)

Comment on lines +129 to +131
// Outline-style Export PDF pill that lives in the card's toolbar header.
// Distinct from the filled <ExportPdfButton /> that sits inside the card
// body — both appear in Figma 3427-16715 and the user's screenshot.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convert this to a JSDoc format docstring instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants