-
Notifications
You must be signed in to change notification settings - Fork 1
docs: add KNOWLEDGE.md with codebase patterns and conventions #174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
82e90ec
249a38c
05f858d
baf366c
22ad510
4def0ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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` | ||
|
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 | ||
| ``` | ||
|
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_ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update the “Last updated” date to match this PR change date. Line 234 shows Proposed fix- _Last updated: 2026-04-24_
+ _Last updated: 2026-04-30_🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
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 indocs/. However, there's existing precedent for root-level markdown files (DEPLOYMENT.md, ISSUES.md, SECURITY.md, CODE_OF_CONDUCT.md) that aren't indocs/either. The distinction seems to be project governance/meta files at root vs. detailed technical docs indocs/. 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.Was this helpful? React with 👍 or 👎 to provide feedback.