Skip to content

Commit 71a6e36

Browse files
authored
Merge pull request #36 from webstackdev/feature/storybook
Feature/storybook
2 parents 2446f0c + 485e58f commit 71a6e36

131 files changed

Lines changed: 8901 additions & 1637 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/copilot-instructions.md‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,15 @@ You are working in Newsletter Maker, a Django + DRF + Celery + Qdrant backend wi
3636
- The frontend uses Next.js App Router.
3737
- Shared backend-facing types belong in `frontend/src/lib/types.ts`.
3838
- Shared backend-facing data access belongs in `frontend/src/lib/api.ts` unless there is a clear reason to add a route handler under `frontend/src/app/api/`.
39-
- Keep reusable UI in `frontend/src/components/` and page assembly in `frontend/src/app/`.
39+
- Keep reusable components in `frontend/src/components/`, provider-style wrappers in `frontend/src/providers/`, and page assembly in `frontend/src/app/`.
40+
- Use `frontend/src/components/elements/` for app-owned components that combine shadcn primitives with project-specific functionality.
41+
- Use `frontend/src/components/layout/` for shared navigation, page chrome, and structural layout components.
42+
- Use `frontend/src/components/ui/` only for shadcn components installed by `npx shadcn@latest add <component>`; do not move custom app components into that folder.
43+
- Use `frontend/src/providers/` for provider-style wrappers and context composition such as theme or query providers.
44+
- For component folders under `frontend/src/components/elements/`, `frontend/src/components/layout/`, `frontend/src/providers/`, or `frontend/src/app/**/_components/`, let the folder carry the component name and use `index.tsx`, `index.test.tsx`, and `index.stories.tsx` inside that folder instead of repeating the component name in each file.
45+
- Do not add barrel `index.ts` files inside those component or provider folders unless the task explicitly requires one.
46+
- Frontend tests should live beside the files they cover in `frontend/src/app/` and `frontend/src/components/` rather than in separate `__tests__/` folders.
47+
- When adding or changing a frontend route, page, or component, add or update direct colocated Vitest coverage in the same change. If a file is a pure framework re-export or adapter and a dedicated test is intentionally skipped, call that out explicitly.
4048
- Preserve existing backend payload shapes in TypeScript types and UI code unless the backend contract is intentionally changing.
4149

4250
## Documentation Standards
@@ -45,6 +53,7 @@ You are working in Newsletter Maker, a Django + DRF + Celery + Qdrant backend wi
4553
- Add or improve module docstrings plus public classes, public functions, and non-obvious helpers.
4654
- Do not add noisy boilerplate to trivial `__str__` methods, simple properties, or obvious one-line helpers unless the surrounding file genuinely benefits.
4755
- TypeScript and React code should use JSDoc for exported utilities, hooks, route handlers, and non-trivial components when behavior is not obvious from the type signature alone.
56+
- For React components, providers, and App Router pages, keep the component JSDoc to a short summary paragraph and document prop fields on the props type or interface. Avoid `@param` and `@returns` tags on React components because Storybook Autodocs flattens them poorly.
4857
- If architecture or workflow behavior changes, update the most relevant docs in `docs/`, especially `docs/DEVELOPER_GUIDE.md`, `docs/IMPLEMENTATION_OVERVIEW.md`, `docs/MODELS.md`, `docs/RELEVANCE_SCORING.md`, or `docs/LOGGING.md`.
4958

5059
## Prompt Skill Conventions

‎.github/instructions/frontend-app.instructions.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ applyTo:
1111
- This frontend uses Next.js App Router, not the Pages Router.
1212
- Keep backend-facing types in `frontend/src/lib/types.ts` and shared server-side API access in `frontend/src/lib/api.ts` unless a route handler in `frontend/src/app/api/` is the correct boundary.
1313
- Reuse the existing backend contract. This repo currently consumes `snake_case` fields from Django; do not silently rename payload keys in the frontend.
14-
- Keep reusable UI in `frontend/src/components/` and page composition in `frontend/src/app/`.
14+
- Keep reusable components in `frontend/src/components/`, provider-style wrappers in `frontend/src/providers/`, and page composition in `frontend/src/app/`.
15+
- Keep Vitest files beside the route page, route-local component, or shared component they exercise instead of creating separate `__tests__/` folders.
16+
- Add or update a colocated `*.test.ts` or `*.test.tsx` file in the same change when introducing or modifying a route handler, page, or component. If the file is only a framework passthrough, document why dedicated coverage is omitted.
1517
- Prefer strong explicit types over loose `Record<string, unknown>` shapes when the contract is known.
1618
- Add JSDoc for exported utilities, route handlers, hooks, and non-trivial components when behavior is not obvious from the signature.
19+
- For React components, providers, and App Router pages, keep the component JSDoc to a short summary paragraph and put prop descriptions on the props type or interface fields. Avoid `@param` and `@returns` tags on React components because Storybook Autodocs flattens them into a single block.
1720
- When a change depends on new backend fields or endpoints, update the corresponding types and API helpers in the same change.
1821

