Skip to content
Open
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
235 changes: 235 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,235 @@
# 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

**Locations:** `src/lib/ThemeContext.tsx` (provider), `src/lib/useTheme.ts` (hook)

### Components

- `ThemeProvider` - wraps app, manages state
- `useTheme()` - hook for components (throws if used outside provider)
- 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 (wrapped in callback, not passed directly)

### 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 (.env file)
VITE_PLAUSIBLE_DOMAIN=your-domain.com
```
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 => (prev === index ? null : index))`
- 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 & E2E Port Conflict

- Vite dev server runs on **port 3000** (configured in `vite.config.ts`)
- Preview command serves production build on same port (3000)
- **Resolved:** Playwright config (`playwright.config.ts`) was updated to use port 3000, matching the Vite dev server
- Both `baseURL` and `webServer.port` in Playwright config are set to 3000

---

_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