UI Components
SaaSForge AI ships 25 shadcn/ui primitives plus chat-specific components, dashboard widgets, marketing sections, and billing UI. This guide is the map.
Where components live
src/components/
├── ui/ shadcn primitives (25 files)
├── chat/ Chat interface (interface, input, history, model selector, RAG indicator, attachments)
├── chat-demo/ Embeddable chat demo for landing page
├── documents/ Upload, listing, drag-drop, RAG state
├── dashboard/ KPI cards, usage stats, settings, API keys
├── billing/ Pricing table, Stripe checkout, invoices, credit cards
├── marketing/ Hero, CTA, integrations, generic helpers
├── hero2/ Alternate hero layouts
├── features/ Features grid
├── pricing/, pricing2/ Pricing tables (variants)
├── faq/, faq2/ FAQ accordions
├── testimonials/ Testimonials grid/carousel
├── footer/, footer2/ Footer (variants)
├── header/ Site header + nav
├── layout/ App shell, container helpers
├── sidebar/ Dashboard sidebar
├── docs/ In-product docs renderer
├── theme/ next-themes provider + toggle
├── blog/ Blog listing + post layouts
├── legal/ Legal pages
├── stats/ Numeric stats strip
├── process/ "How it works" steps
├── services/, comprehensive-services/
├── integrations/, integrations2/
├── most-popular-products/, product-list/, highlight-product/
├── help-center/, readiness/, need-custom-solution/
└── logo/ SVG logo + variants
The shadcn primitives (src/components/ui/)
| File | Purpose |
|---|---|
accordion.tsx | Collapsible panels |
avatar.tsx | User and AI avatars |
badge.tsx, status-badge.tsx, section-badge.tsx | Inline labels and status |
button.tsx | All button variants/sizes |
card.tsx | Container with header/content/footer |
carousel.tsx | Embla-based slider |
chart.tsx | Recharts wrapper |
dialog.tsx, sheet.tsx, popover.tsx, tooltip.tsx | Overlays |
dropdown.tsx, dropdown-menu.tsx | Menus |
empty-state.tsx, loading-state.tsx | Async state placeholders |
heading.tsx | Typography wrapper |
input.tsx | Form input |
message-bubble.tsx | Chat-style message bubble |
pagination.tsx | Numeric pagination |
section.tsx | Page section with consistent padding |
sonner.tsx | Toast provider (Sonner) |
table.tsx | Low-level table primitives |
tabs.tsx | Tabs/tab-list/tab-trigger |
All primitives use class-variance-authority for variants and clsx for composition. Edit them like any other source file.
Chat-specific components (src/components/chat/)
These are the building blocks of the chat experience. Each is independently editable.
| File | Role |
|---|---|
chat-interface.tsx | Top-level chat shell: wires input, history, streaming, errors |
chat-input.tsx | Textarea with auto-grow, send button, attachment button |
chat-history.tsx | Scrollable list of past messages |
markdown-message.tsx | Renders LLM output (Markdown + code blocks + tables) |
model-selector.tsx | Dropdown of available LLMs (OpenAI/Anthropic etc.) |
document-selector.tsx | Picker for which uploaded docs to use as RAG context |
attachment-button.tsx | "+" button to attach a file to a message |
suggestion-cards.tsx | Starter prompts shown in empty state |
ai-avatar.tsx | The AI/persona avatar shown next to assistant messages |
thinking-skeleton.tsx | Loading skeleton while a response streams |
Common edits
Change starter prompts (the empty-state cards): edit src/components/chat/suggestion-cards.tsx (or, if it pulls from config, edit the matching entry in src/config/ui/).
Restrict the model selector to a subset of models: edit src/config/ai-models.ts to remove or gate models, or edit model-selector.tsx to filter by user tier.
Re-skin the message bubble: edit src/components/chat/markdown-message.tsx. Tailwind classes on the wrapper control padding, background, max-width.
Custom AI avatar: replace the SVG/image in ai-avatar.tsx. Honor light/dark via Tailwind classes (e.g., dark:invert).
Embedding the chat on a landing page: use <ChatDemo /> from src/components/chat-demo/: it ships pre-wired with mocked responses for marketing.
Documents & RAG components (src/components/documents/)
For the upload + retrieval surface:
document-upload.tsx: file input with size/type validationdocument-list.tsx: list of uploaded docs, with delete + re-processdrag-drop-zone.tsx: drag-and-drop wrapperrag-indicator.tsx: shows when a chat response used document context
To support new file types beyond PDF, edit the validator in document-upload.tsx and the parser in src/lib/rag/ (covered in RAG Pipeline).
Dashboard widgets (src/components/dashboard/)
KPI cards, usage charts, credit history, settings panels, API key management. They wrap the chart.tsx primitive (Recharts) with brand colors via CSS variables.
Billing UI (src/components/billing/)
Stripe-aware components:
pricing-table.tsx: reads tiers fromsrc/config/pricing.tsstripe-checkout.tsx: wraps Stripe Checkout redirectcredit-card.tsx,invoice-list.tsx: billing history surface
Editing an existing primitive
Open the file under src/components/ui/ and adjust either:
- Tailwind classes in the base template literal: visual-only changes.
cva()definitions: add/remove variants and sizes.
Example: add a new xl size to button.tsx:
const buttonVariants = cva(
"inline-flex items-center justify-center ...",
{
variants: {
size: {
default: "h-9 px-4 py-2",
sm: "h-8 px-3 text-xs",
lg: "h-10 px-8",
xl: "h-12 px-10 text-base", // new
icon: "size-9",
},
},
},
);
Adding a brand-new primitive
The repo follows the standard shadcn CLI workflow:
pnpm dlx shadcn@latest add slider
The generator drops src/components/ui/slider.tsx using your existing Tailwind config and CSS variables. No further wiring needed.
components.json at the repo root holds the CLI config: only edit if you change the project structure.
When to edit a component vs. when to edit config
| Want to change... | Edit |
|---|---|
| Hero headline, FAQ Q&A, footer links | Config file in src/config/ui/ |
| Available LLM models / labels | src/config/ai-models.ts |
| Starter prompts in empty chat state | src/config/ui/chat-demo.ts or suggestion-cards.tsx |
| Color of all primary buttons | CSS variable in src/app/globals.css |
| Layout/order of section content | The section component file |
| Add a new variant (e.g., button size) | cva() block in the primitive |
| Add a brand-new primitive | pnpm dlx shadcn@latest add ... |
For brand basics (name, emails, logo paths) see Customization. For full theme work see Theming.