Skip to content

Commit effeda9

Browse files
Readme updated
1 parent 7f8e7ed commit effeda9

5 files changed

Lines changed: 59 additions & 20 deletions

File tree

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,37 @@ It includes a dashboard experience for history and favorites, plus subscription-
6767
- `get-onboarding-status/`: returns prior onboarding state and marks first-time users onboarded
6868
- Stripe sync functions (`create-stripe-checkout`, `stripe-webhook`, `create-stripe-portal`) 💳
6969

70+
## Local development 🛠️
71+
72+
From the `frontend/` directory:
73+
74+
| Command | Description |
75+
|--------|-------------|
76+
| `npm run dev` | Start the Next.js dev server |
77+
| `npm run build` | Production build |
78+
| `npm run start` | Run the production server (after `build`) |
79+
| `npm run lint` | ESLint (Next.js + TypeScript rules) |
80+
| `npm run test` | Vitest — runs all `*.test.ts(x)` / `*.spec.ts(x)` files |
81+
82+
Requirements: **Node.js 20+** (matches CI).
83+
84+
## Testing 🧪
85+
86+
- **Runner:** [Vitest](https://vitest.dev/) v4 with **jsdom** as the test environment.
87+
- **Assertions / DOM:** [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) and [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) (via `vitest.setup.ts`).
88+
- **Config:** `frontend/vitest.config.ts` — path alias `@/` matches the Next.js app, `include` pattern `**/*.{test,spec}.{ts,tsx}`.
89+
- **Current tests:** `frontend/app/page.test.tsx` — smoke test for the landing page (branding, primary heading, signup links).
90+
91+
Add new tests next to the code they cover using the `*.test.tsx` (or `.test.ts`) naming convention.
92+
93+
## Continuous integration (GitHub Actions) 🔄
94+
95+
Workflows live under [`.github/workflows/`](.github/workflows/) and run on **push** and **pull_request** to **`main`**. Both use **Node 20** and `npm ci` in **`frontend/`**.
96+
97+
| Workflow | File | What it runs |
98+
|----------|------|----------------|
99+
| **Linter** | [`ci.yml`](.github/workflows/ci.yml) | `npm run lint` |
100+
| **Frontend** | [`frontend-tests.yml`](.github/workflows/frontend-tests.yml) | `npm run test` (Vitest) |
101+
102+
Together they keep ESLint clean and the Vitest suite passing on every change to `main`.
103+

frontend/app/dashboard/layout.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
import { DashboardSidebar } from "@/components/dashboard-sidebar";
2-
import { DashboardOnboardingTrigger } from "@/components/dashboard-onboarding-trigger";
32

43
export default function DashboardLayout({
54
children,
65
}: {
76
children: React.ReactNode;
87
}) {
9-
return (
10-
<>
11-
<DashboardOnboardingTrigger />
12-
<DashboardSidebar>{children}</DashboardSidebar>
13-
</>
14-
);
8+
return <DashboardSidebar>{children}</DashboardSidebar>;
159
}

frontend/app/layout.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ const geistMono = Geist_Mono({
1414
});
1515

1616
export const metadata: Metadata = {
17-
title: "Create Next App",
18-
description: "Generated by create next app",
17+
title: "What to read AI",
18+
description: "Personalized book recommendations from your shelf photos, favorites, and preferences.",
19+
icons: {
20+
icon: [{ url: "/logo/default.png", type: "image/png" }],
21+
shortcut: "/logo/default.png",
22+
apple: "/logo/default.png",
23+
},
1924
};
2025

2126
export default function RootLayout({

frontend/components/dashboard-onboarding-trigger.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ import { Button } from "@/components/ui/button";
55
import { createClient } from "@/lib/supabase/client";
66
import { DASHBOARD_ONBOARDING_START_EVENT } from "@/lib/dashboard-onboarding-events";
77

8-
export function DashboardOnboardingTrigger() {
8+
/** Auto-starts the product tour for users who are not yet onboarded (invokes edge function once). */
9+
function useDashboardOnboardingAutoStart() {
910
const autoStartedRef = useRef(false);
1011

11-
const handleStartOnboarding = () => {
12-
window.dispatchEvent(new Event(DASHBOARD_ONBOARDING_START_EVENT));
13-
};
14-
1512
useEffect(() => {
1613
if (autoStartedRef.current) return;
1714

@@ -33,13 +30,18 @@ export function DashboardOnboardingTrigger() {
3330

3431
void run();
3532
}, []);
33+
}
34+
35+
export function DashboardDemoButton() {
36+
useDashboardOnboardingAutoStart();
37+
38+
const handleStartOnboarding = () => {
39+
window.dispatchEvent(new Event(DASHBOARD_ONBOARDING_START_EVENT));
40+
};
3641

3742
return (
38-
<div className="fixed right-4 top-3 z-50 rounded-md border border-border bg-background/95 p-0.5 shadow-sm backdrop-blur-sm">
39-
<Button type="button" variant="outline" size="sm" onClick={handleStartOnboarding}>
40-
Demo App
41-
</Button>
42-
</div>
43+
<Button type="button" variant="outline" size="sm" onClick={handleStartOnboarding}>
44+
Demo App
45+
</Button>
4346
);
4447
}
45-

frontend/components/dashboard-sidebar.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import { createClient } from "@/lib/supabase/client";
2222
import { useDashboardUser } from "@/hooks/use-dashboard-user";
2323
import { useDashboardOnboardingListener } from "@/hooks/use-dashboard-onboarding-listener";
24+
import { DashboardDemoButton } from "@/components/dashboard-onboarding-trigger";
2425
import { DashboardSidebarNav } from "@/components/dashboard-sidebar-nav";
2526
import { DashboardSidebarProfile } from "@/components/dashboard-sidebar-profile";
2627

@@ -85,6 +86,9 @@ export function DashboardSidebar({ children }: { children: React.ReactNode }) {
8586
<SidebarInset>
8687
<header className="flex h-12 shrink-0 items-center gap-2 border-b border-border bg-background px-4">
8788
<SidebarTrigger />
89+
<div className="ml-auto flex items-center gap-2">
90+
<DashboardDemoButton />
91+
</div>
8892
</header>
8993
{children}
9094
</SidebarInset>

0 commit comments

Comments
 (0)