1922
## Validation
@@ -29,3 +32,4 @@ applyTo:
2932
- `frontend/src/lib/api.ts`
3033
- `frontend/src/app/`
3134
- `frontend/src/components/`
35+
- `frontend/src/providers/`
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
name: "Frontend Component Structure Guidelines"
3+
description: "Use when creating, moving, or refactoring React components, Storybook stories, or frontend tests in frontend/src/. Covers the preferred elements/layout/ui/providers/app _components directory structure and colocated naming conventions."
4+
applyTo:
5+
- "frontend/src/**/*.ts"
6+
- "frontend/src/**/*.tsx"
7+
---
8+
9+
# Frontend Component Structure Guidelines
10+
11+
- Avoid growing a flat `frontend/src/components/` directory.
12+
- Put app-owned presentational or interactive components that combine shadcn primitives with project-specific functionality in `frontend/src/components/elements/`.
13+
- Put shared structural components in `frontend/src/components/layout/`.
14+
- Keep `frontend/src/components/ui/` for shadcn components installed directly by `npx shadcn@latest add <component>`.
15+
- Put provider-style wrappers and context composition in `frontend/src/providers/`.
16+
- Put route-local components in `frontend/src/app/**/_components/` when they are only used by a single route.
17+
- Put route page tests beside the page or route-local component they cover within the same `frontend/src/app/**` directory.
18+
- For app-owned folders under `frontend/src/components/elements/`, `frontend/src/components/layout/`, `frontend/src/providers/`, and `frontend/src/app/**/_components/`, let the folder name carry the component or provider name and use `index.tsx`, `index.test.tsx`, and `index.stories.tsx` for colocated files.
19+
- Do not add barrel `index.ts` files inside those component or provider folders unless a task explicitly needs a separate module boundary.
20+
- Preserve shadcn's generated file naming and structure inside `frontend/src/components/ui/`; do not wrap those generated components in extra folders just to match the app-owned component pattern.
21+
- For new Storybook stories that use `tags: ["autodocs"]`, set `parameters.docs` to the shared compact docs helper in `frontend/src/lib/storybook-docs.tsx` so the Docs tab omits the default `Stories` block and uses the reduced primary canvas height.
22+
23+
## Preferred Shapes
24+
25+
Shared reusable component:
26+
27+
```text
28+
frontend/src/components/elements/StatusBadge/
29+
index.tsx
30+
index.stories.tsx
31+
index.test.tsx
32+
```
33+
34+
Shadcn-installed primitive:
35+
36+
```text
37+
frontend/src/components/ui/button.tsx
38+
```
39+
40+
Shared provider:
41+
42+
```text
43+
frontend/src/providers/ThemeProvider/
44+
index.tsx
45+
index.test.tsx
46+
```
47+
48+
Route-local component:
49+
50+
```text
51+
frontend/src/app/projects/[id]/_components/MemberInviteCard/
52+
index.tsx
53+
index.stories.tsx
54+
index.test.tsx
55+
```
56+
57+
Route page with colocated test:
58+
59+
```text
60+
frontend/src/app/admin/sources/
61+
page.tsx
62+
page.test.tsx
63+
```
64+
65+
## Placement Heuristics
66+
67+
- If the component is a shadcn primitive created by the CLI, keep it under `components/ui/` with the generated naming.
68+
- If the component is app-owned and composes shadcn primitives with project-specific behavior or presentation, place it under `components/elements/`.
69+
- If the component primarily arranges shared navigation or page chrome, place it under `components/layout/`.
70+
- If the module primarily provides context or wraps app trees with provider logic, place it under `providers/`.
71+
- If the component is only consumed by one route segment, keep it under that route's `_components/` folder instead of promoting it to `components/`.
72+
- Prefer folder-level naming over duplicate file naming. For example, prefer `OriginalContentIdeaCard/index.tsx` over `OriginalContentIdeaCard/OriginalContentIdeaCard.tsx`.
73+
- When extracting from a large page, prefer moving the smallest reusable visual leaves first, then larger feature sections, while keeping the page as the orchestration layer.
74+
- Prefer `*.test.tsx` files beside the owning page or component over `__tests__/` directories for new frontend tests.
75+
76+
## Notes
77+
78+
- Preserve the existing backend contract and keep frontend payloads in `snake_case`.
79+
- Follow the repo's colocated story convention for Storybook.
80+
- Reuse `frontend/src/lib/storybook-docs.tsx` for compact Docs tabs in new stories instead of re-declaring the same docs page JSX in each file.
81+
- Do not move files only to satisfy the structure guideline unless the current task already touches that area.

