Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"Edit",
"Bash",
"WebFetch",
"mcp__plugin_serena_serena__*",
"mcp__plugin_context7_context7__*",
"mcp__plugin_playwright_playwright__*"
"mcp__plugin_playwright_playwright__*",
"mcp__serena__*"
],
"ask": [
"Bash(git commit *)",
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,4 @@ agentic/runs/
docker-compose.override.yml
secrets/
/.playwright-mcp/
/screenshots/
4 changes: 2 additions & 2 deletions .serena/memories/code_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
- **Hooks**: camelCase with `use` prefix (e.g., `useSpecs.ts`)
- **Utils/Types**: camelCase files (e.g., `api.ts`)
- **Exports**: Named exports (no default exports)
- **Styling**: MUI `sx` prop + Emotion `styled()`, no CSS modules
- **State**: Local state + custom hooks (no Redux/Zustand)
- **Styling**: MUI `sx` prop + theme tokens from `app/src/theme/index.ts`. No hardcoded hex colors — use `colors.*`, `semanticColors.*`, `fontSize.*`, `typography.fontFamily` imports. See Serena memory `style_guide` for full token reference.
- **State**: Local state + custom hooks (no Redux/Zustand). Avoid `setState` inside `useEffect` for prop resets — use render-time ref pattern instead.
- **API calls**: Plain `fetch()` in `utils/api.ts`

## Agentic Layer Conventions
Expand Down
44 changes: 44 additions & 0 deletions .serena/memories/style_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Frontend Style Guide

All visual values are centralized in `app/src/theme/index.ts`. Never use hardcoded hex colors or font strings — always import tokens.

## Imports
```ts
import { typography, colors, semanticColors, fontSize, spacing } from '../theme';
// Shared style constants:
import { headingStyle, subheadingStyle, textStyle, codeBlockStyle, tableStyle, labelStyle, monoText } from '../theme';
```

## Colors
- **Brand**: `colors.primary` (#3776AB), `colors.accent` (#FFD43B), `colors.primaryDark` (#306998)
- **Gray scale**: `colors.gray[50]` to `colors.gray[900]`
- **Semantic text**: `semanticColors.labelText` (7.0:1), `semanticColors.subtleText` (5.8:1), `semanticColors.mutedText` (4.6:1)
- **Status**: `colors.success`, `colors.error`, `colors.warning`, `colors.info`
- **Backgrounds**: `colors.background`, `colors.accentBg`
- **Code blocks**: `colors.codeBlock.bg`, `colors.codeBlock.text`

## WCAG Rule
`colors.gray[400]` (#9ca3af) and lighter **must never be used for text or icons**. Minimum text color: `semanticColors.mutedText` (#6b7280, 4.6:1 contrast).

## Font
Always use `typography.fontFamily` — never inline `'"MonoLisa", monospace'` or raw `'monospace'`.
**Exception**: ErrorBoundary uses raw `'monospace'` intentionally (crash-safe fallback).

## Font Sizes
`fontSize.micro` (0.5rem) and `fontSize.xxs` (0.625rem) are restricted to data-dense pages (StatsPage, DebugPage).
Public pages use `fontSize.xs` (0.75rem) as minimum.
Full scale: micro, xxs, xs, sm, md, base, lg, xl.

## Shared Constants
- `headingStyle` — page h2 (1.25rem, 600, gray.800)
- `subheadingStyle` — page h3 (1rem, 600, gray.700)
- `textStyle` — body text (0.9375rem, labelText, lineHeight 1.8)
- `codeBlockStyle` — dark code blocks
- `tableStyle` — consistent table cells/headers
- `labelStyle` — small labels (0.875rem, labelText)

## Highlight Colors
Use theme tokens for highlight treatments: `colors.highlight.bg`/`colors.highlight.text` for highlighted tag chips and `colors.tooltipLight` for tooltip text on dark backgrounds. Do not reintroduce hardcoded highlight hex values.

## Full reference
See `docs/reference/style-guide.md` for complete documentation including spacing, breakpoints, component specs, animations, and accessibility rules.
26 changes: 18 additions & 8 deletions agentic/commands/prime.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,25 @@ gh pr list --limit 10 2>/dev/null || echo "(gh CLI not available)"

## Serena

- Run `activate_project` with project "pyplots"
- Run `list_memories` and read relevant ones
- Run `check_onboarding_performed`
- Run `list_memories` and read relevant ones

### JetBrains Tools (prefer over brute-force scanning)

Use Serena's JetBrains-backed tools for code navigation — they provide semantic understanding
that grep/glob cannot:

- `jet_brains_get_symbols_overview` — get top-level symbols in a file (classes, functions, variables). Use with `depth: 1` to also see methods of classes. Start here to understand a file before diving deeper.
- `jet_brains_find_symbol` — search for a symbol by name across the codebase. Supports name path patterns like `MyClass/my_method`. Use `include_body: true` to read source code, `include_info: true` for docstrings/signatures.
- `jet_brains_find_referencing_symbols` — find all usages of a symbol (who calls this function? who imports this class?). Essential for understanding impact of changes.
- `jet_brains_find_declaration` — jump to where a symbol is defined.
- `jet_brains_find_implementations` — find implementations of an interface/abstract class.
- `jet_brains_type_hierarchy` — understand class inheritance chains.

Prefer Serena's symbolic tools (`jet_brains_find_symbol`, `jet_brains_get_symbols_overview`,
`jet_brains_find_referencing_symbols`) over brute-force file scanning.
### Editing via Serena

Use Serena's thinking tools to maintain focus:
For structural edits, prefer Serena's symbol-aware tools over raw text replacement:

- `think_about_collected_information` - after research/search sequences
- `think_about_task_adherence` - before making code changes
- `think_about_whether_you_are_done` - when task seems complete
- `replace_symbol_body` — replace an entire function/class body
- `insert_after_symbol` / `insert_before_symbol` — add code relative to a symbol
- `search_for_pattern` — regex search across the codebase (fast, flexible)
6 changes: 5 additions & 1 deletion api/routers/insights.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class PlotOfTheDayResponse(BaseModel):
preview_url: str | None = None
image_description: str | None = None
code: str | None = None
library_version: str | None = None
python_version: str | None = None
date: str


Expand Down Expand Up @@ -397,6 +399,8 @@ async def _build_potd(spec_repo: SpecRepository, impl_repo: ImplRepository) -> P
preview_url=preview_url,
image_description=full_impl.review_image_description if full_impl else None,
code=strip_noqa_comments(full_impl.code) if full_impl and full_impl.code else None,
library_version=full_impl.library_version if full_impl else None,
python_version=full_impl.python_version if full_impl else None,
date=today,
)

Expand Down Expand Up @@ -525,7 +529,7 @@ async def _build_related(
@router.get("/related/{spec_id}", response_model=RelatedSpecsResponse)
async def get_related_specs(
spec_id: str,
limit: int = Query(default=6, ge=1, le=12),
limit: int = Query(default=6, ge=1, le=24),
mode: str = Query(default="spec", pattern="^(spec|full)$"),
library: str | None = Query(default=None),
db: AsyncSession = Depends(require_db),
Expand Down
41 changes: 27 additions & 14 deletions app/src/components/Breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import { Link } from 'react-router-dom';
import Box from '@mui/material/Box';
import type { SxProps, Theme } from '@mui/material/styles';
import { colors, fontSize, semanticColors, typography } from '../theme';

export interface BreadcrumbItem {
label: string;
shortLabel?: string; // Shown on mobile (xs) if provided
to?: string; // If undefined, this is the current page (not linked)
}

Expand All @@ -26,11 +28,12 @@ export interface BreadcrumbProps {
* <Breadcrumb items={[{ label: 'pyplots.ai', to: '/' }, { label: 'catalog' }]} />
*
* @example
* // With right action
* <Breadcrumb
* items={[{ label: 'pyplots.ai', to: '/' }, { label: 'catalog' }]}
* rightAction={<Link to="/suggest">suggest spec</Link>}
* />
* // With short labels for mobile
* <Breadcrumb items={[
* { label: 'pyplots.ai', to: '/' },
* { label: 'scatter-basic', to: '/scatter-basic' },
* { label: 'matplotlib', shortLabel: 'mpl' },
* ]} />
*/
export function Breadcrumb({ items, rightAction, sx }: BreadcrumbProps) {
return (
Expand All @@ -46,10 +49,10 @@ export function Breadcrumb({ items, rightAction, sx }: BreadcrumbProps) {
px: 2,
py: 1,
mb: 2,
bgcolor: '#f3f4f6',
borderBottom: '1px solid #e5e7eb',
fontFamily: '"MonoLisa", monospace',
fontSize: '0.85rem',
bgcolor: colors.gray[100],
borderBottom: `1px solid ${colors.gray[200]}`,
fontFamily: typography.fontFamily,
fontSize: fontSize.base,
...sx,
}}
>
Expand All @@ -58,7 +61,7 @@ export function Breadcrumb({ items, rightAction, sx }: BreadcrumbProps) {
{items.map((item, index) => (
<Box key={index} sx={{ display: 'flex', alignItems: 'center' }}>
{index > 0 && (
<Box component="span" sx={{ mx: 1, color: '#9ca3af' }}>
<Box component="span" sx={{ mx: 1, color: semanticColors.mutedText }}>
</Box>
)}
Expand All @@ -67,16 +70,26 @@ export function Breadcrumb({ items, rightAction, sx }: BreadcrumbProps) {
component={Link}
to={item.to}
sx={{
color: '#3776AB',
color: colors.primary,
textDecoration: 'none',
'&:hover': { textDecoration: 'underline' },
}}
>
{item.label}
{item.shortLabel ? (
<>
<Box component="span" sx={{ display: { xs: 'none', sm: 'inline' } }}>{item.label}</Box>
<Box component="span" sx={{ display: { xs: 'inline', sm: 'none' } }}>{item.shortLabel}</Box>
</>
) : item.label}
</Box>
) : (
<Box component="span" sx={{ color: '#4b5563' }}>
{item.label}
<Box component="span" sx={{ color: colors.gray[700] }}>
{item.shortLabel ? (
<>
<Box component="span" sx={{ display: { xs: 'none', sm: 'inline' } }}>{item.label}</Box>
<Box component="span" sx={{ display: { xs: 'inline', sm: 'none' } }}>{item.shortLabel}</Box>
</>
) : item.label}
</Box>
)}
</Box>
Expand Down
3 changes: 2 additions & 1 deletion app/src/components/CodeHighlighter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light';
import { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import python from 'react-syntax-highlighter/dist/esm/languages/prism/python';
import { typography } from '../theme';

SyntaxHighlighter.registerLanguage('python', python);

Expand All @@ -16,7 +17,7 @@ export default function CodeHighlighter({ code }: CodeHighlighterProps) {
customStyle={{
margin: 0,
fontSize: '0.85rem',
fontFamily: '"MonoLisa", "MonoLisa Fallback", monospace',
fontFamily: typography.fontFamily,
background: 'transparent',
}}
>
Expand Down
Loading
Loading