Skip to content
Open
Changes from 2 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
234 changes: 234 additions & 0 deletions KNOWLEDGE.md

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.

🚩 KNOWLEDGE.md placed at root rather than docs/ directory

AGENTS.md prescribes docs/ as the directory for "Documentation files" and lists ARCHITECTURE.md, DEVELOPMENT.md, etc. there. KNOWLEDGE.md covers similar content (architectural patterns, conventions) and could arguably belong in docs/. However, there's existing precedent for root-level markdown files (DEPLOYMENT.md, ISSUES.md, SECURITY.md, CODE_OF_CONDUCT.md) that aren't in docs/ either. The distinction seems to be project governance/meta files at root vs. detailed technical docs in docs/. KNOWLEDGE.md straddles this line - it's a meta file about how to work in the codebase (like AGENTS.md) but also contains detailed technical documentation (like ARCHITECTURE.md). Not flagged as a rule violation since the AGENTS.md file organization section is descriptive of existing structure rather than an explicit prohibition on root-level docs.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
# Knowledge: DocuGen Patterns & Conventions

This document captures architectural decisions, patterns, and conventions that are implemented in the codebase but not formally documented elsewhere.
Comment on lines +1 to +3

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.

🚩 Significant content overlap with docs/ARCHITECTURE.md

KNOWLEDGE.md covers topics that substantially overlap with docs/ARCHITECTURE.md: lazy loading strategy (section 3), component architecture (section 4), theme system (section 5), and more. For example, both documents describe the lazy loading pattern in App.tsx, the theme context system, and the centralized content management approach. This creates a maintenance burden where changes need to be reflected in two places. The KNOWLEDGE.md intro says it captures things "not formally documented elsewhere" but much of it IS documented in ARCHITECTURE.md.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


---

## 1. Centralized Content Management

Most marketing copy lives in a single file: **`src/data/content.ts`**

- Components generally import content from this central source rather than containing inline text
- Known exceptions currently include inline copy in `src/components/Preview.tsx` and default props/docs in `src/components/ShareButtons.tsx`
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
- Export naming convention: uppercase constants (`SITE`, `NAV_LINKS`, `HERO_COPY`, `FEATURES`, `FAQS`, etc.)
- Content in `src/data/content.ts` is organized by feature/section

```typescript
// Example structure
export const SITE = { name: 'DocuGen', tagline: '...', ... };
export const HERO_COPY = { headline: '...', subheadline: '...', ... };
export const FEATURES = [{ icon: '...', title: '...', ... }, ...];
export const FAQS = [{ question: '...', answer: '...', ... }];
```

**Rationale:** Enables copy updates without touching component logic. Supports i18n migration.

---

## 2. CSS Class Utility (`cn()`)

**Location:** `src/lib/utils.ts`

```typescript
cn(...classes: (string | undefined | null | false)[]): string
```

Filters falsy values and joins class names with spaces.

```tsx
<button className={cn('base-class', isActive && 'active-class', className)}>
```

**Used throughout:** All components use this pattern for conditional styling.

---

## 3. Lazy Loading Strategy

**Location:** `src/App.tsx`

- Page-critical sections use static imports: `Hero`, `HowItWorks`, `FAQ`, `Navbar`, `Footer`
- Heavy sections are lazy-loaded: `Features`, `Testimonials`, `Preview`, `Pricing`, `Newsletter`

```typescript
const Features = lazy(() =>
import('./components/Features').then(module => ({ default: module.Features }))
);
```

- Each lazy component wrapped in `<Suspense fallback={<Loading />} />`
- Custom `Loading` spinner component for consistent loading UI

**Rationale:** Improves initial bundle load time. Critical path content renders immediately.

---

## 4. UI Component Library

**Location:** `src/components/ui/`

### Button

- Variants: `primary` (teal), `secondary` (dark), `ghost` (text)
- Sizes: `sm`, `md`, `lg`
- Props: `children`, `variant?`, `size?`, `className?`, `onClick?`, `type?`

### Input

- Dark theme styling with teal focus ring
- Supports `text` and `email` types
- Props: `placeholder?`, `type?`, `className?`, `disabled?`, `value?`, `onChange?`, `onBlur?`
- Supports all standard HTML input attributes via spread

### Container

- Responsive max-width wrapper (`max-w-7xl`)
- Horizontal padding: `px-4 sm:px-6 lg:px-8`
- Props: `children`, `className?`

### Skeleton

- Base component with variants: `text`, `circular`, `rectangular`
- Pre-built composite components:
- `SkeletonCard` - user card with avatar
- `SkeletonButton` - standard button dimensions
- `SkeletonInput` - form input height
- `SkeletonFeature` - icon + title + description
- `SkeletonTestimonial` - quote + author info

---

## 5. Theme System Architecture

**Location:** `src/lib/ThemeContext.tsx`

### Components

- `ThemeProvider` - wraps app, manages state
- `useTheme()` - hook for components (throws if used outside provider)
Comment thread
shazzar00ni marked this conversation as resolved.
Outdated

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

The useTheme() hook is not defined in src/lib/ThemeContext.tsx; it lives in src/lib/useTheme.ts and imports ThemeContext from ThemeContext.tsx. Please update this section’s “Location”/component breakdown so readers can find the hook in the correct file.

Suggested change
**Location:** `src/lib/ThemeContext.tsx`
### Components
- `ThemeProvider` - wraps app, manages state
- `useTheme()` - hook for components (throws if used outside provider)
**Locations:**
- `src/lib/ThemeContext.tsx` - `ThemeProvider`, `ThemeContext`, `Theme` type
- `src/lib/useTheme.ts` - `useTheme()` hook for components (throws if used outside provider)
### Components
- `ThemeProvider` - wraps app, manages state
- `ThemeContext` - shared context consumed by the hook
- `useTheme()` - hook for components

