- Node.js 18+
- pnpm (recommended package manager)
- Git
# Clone the repository
git clone <repository-url>
cd jahannuma
# Install dependencies
pnpm install
# Set up environment variables
cp .env.example .env.local
# Edit .env.local with your Clerk and Airtable credentials
# Start development server
pnpm dev# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=
# Airtable Configuration
AIRTABLE_TOKEN=
AIRTABLE_BASE_ID=
# Optional: Additional services
NEXT_PUBLIC_ANALYTICS_ID=src/
├── types/ # Type definitions by feature
│ ├── airtable/ # Airtable base types
│ ├── features/ # Feature-specific types (ashaar, ghazlen, etc.)
│ ├── api/ # API request/response types
│ ├── ui/ # UI state types
│ └── index.ts # Barrel exports
├── hooks/ # Custom React hooks
│ ├── airtable/ # Data fetching hooks
│ ├── auth/ # Authentication hooks
│ ├── social/ # Social interaction hooks
│ ├── utils/ # Utility hooks
│ └── index.ts # Barrel exports
├── lib/ # Server-side utilities and services
│ ├── airtable/ # Airtable client and operations
│ ├── cache/ # Caching utilities
│ ├── user/ # User metadata management
│ ├── social/ # Social features
│ ├── i18n/ # Internationalization
│ └── seo/ # SEO utilities
├── components/ # UI components by feature
│ ├── ashaar/ # Ashaar-specific components
│ ├── ghazlen/ # Ghazal components
│ ├── nazmen/ # Nazm components
│ ├── rubai/ # Rubai components
│ ├── shared/ # Common components
│ └── index.ts # Barrel exports
└── utils/ # Client-side utilities
├── date.ts # Date formatting
├── text.ts # Text manipulation
├── url.ts # URL utilities
├── storage.ts # Local storage
├── performance.ts # Performance optimization
├── validation.ts # Form validation
└── index.ts # Barrel exports
When implementing a new feature:
// 1. Define types in src/types/features/
export interface NewFeatureRecord {
id: string;
title: string;
content: string;
}
// 2. Create hooks in src/hooks/
export function useNewFeature() {
return useAirtableList<NewFeatureRecord>("/api/airtable/new-feature");
}
// 3. Implement API routes in app/api/
export async function GET() {
// Server-side logic
}
// 4. Create components in src/components/
export function NewFeatureCard() {
// Component implementation
}// Preferred: Barrel imports for common usage
import { AshaarRecord, useAirtableList } from "@/src/types";
import { AsharCard } from "@/src/components";
// Specific imports when needed
import { formatDate } from "@/src/utils/date";
import { validateEmail } from "@/src/utils/validation";- Types: PascalCase (e.g.,
UserRecord,ApiResponse) - Components: PascalCase (e.g.,
AsharCard.tsx) - Hooks: camelCase starting with 'use' (e.g.,
useAirtableList.ts) - Utilities: camelCase (e.g.,
formatDate.ts) - API Routes: lowercase (e.g.,
route.ts,[id]/route.ts)
// app/api/airtable/[feature]/route.ts
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@clerk/nextjs/server";
export async function GET(request: NextRequest) {
try {
// Authentication check
const { userId } = await auth();
// Business logic
const data = await fetchData();
// Type-safe response
const response: ApiResponse<DataType> = {
success: true,
data,
};
return NextResponse.json(response);
} catch (error) {
// Error handling
return NextResponse.json(
{
success: false,
error: {
code: "FETCH_FAILED",
message: "Failed to fetch data",
},
},
{ status: 500 }
);
}
}- List endpoints:
GET /api/airtable/[feature] - Detail endpoints:
GET /api/airtable/[feature]/[id] - User actions:
POST /api/user/[action] - Search:
GET /api/search/[feature]?q=query
// src/components/feature/FeatureCard.tsx
import React from "react";
import { FeatureRecord } from "@/src/types";
interface FeatureCardProps {
data: FeatureRecord;
onLike?: (id: string) => void;
className?: string;
}
export function FeatureCard({ data, onLike, className }: FeatureCardProps) {
return <div className={className}>{/* Component implementation */}</div>;
}
// Export both named and default
export { FeatureCard as default };- Feature Components: Domain-specific UI (ashaar, ghazlen, etc.)
- Shared Components: Reusable UI elements
- Layout Components: Page structure and navigation
- Form Components: Input handling and validation
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Generate coverage report
pnpm test:coverage// src/utils/__tests__/date.test.ts
import { formatDate } from "../date";
describe("formatDate", () => {
it("should format date correctly", () => {
const result = formatDate("2023-12-25");
expect(result).toBe("December 25, 2023");
});
});// Use React.memo for expensive components
export const ExpensiveComponent = React.memo(({ data }) => {
return <div>{/* Complex rendering */}</div>;
});
// Use useMemo for expensive calculations
const expensiveValue = useMemo(() => {
return complexCalculation(data);
}, [data]);// Lazy load components
const LazyComponent = lazy(() => import("./LazyComponent"));
// Dynamic imports for utilities
const { heavyFunction } = await import("@/src/utils/heavy");// Use Next.js Image component
import Image from "next/image";
<Image
src="/path/to/image.jpg"
alt="Description"
width={500}
height={300}
priority={isAboveFold}
/>;# TypeScript checking
pnpm tsc --noEmit
# Linting
pnpm lint
# Build validation
pnpm build- Import Errors: Check path aliases in
tsconfig.json - Type Errors: Ensure proper type imports
- Build Failures: Verify all exports are properly defined
# Production build
pnpm build
# Start production server
pnpm start- Set production environment variables
- Configure domain and SSL
- Set up monitoring and analytics
- Configure CDN for static assets
- TypeScript: All new code must be TypeScript
- ESLint: Follow configured linting rules
- Prettier: Use for code formatting
- Comments: JSDoc for public APIs
- Create feature branch from
main - Implement changes following architecture
- Add tests for new functionality
- Update documentation as needed
- Submit PR with clear description
- TypeScript compilation passes
- All tests pass
- Performance impact considered
- Documentation updated
- Security implications reviewed