Skip to content

Latest commit

 

History

History
475 lines (345 loc) · 13.5 KB

File metadata and controls

475 lines (345 loc) · 13.5 KB

Devus — Contributing & Architecture Guide

Use this document when iterating on Devus outside of Lovable (VS Code, Cursor, WebStorm, etc.). It captures every architectural decision so the codebase stays consistent regardless of who — or what — is editing it.


Table of Contents

  1. Quick Start
  2. Project Architecture
  3. Tech Stack & Versions
  4. Design System Rules
  5. Component Conventions
  6. Routing & Pages
  7. State Management
  8. Backend (Lovable Cloud / Supabase)
  9. Edge Functions
  10. Authentication
  11. Data Layer
  12. Animation Guidelines
  13. MCP / Context7 Usage
  14. Testing
  15. Do-Not-Touch Files
  16. Commit & PR Conventions

Quick Start

# Install dependencies (use bun — it's what Lovable uses)
bun install

# Start dev server
bun run dev          # http://localhost:8080

# Run tests
bun run test

# Production build
bun run build

Environment variables are managed via .env (auto-generated by Lovable Cloud). Never edit .env manually. If you need additional secrets, add them through Lovable's secrets manager or Supabase dashboard.


Project Architecture

src/
├── components/          # Reusable UI components
│   ├── ui/              # shadcn/ui primitives (DO NOT customize inline)
│   └── dashboard/       # Dashboard-specific components
├── contexts/            # React contexts (AuthContext)
├── hooks/               # Custom hooks (use-tools, use-ai-search, etc.)
├── integrations/
│   └── supabase/        # Auto-generated client & types — DO NOT EDIT
├── lib/
│   ├── data.ts          # Static tool catalog + query helpers
│   ├── types.ts         # Shared TypeScript interfaces
│   └── utils.ts         # cn() and utility functions
├── pages/               # Route-level page components
├── index.css            # Design system tokens (THE source of truth)
└── main.tsx             # App entry point

supabase/
├── config.toml          # Auto-managed — DO NOT EDIT
└── functions/           # Deno edge functions
    ├── search-tools/    # AI-powered tool search
    └── weekly-tools/    # Weekly tool discovery via Perplexity

Tech Stack & Versions

Layer Technology Notes
Framework React 18 No Next.js, no SSR
Build Vite 5 SWC plugin for React
Language TypeScript (strict: false) noImplicitAny: false for flexibility
Styling Tailwind CSS 3.4 tailwindcss-animate plugin
Components shadcn/ui (Radix primitives) Default style, CSS variables enabled
Animation Framer Motion 12 Primary animation library
Routing React Router DOM 6 Client-side SPA routing
State React Query 5 + React Context No Redux, no Zustand
Backend Supabase (via Lovable Cloud) Auth, DB, Edge Functions, Storage
Package Manager bun Lockfile: bun.lockb

Adding Dependencies

When adding packages outside Lovable, use Context7 MCP (see MCP section) to verify correct package names and latest stable versions before installing:

bun add <package>@<version>

Design System Rules

⚠️ CRITICAL: Never use raw color values in components

All colors flow through CSS custom properties defined in src/index.css and mapped in tailwind.config.ts.

Token Flow

index.css (HSL values)  →  tailwind.config.ts (hsl(var(--token)))  →  Components (Tailwind classes)

Core Tokens

Token Purpose Example Class
--background Page background bg-background
--foreground Primary text text-foreground
--primary Brand cyan accent bg-primary, text-primary
--card Card backgrounds bg-card
--muted Subdued backgrounds bg-muted
--muted-foreground Secondary text text-muted-foreground
--border Borders border-border
--glow Cyan glow effects text-glow
--surface Elevated surfaces bg-surface
--dash-* Dashboard-specific tokens bg-dash-card

❌ DON'T

<div className="bg-black text-white border-gray-700">  // ← raw colors
<div className="bg-[#0a0a0f]">                          // ← hardcoded hex

