Configuration

Customizing Devfund Components

Learn how to customize and configure Devfund components to match your design system and requirements.

Component Props

All Devfund components accept minimal props for simplicity:

typescript
interface DevfundComponentProps {
  username: string;  // Required
}

Customizing Styles

Via Tailwind CSS Classes

Components use Tailwind CSS classes. Modify the generated component file directly:

tsx
// components/devfund/CardPaymentQR.tsx

// Change button color
className="bg-blue-400 hover:bg-blue-500"  // from bg-yellow-400

// Change modal background
className="bg-gray-100"  // from bg-white

// Change border radius
className="rounded-3xl"  // from rounded-2xl

Override via CSS Modules

If you prefer CSS Modules, add styles to your component:

css
/* components/devfund/CardPaymentQR.module.css */

.button {
  @apply bg-blue-400 hover:bg-blue-500 text-white px-6 py-3 rounded-lg;
}

.modal {
  @apply bg-white rounded-2xl shadow-xl p-8;
}

Then import in your component:

tsx
import styles from './CardPaymentQR.module.css';

// Use: className={styles.button}

Global Styles

Add global styles in your globals.css:

css
/* app/globals.css */

.devfund-button {
  @apply font-semibold px-6 py-3 rounded-lg transition-all;
}

.devfund-modal {
  @apply shadow-xl rounded-2xl;
}

Extending Components

Create Wrapper Component

Create a wrapper component for consistent styling:

tsx
// components/devfund/SupportButton.tsx
import CardPaymentQR from '@/components/devfund/CardPaymentQR';

interface SupportButtonProps {
  username: string;
  variant?: 'card' | 'glass' | 'minimal' | 'modern' | 'modal';
}

export function SupportButton({ username, variant = 'card' }: SupportButtonProps) {
  // Map variant to component
  const components: Record<string, typeof CardPaymentQR> = {
    card: CardPaymentQR,
    // ... other variants
  };
  
  const Component = components[variant] || CardPaymentQR;
  
  return (
    <div className="custom-wrapper">
      <Component username={username} />
    </div>
  );
}

Add Context

Add context and information around the component:

tsx
export default function SupportSection({ username }: { username: string }) {
  return (
    <section className="bg-gray-50 rounded-lg p-8">
      <div className="max-w-md mx-auto">
        <h3 className="text-xl font-bold mb-2">Support My Work</h3>
        <p className="text-gray-600 mb-6">
          Help me continue building amazing tools and libraries.
        </p>
        <CardPaymentQR username={username} />
      </div>
    </section>
  );
}

Configuration Options

API Endpoint

The component fetches from:

https://www.devfund.in/api/profile/{username}

To use a different API, modify the component's fetch URL:

tsx
const response = await fetch(
  `https://your-api.com/api/profile/${encodeURIComponent(username)}`
);

Timeout Duration

Default timeout is 10 seconds. To change it:

tsx
signal: AbortSignal.timeout(15000), // 15 seconds

Error Messages

Customize error messages:

tsx
if (response.status === 404) {
  throw new Error('Profile not found. Please check the username.');
}

if (response.status >= 500) {
  throw new Error('Our servers are temporarily unavailable.');
}

Theming

Light Theme

Use light colors and backgrounds:

tsx
// Button
className="bg-yellow-400 text-gray-900"

// Modal
className="bg-white text-gray-900"

// Background
className="bg-gray-50"

Dark Theme

Use dark colors and light text:

tsx
// Button
className="bg-gray-700 text-white"

// Modal
className="bg-gray-800 text-white"

// Background
className="bg-gray-900"

Advanced Customization

Add Analytics

Track component interactions:

tsx
const handleOpen = () => {
  setIsOpen(true);
  
  // Send analytics
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', 'payment_modal_opened', {
      username: username,
      component: 'CardPaymentQR'
    });
  }
};

Add Animations

Add custom animations using Framer Motion or CSS:

tsx
// With Framer Motion
import { motion } from 'framer-motion';

<motion.div
  initial={{ opacity: 0, scale: 0.95 }}
  animate={{ opacity: 1, scale: 1 }}
  transition={{ duration: 0.3 }}
  className="bg-white rounded-2xl..."
>
  {/* Modal content */}
</motion.div>

Add Form Validation

Enhance with input validation:

tsx
if (!username || username.trim() === '') {
  setError('Please provide a valid username');
  return;
}

if (username.length > 50) {
  setError('Username is too long');
  return;
}

Environment Variables

For API changes or configuration:

env
# .env.local
NEXT_PUBLIC_DEVFUND_API=https://devfund.in
NEXT_PUBLIC_DEVFUND_TIMEOUT=10000

Then use in component:

tsx
const apiUrl = process.env.NEXT_PUBLIC_DEVFUND_API || 'https://devfund.in';
const timeout = process.env.NEXT_PUBLIC_DEVFUND_TIMEOUT || 10000;

Build Optimization

Tree Shaking

Only import what you need:

tsx
// ✅ Good: Import specific component
import CardPaymentQR from '@/components/devfund/CardPaymentQR';

// ❌ Avoid: Import all if you only need one

Code Splitting

Lazy load components:

tsx
import dynamic from 'next/dynamic';

const CardPaymentQR = dynamic(() => 
  import('@/components/devfund/CardPaymentQR'),
  { loading: () => <p>Loading...</p> }
);

Performance Tips

  1. Memoize components if re-rendering frequently:

    tsx
    export default memo(CardPaymentQR);
  2. Use loading states to prevent layout shift:

    tsx
    const [loading, setLoading] = useState(false);
  3. Optimize images - QR codes should load quickly

  4. Cache API responses if possible:

    tsx
    // Implement caching logic
    const cached = localStorage.getItem(`user_${username}`);

Accessibility Customization

Enhance accessibility:

tsx
// Add ARIA descriptions
<button aria-describedby="support-help">
  Support Button
</button>
<p id="support-help" className="sr-only">
  Opens a payment interface to support via UPI
</p>

Integration Examples

With Next.js App Router

tsx
// app/support/page.tsx
import CardPaymentQR from '@/components/devfund/CardPaymentQR';

export default function SupportPage() {
  return <CardPaymentQR username="yourname" />;
}

With TypeScript

tsx
import CardPaymentQR from '@/components/devfund/CardPaymentQR';

interface PageProps {
  params: { username: string };
}

export default function Page({ params }: PageProps) {
  return <CardPaymentQR username={params.username} />;
}

Common Customizations

Remove QR Code

Remove QR code and show only UPI ID:

tsx
{/* Hide QR code */}
{profile.qrCodeImage && (
  <div className="hidden">
    <img src={profile.qrCodeImage} />
  </div>
)}

Show Multiple UPI IDs

Display all available UPI IDs:

tsx
<div className="space-y-3">
  {profile.upiIds.map((upi) => (
    <div key={upi.id} className="p-3 bg-gray-100 rounded">
      {upi.label}: {upi.upiId}
    </div>
  ))}
</div>

Add Default Amount

Show suggested payment amount:

tsx
{profile.defaultAmount && (
  <div className="mt-4 p-3 bg-yellow-50 rounded">
    Suggested: ₹{profile.defaultAmount}
  </div>
)}

Next Steps