‎.github/skills/coverage-auditor/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Use this skill to add the smallest effective tests around the changed behavior.
1010
## Rules
1111

1212
- **Backend:** Use `pytest` with the existing patterns in `core/tests/` and `tests/`.
13-
- **Frontend:** Use `vitest` and the existing co-located `__tests__` structure under `frontend/src/`.
13+
- **Frontend:** Use `vitest` with colocated `*.test.ts` and `*.test.tsx` files beside the route, page, or component under `frontend/src/`.
1414
- Mock external integrations such as feed parsing, Reddit, email providers, Qdrant, or LLM calls instead of relying on live services.
1515
- Prefer focused behavior tests over broad snapshot-style tests.
1616
- For defensive branches that are intentionally unreachable, document exclusions explicitly with `# pragma: no cover` or `/* v8 ignore next */` only when justified.
@@ -24,7 +24,7 @@ Use this skill to add the smallest effective tests around the changed behavior.
2424
- `core/tests/test_tasks.py`
2525
- `core/tests/test_newsletters.py`
2626
- `core/tests/test_pipeline.py`
27-
- For frontend work, extend the nearest existing `__tests__` file under `frontend/src/components/` or `frontend/src/lib/`.
27+
- For frontend work, add or extend the nearest colocated `*.test.ts` or `*.test.tsx` file beside the owning route, page, or component.
2828
- When adding new frontend tests, keep imports sorted to satisfy the repo's ESLint import-order rules. If you hit `Run autofix to sort these imports!`, fix the import block or run file-scoped ESLint before moving on.
2929
- After changing tests, run the narrowest relevant validation command first.
3030
- For Provider/Wrapper components, do not test state or initialization. Instead, render a consumer child component and assert that the context values or library configurations (like QueryClient options) match the expected project defaults.

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ frontend/coverage/
1717
frontend/node_modules/
1818

1919
docs/
20+
21+
*storybook.log
22+
storybook-static

‎.vscode/settings.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"nodeenv",
4444
"noinput",
4545
"nomic",
46+
"oklch",
4647
"OLLAMA",
4748
"ormsgpack",
4849
"PRAW",

‎SESSION.md‎

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1 @@
11
# Session Restore Point
2-
3-
## Current focus
4-
5-
Phase 3 WP5: original content idea generation in `trends/`.
6-
7-
## What landed today
8-
9-
- Added `OriginalContentIdeaStatus` and `OriginalContentIdea` to `trends/models.py`.
10-
- Added migration `trends/migrations/0005_original_content_idea.py`.
11-
- Added new prompt skill folder `skills/original_content_ideation/` with:
12-
- `SKILL.md`
13-
- `resources/gap_detect.md`
14-
- `resources/generate.md`
15-
- `resources/critique.md`
16-
- Added partial WP5 task implementation in `trends/tasks.py`:
17-
- `run_all_original_content_idea_generations`
18-
- `generate_original_content_ideas`
19-
- workflow helpers for accept / dismiss / mark written
20-
- heuristic gap detection + fallback generation + heuristic critique
21-
- optional OpenRouter-backed prompt-resource calls for gap detect / generate / critique
22-
- Added partial task coverage in `trends/tests/test_tasks.py` for:
23-
- pending-idea creation
24-
- weekly cap
25-
- mark-written workflow
26-
27-
## What was validated
28-
29-
- `python manage.py check`
30-
- `python manage.py makemigrations --check --dry-run trends`
31-
32-
Both passed after naming the new model index `core_idea_project_7f21_idx`.
33-
34-
## Known incomplete state
35-
36-
- WP5 is not finished.
37-
- No serializer/API route/test work has been added yet for `OriginalContentIdea`.
38-
- `docs/IMPLEMENTATION_PHASE_3.md` still needs a current implementation note for WP5 once the backend slice is complete.
39-
- The focused task validation was interrupted:
40-
- first `pytest trends/tests/test_tasks.py -q` failed on a duplicate `_build_theme_cluster_context` definition introduced during editing
41-
- that duplicate definition was removed
42-
- the rerun was cancelled because we paused for shutdown
43-
- After that, additional external edits were reported in:
44-
- `docs/IMPLEMENTATION_PHASE_3.md`
45-
- `trends/tasks.py`
46-
- `trends/tests/test_tasks.py`
47-
Re-read those files before making new edits tomorrow.
48-
49-
## First steps tomorrow
50-
51-
1. Confirm the active branch. The repo attachment reported `maintenance/finish-core-refactor`, but an earlier terminal action created `feature/original-content-idea-generation`, so verify before continuing.
52-
2. Re-read:
53-
- `trends/tasks.py`
54-
- `trends/tests/test_tasks.py`
55-
- `docs/IMPLEMENTATION_PHASE_3.md`
56-
3. Run the focused validation that was interrupted:
57-
- `pytest trends/tests/test_tasks.py -q`
58-
4. If task tests pass, finish the remaining WP5 slice:
59-
- `trends/serializers.py`
60-
- `trends/api.py`
61-
- `trends/api_urls.py`
62-
- `trends/tests/test_api.py`
63-
- optional admin only if needed
64-
- add WP5 implementation note to `docs/IMPLEMENTATION_PHASE_3.md`
65-
5. After API work, run focused validation again:
66-
- `pytest trends/tests/test_tasks.py trends/tests/test_api.py -q`
67-
- `python3 -m mypy trends/tasks.py`
68-
69-
## Likely follow-up checks
70-
71-
- Watch for unused imports in `trends/tasks.py` (`build_skill_user_prompt` / `get_skill_definition` may no longer be needed for WP5 helpers).
72-
- Confirm the new heuristic tests still pass after any formatter changes.
73-
- Keep WP5 scoped to backend + docs for now; frontend `/ideas` work belongs to WP6.