✅ DO

<div className="bg-background text-foreground border-border">
<div className="bg-surface-elevated">

Typography

Font Variable Usage
Sora font-sans Landing page, headings
Inter font-dash Dashboard UI
JetBrains Mono font-mono Code snippets, badges

Glassmorphism Pattern

The landing page uses a consistent glass utility. Apply it via:

<div className="glass glass-hover rounded-xl p-5">

These classes are defined in index.css under @layer components.


Component Conventions

File Naming

  • Components: PascalCase.tsx (e.g., ToolStackShowcase.tsx)
  • Hooks: use-kebab-case.ts (e.g., use-tools.ts)
  • Pages: PascalCase.tsx in src/pages/

Component Structure

// 1. Imports (React, libraries, local)
import { useState } from "react";
import { motion } from "framer-motion";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

// 2. Interface
interface MyComponentProps {
  title: string;
  onAction: () => void;
}

// 3. Named export (no default exports for components)
export function MyComponent({ title, onAction }: MyComponentProps) {
  // 4. Hooks first
  const [state, setState] = useState(false);

  // 5. Handlers
  const handleClick = () => { ... };

  // 6. Render
  return ( ... );
}

Import Aliases

Always use the @/ alias:

import { tools } from "@/lib/data";     // ✅
import { tools } from "../../lib/data"; // ❌

shadcn/ui Components

  • Live in src/components/ui/
  • Customize via variants in the component file, not inline styles
  • When adding new shadcn components, use the CLI: bunx shadcn@latest add <component>

Routing & Pages

Route Page Component Auth Required
/ Index.tsx No
/tool/:id ToolDetail.tsx No
/dashboard Dashboard.tsx Yes
/submit Submit.tsx Yes
/favorites Redirects → /dashboard
* NotFound.tsx No

Protected routes redirect unauthenticated users to / with state: { openAuth: true }.


State Management

Pattern: Hooks + Context

  • AuthContext (src/contexts/AuthContext.tsx): User session, profile, auth actions
  • Custom hooks (src/hooks/): Domain-specific logic (favorites, tools, search)
  • React Query: Server state (weekly tools cache, etc.)
  • localStorage: Offline fallback for favorites/upvotes when unauthenticated

Rules

  1. No global state libraries (Redux, Zustand, Jotai)
  2. Colocate state as close to usage as possible
  3. Use React Query for anything fetched from Supabase
  4. Auth state always comes from useAuth() hook

Backend (Lovable Cloud / Supabase)

Client Usage

import { supabase } from "@/integrations/supabase/client";

Never create additional Supabase clients. The auto-generated one handles auth tokens automatically.

Database Tables

Table Purpose RLS
profiles User profile data (synced from auth) Yes
discovered_tools AI-discovered tools Yes
weekly_tools_cache Weekly tool drops cache Yes

Database Migrations

All schema changes must go through Lovable's migration tool or SQL files in supabase/migrations/. Never alter the schema via direct SQL in production.

Row-Level Security

Every table has RLS enabled. When adding new tables:

  1. Always enable RLS
  2. Create policies for SELECT, INSERT, UPDATE, DELETE as needed
  3. Use auth.uid() for user-scoped data

Edge Functions

Located in supabase/functions/. Written in Deno (TypeScript).

Function Purpose Required Secrets
search-tools Firecrawl-powered tool search FIRECRAWL_API_KEY
weekly-tools Perplexity + Gemini weekly discovery PERPLEXITY_API_KEY, LOVABLE_API_KEY

Creating New Edge Functions

supabase functions new my-function

Structure:

supabase/functions/my-function/
└── index.ts

Always include CORS headers:

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};

Authentication

  • Provider: Supabase Auth (email/password, Google OAuth, GitHub OAuth)
  • Context: AuthProvider wraps the entire app in App.tsx
  • Profile sync: handle_new_user() trigger creates a profiles row on signup
  • Email confirmation: Enabled by default — do NOT auto-confirm unless explicitly required
  • No anonymous signups: Always require email + password