Copilot uses AI. Check for mistakes.
- Types: `Theme = 'dark' | 'light'`

### Behavior

- Initial theme from `localStorage` key `docugen-theme`, fallback to `prefers-color-scheme`
- Tailwind dark mode via `document.documentElement.classList.add('dark')` / `remove('dark')`
- Theme persistence wrapped in try-catch (non-critical)

```typescript
// In components
const { theme, toggleTheme } = useTheme();
```

---

## 6. Testing Patterns

### Test Location

- Tests co-located: `Component.test.tsx` next to `Component.tsx`
- Glob pattern: `src/**/*.test.{ts,tsx}`

### Test Setup (`src/test/setup.ts`)

- Global mocks:
- `IntersectionObserver` - stub implementation
- `localStorage` - mocked with `vi.fn()` for `getItem`, `setItem`, `clear`, `removeItem`
- Reset between tests: `localStorageMock.clear.mockClear()` and `mockReturnValue(null)`
- Uses `afterEach(cleanup())` from RTL
Comment thread
shazzar00ni marked this conversation as resolved.
Outdated

### Mock Pattern

```typescript
beforeEach(() => {
localStorageMock.clear.mockClear();
localStorageMock.getItem.mockClear();
localStorageMock.setItem.mockClear();
localStorageMock.getItem.mockReturnValue(null);
});
```

---

## 7. Analytics Integration

**Location:** `src/components/Analytics.tsx`

- Conditionally injects Plausible analytics
- Reads domain from `import.meta.env.VITE_PLAUSIBLE_DOMAIN`
- Script attributes: `defer`, `data-domain`
- Cleanup: removes script on unmount

```typescript
// Environment variable
VITE_PLAUSIBLE_DOMAIN = your - domain.com;

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

The environment variable example is formatted like JavaScript/TypeScript and includes spaces/semicolon (VITE_PLAUSIBLE_DOMAIN = your - domain.com;), which is not a valid .env entry and is easy to copy/paste incorrectly. Please change it to a correct .env example (e.g. VITE_PLAUSIBLE_DOMAIN=your-domain.com).

Suggested change
VITE_PLAUSIBLE_DOMAIN = your - domain.com;
VITE_PLAUSIBLE_DOMAIN=your-domain.com

Copilot uses AI. Check for mistakes.
```
Comment thread
shazzar00ni marked this conversation as resolved.

---

## 8. Custom Color Palette

**Location:** `tailwind.config.js`

### Extended Colors

- `light/*` - Light theme palette (50-950)
- `teal/*` - Brand accent color (50-950)
- `dark/*` - Dark theme palette (50-950)

### Custom Animations

- `fade-in` - opacity 0→1 over 0.5s
- `slide-up` - translateY(20px)→0 + fade over 0.6s
- `slide-up-delayed` - same with 0.2s delay

### Fonts

- Sans: `Inter` + system fallbacks
- Mono: `JetBrains Mono` + `Fira Code` fallbacks

---

## 9. Environment Variable Conventions

- Uses Vite `import.meta.env` (not `process.env`)
- Prefix: `VITE_` required for client-side variables
- Example: `VITE_PLAUSIBLE_DOMAIN`

---

## 10. Error & State Patterns

### ErrorBoundary

- Class component using `getDerivedStateFromError` + `componentDidCatch`
- Console logs errors with component stack
- Supports custom `fallback` prop
- Default fallback includes retry button

### Accordion (FAQ pattern)

- Single-item-open pattern (`openIndex: number | null`)
- Toggle handler: `setOpenIndex(prev === index ? null : index)`
Comment thread
shazzar00ni marked this conversation as resolved.
Outdated
- Animations via Framer Motion `AnimatePresence` + `height: auto`

---

## 11. Accessibility Patterns

- `aria-expanded` on collapsible buttons
- `aria-label` on icon-only buttons
- `role="dialog"` + `aria-label` + `aria-describedby` on modals
- `aria-invalid` on form inputs
- Focus ring styles on all interactive elements

---

## 12. Dev Server

- Vite dev server runs on **port 3000** (configured in `vite.config.ts`)
- Preview command serves production build on same port
- E2E tests target `http://localhost:5173` (Playwright default)
Comment thread
shazzar00ni marked this conversation as resolved.
Outdated
Comment thread
shazzar00ni marked this conversation as resolved.
Outdated

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

The port details here are internally inconsistent with the repo configuration: vite.config.ts sets the dev server to 3000, but playwright.config.ts configures webServer.port/baseURL as 5173. Also, vite preview does not use server.port by default (it has its own preview port unless configured). Please update this section to reflect the actual ports being used, or adjust the configs so dev/e2e/preview are aligned.

Suggested change
- Preview command serves production build on same port
- E2E tests target `http://localhost:5173` (Playwright default)
- `vite preview` does **not** automatically reuse `server.port`; its preview port must be configured separately if you want it to match dev
- E2E tests currently target `http://localhost:5173` (per Playwright configuration), so dev and E2E are not using the same port

Copilot uses AI. Check for mistakes.

---

_Last updated: 2026-04-24_

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the “Last updated” date to match this PR change date.

Line 234 shows 2026-04-24, but this PR was created on 2026-04-30.

Proposed fix
- _Last updated: 2026-04-24_
+ _Last updated: 2026-04-30_
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@KNOWLEDGE.md` at line 234, Update the "Last updated" date string in
KNOWLEDGE.md by replacing the existing "_Last updated: 2026-04-24_" text with
"_Last updated: 2026-04-30_" so the file reflects the PR creation date; locate
the exact string "_Last updated: 2026-04-24_" and change only the date portion.

Loading