‎frontend/.storybook/main.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { StorybookConfig } from "@storybook/nextjs-vite"
2+
3+
const config: StorybookConfig = {
4+
stories: ["../src/**/*.stories.@(ts|tsx|js|jsx|mjs)"],
5+
addons: [
6+
"@storybook/addon-themes",
7+
"@storybook/addon-a11y",
8+
"@storybook/addon-vitest",
9+
"@chromatic-com/storybook",
10+
"@storybook/addon-docs",
11+
],
12+
framework: {
13+
name: "@storybook/nextjs-vite",
14+
options: {},
15+
},
16+
staticDirs: ["../public"],
17+
}
18+
19+
export default config

‎frontend/.storybook/manager.ts‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { addons } from "storybook/manager-api"
2+
import { create } from "storybook/theming"
3+
4+
const shadcnTheme = create({
5+
base: "light",
6+
7+
fontBase: '"Geist Sans", sans-serif',
8+
fontCode: '"Geist Mono", monospace',
9+
10+
brandTitle: "My Component Library",
11+
brandUrl: "/",
12+
brandTarget: "_self",
13+
14+
// Storybook manager theme colors must stay in formats polished can parse.
15+
colorPrimary: "#06b6d4",
16+
colorSecondary: "#06b6d4",
17+
18+
appBg: "#f5f5f5",
19+
appContentBg: "#fafafa",
20+
appPreviewBg: "#fafafa",
21+
appBorderColor: "#e4e4e7",
22+
appBorderRadius: 10,
23+
24+
textColor: "#18181b",
25+
textInverseColor: "#fafafa",
26+
27+
barTextColor: "#71717a",
28+
barSelectedColor: "#06b6d4",
29+
barHoverColor: "#06b6d4",
30+
barBg: "#fafafa",
31+
32+
inputBg: "#fafafa",
33+
inputBorder: "#e4e4e7",
34+
inputTextColor: "#18181b",
35+
inputBorderRadius: 8,
36+
})
37+
38+
addons.setConfig({
39+
theme: shadcnTheme,
40+
})

‎frontend/.storybook/preview.tsx‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import "../src/app/globals.css"
2+
3+
import { withThemeByClassName } from "@storybook/addon-themes"
4+
import type { Preview } from "@storybook/nextjs-vite"
5+
import type { ReactNode } from "react"
6+
7+
import { QueryProvider } from "../src/providers/QueryProvider"
8+
9+
export const decorators = [
10+
withThemeByClassName({
11+
themes: {
12+
light: "",
13+
dark: "dark",
14+
},
15+
defaultTheme: "light",
16+
}),
17+
]
18+
19+
function StorybookProviders({ children }: { children: ReactNode }) {
20+
return (
21+
<QueryProvider>
22+
<div className="min-h-screen bg-background p-6 text-foreground">{children}</div>
23+
</QueryProvider>
24+
)
25+
}
26+
27+
const preview: Preview = {
28+
tags: ["autodocs"],
29+
parameters: {
30+
options: {
31+
storySort: {
32+
order: [
33+
"Pages",
34+
["*", ["Components", "Views", "*"]],
35+
"Layout",
36+
"Features",
37+
["*", ["Components", "*"]],
38+
"UI",
39+
["*"],
40+
"*",
41+
],
42+
},
43+
},
44+
layout: "padded",
45+
controls: {
46+
matchers: {
47+
color: /(background|color)$/i,
48+
date: /Date$/i,
49+
},
50+
},
51+
nextjs: {
52+
appDirectory: true,
53+
},
54+
},
55+
decorators: [
56+
(Story) => (
57+
<StorybookProviders>
58+
<Story />
59+
</StorybookProviders>
60+
),
61+
],
62+
}
63+
64+
export default preview

0 commit comments

Comments
 (0)