Auth Flow

User signs up → Supabase creates auth.users row
                → handle_new_user() trigger creates profiles row
                → AuthContext picks up session via onAuthStateChange
                → Profile fetched from profiles table

Data Layer

Static Data (src/lib/data.ts)

The primary tool catalog is a static TypeScript array. This is intentional for MVP speed. Tools are defined with full metadata:

interface Tool {
  id: string;
  name: string;
  description: string;
  category: Category;
  tags: Tag[];
  url: string;
  // ... see src/lib/types.ts for full shape
}

Categories & Tags

Categories and tags are typed enums in src/lib/types.ts. When adding new ones:

  1. Add to the Category or Tag union type
  2. Add metadata to the categories or tags array in data.ts
  3. Ensure consistency across all filter UIs

Animation Guidelines

Context Library Pattern
Page transitions Framer Motion motion.div with initial/animate/exit
Scroll reveals Framer Motion whileInView with viewport={{ once: true }}
Hover effects Framer Motion whileHover={{ y: -4 }}
Staggered lists Framer Motion delay: index * 0.06
Micro-interactions Tailwind transition-all duration-200

Rules

  1. Use framer-motion for anything beyond simple CSS transitions
  2. Keep durations under 400ms for UI interactions
  3. Use once: true on scroll animations to avoid re-triggering
  4. Stagger delays: 40-80ms between items

MCP / Context7 Usage

When working outside Lovable, use Context7 MCP to ensure dependency accuracy.

What Context7 Does

Context7 resolves library documentation in real-time, ensuring you install correct versions and use up-to-date APIs. This prevents:

  • Installing deprecated packages
  • Using outdated API patterns
  • Version conflicts with existing dependencies

Setup in Your IDE

  1. Install the Context7 MCP server in your IDE's MCP configuration
  2. When adding a new dependency, query Context7 first:
    • "What's the latest stable version of <package>?"
    • "Show me the API for <package> v<version>"
  3. Cross-reference with the existing package.json to avoid conflicts

Workflow

1. Need a new package? → Ask Context7 for latest stable version
2. Context7 confirms version + API → bun add <package>@<version>
3. Implement using verified API patterns
4. Ensure import style matches project conventions (@/ aliases, named exports)

Packages to Be Careful With

Package Current Version Notes
framer-motion ^12.x API changed significantly from v10/v11
react-router-dom ^6.x v7 has breaking changes — stay on v6
@tanstack/react-query ^5.x v5 has different defaults than v4
lucide-react ^0.462 Icon names change between versions
shadcn/ui CLI-based Always use bunx shadcn@latest add

Testing

bun run test          # Single run
bun run test:watch    # Watch mode
  • Framework: Vitest + jsdom
  • Location: src/test/ or colocated *.test.ts files
  • Setup: src/test/setup.ts

Do-Not-Touch Files

These are auto-generated and will be overwritten:

File Reason
.env Managed by Lovable Cloud
src/integrations/supabase/client.ts Auto-generated Supabase client
src/integrations/supabase/types.ts Auto-generated from DB schema
supabase/config.toml Managed by Lovable Cloud
bun.lockb Generated by bun
supabase/migrations/* Managed via migration tool

Commit & PR Conventions

Branch Naming

feature/tool-stack-showcase
fix/auth-modal-scroll
refactor/dashboard-sidebar

Commit Messages

feat: add ToolStackShowcase with category filtering
fix: make auth modal scrollable on mobile
refactor: extract glass card into shared component
chore: update framer-motion to v12.30

Before Pushing

  1. bun run build — ensure no TypeScript errors
  2. bun run test — all tests pass
  3. Verify no raw color values in new components
  4. Verify all new components use @/ import aliases
  5. Verify design tokens from index.css are used (no hardcoded colors)

Questions?

Follow the build journey on X: @builtbyangelo