Generate a fully functional, multi-page Next.js MVP application for 'SoilSense', a SaaS platform designed to help farmers and land managers monitor, analyze, and improve soil health, addressing the problem of soil degradation due to over-farming as highlighted in recent scientific findings.
**1. PROJECT OVERVIEW:**
SoilSense aims to combat soil degradation by providing actionable insights into soil health. The platform will ingest soil data (either through integrated IoT sensors or manual input), analyze it for risks like compaction and nutrient depletion, and offer tailored recommendations for sustainable farming practices. The core value proposition is to enable users to maintain soil fertility, increase crop yields, mitigate the impact of natural events exacerbated by poor soil conditions (like erosion or reduced water retention), and promote long-term land sustainability.
**2. TECH STACK:**
- **Framework:** Next.js (App Router)
- **UI Library:** shadcn/ui for accessible and reusable components.
- **Styling:** Tailwind CSS for utility-first styling.
- **Database ORM:** Drizzle ORM with PostgreSQL (using Vercel Postgres or a similar managed service).
- **Authentication:** NextAuth.js (for email/password and potentially OAuth).
- **State Management:** React Context API and Zustand for global state.
- **Data Fetching:** Server Actions and React Server Components for efficient data handling.
- **Charting:** Recharts or Chart.js for data visualization.
- **Form Handling:** React Hook Form with Zod for validation.
- **Deployment:** Vercel (recommended for seamless Next.js deployment).
**3. DATABASE SCHEMA (PostgreSQL with Drizzle ORM):**
```typescript
// schema.ts
import { pgTable, serial, varchar, text, timestamp, integer, real, boolean, pgEnum } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
// Enum for soil condition risk levels
export const riskLevelEnum = pgEnum('risk_level', ['low', 'medium', 'high', 'critical']);
// Users Table
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: varchar('name'),
email: varchar('email', { length: 255 }).notNull().unique(),
password: varchar('password', { length: 255 }).notNull(), // Hashed password
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const userRelations = relations(users, ({ many }) => ({
farms: many(farms),
}));
// Farms Table
export const farms = pgTable('farms', {
id: serial('id').primaryKey(),
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
name: varchar('name', { length: 255 }).notNull(),
location: varchar('location', { length: 255 }),
sizeAcres: real('size_acres'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const farmRelations = relations(farms, ({ one, many }) => ({
user: one(users, { fields: [farms.userId], returns: [users.id] }),
fields: many(fields),
}));
// Fields Table (Sections within a farm)
export const fields = pgTable('fields', {
id: serial('id').primaryKey(),
farmId: integer('farm_id').notNull().references(() => farms.id, { onDelete: 'cascade' }),
name: varchar('name', { length: 255 }).notNull(),
coordinates: text('coordinates'), // e.g., GeoJSON or simple lat/lng string
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const fieldRelations = relations(fields, ({ one, many }) => ({
farm: one(farms, { fields: [fields.farmId], returns: [farms.id] }),
soilReadings: many(soilReadings),
}));
// Soil Readings Table
export const soilReadings = pgTable('soil_readings', {
id: serial('id').primaryKey(),
fieldId: integer('field_id').notNull().references(() => fields.id, { onDelete: 'cascade' }),
timestamp: timestamp('timestamp').defaultNow(),
// Core soil parameters
moisturePercent: real('moisture_percent'),
ph: real('ph'),
organicMatterPercent: real('organic_matter_percent'),
compactionIndex: real('compaction_index'), // Higher value indicates more compaction
// Other potential parameters: NPK levels, temperature, etc.
temperatureCelsius: real('temperature_celsius'),
nitrogen: real('nitrogen'),
phosphorus: real('phosphorus'),
potassium: real('potassium'),
// Risk Assessment
compactionRisk: riskLevelEnum('compaction_risk'),
nutrientDeficiencyRisk: riskLevelEnum('nutrient_deficiency_risk'),
moistureStressRisk: riskLevelEnum('moisture_stress_risk'),
});
export const soilReadingRelations = relations(soilReadings, ({ one }) => ({
field: one(fields, { fields: [soilReadings.fieldId], returns: [fields.id] }),
}));
// Recommendations Table
export const recommendations = pgTable('recommendations', {
id: serial('id').primaryKey(),
fieldId: integer('field_id').notNull().references(() => fields.id, { onDelete: 'cascade' }),
recommendationText: text('recommendation_text').notNull(),
type: varchar('type', { length: 255 }), // e.g., 'Crop Rotation', 'Fertilization', 'Tillage'
generatedAt: timestamp('generated_at').defaultNow(),
isActive: boolean('is_active').default(true),
});
export const recommendationRelations = relations(recommendations, ({ one }) => ({
field: one(fields, { fields: [recommendations.fieldId], returns: [fields.id] }),
}));
```
**4. CORE FEATURES & USER FLOW:**
* **User Authentication (Sign Up / Login / Logout):**
* Flow: User accesses `/auth/login`. Sees email/password fields and a 'Sign Up' link. Upon clicking 'Sign Up', they are directed to `/auth/signup` with similar fields. Successful login/signup redirects to the dashboard. Logout clears session and redirects to login.
* Auth Implementation: NextAuth.js with credentials provider. JWT sessions stored in cookies.
* **Dashboard (Overview):**
* Flow: After login, user lands on `/dashboard`. Displays a summary of their farms, recent soil readings, high-risk alerts (e.g., critical compaction risk), and a quick link to add new data/farm.
* Components: Farm list overview, summary cards for key risks, recent activity feed.
* **Farm Management (CRUD):**
* Flow: From the dashboard, user can click 'Add Farm' (navigates to `/farms/new`). Fills a form (name, location, size). Can view/edit/delete existing farms from a list page (`/farms`). Each farm has its own detail page (`/farms/[farmId]`).
* Fields: Each farm can contain multiple fields. User can add fields within a farm (`/farms/[farmId]/fields/new`), providing name and optional coordinates.
* **Soil Data Input:**
* Flow: User navigates to a specific field's page (`/fields/[fieldId]`). Clicks 'Add Soil Reading'. A modal or form appears to input parameters (moisture, pH, organic matter, etc.). Alternatively, if sensors are integrated, data populates automatically via an API route.
* Validation: Use React Hook Form and Zod to validate all inputs before submission. Ensure numerical ranges are respected (e.g., pH 0-14).
* **Soil Analysis & Risk Assessment:**
* Flow: Triggered automatically after new data input or on-demand from the field detail page. Backend logic (or a dedicated microservice) processes readings against predefined thresholds (e.g., compaction index > X is 'high risk'). Risk levels are assigned and stored in `soilReadings`.
* Logic: Server-side processing using Drizzle ORM queries to fetch relevant readings and apply risk assessment rules.
* **Recommendations Engine:**
* Flow: Based on detected risks (compaction, nutrient deficiency), the system generates relevant recommendations (e.g., 'Implement cover cropping', 'Adjust NPK fertilization ratio'). These are stored in the `recommendations` table and displayed on the field detail page.
* MVP Scope: Start with rule-based recommendations. Future iterations can involve ML models.
* **Resource Center:**
* Flow: A static or dynamic page (`/resources`) containing articles, guides, and videos on soil health management. Content can be managed via a CMS or directly in the codebase for MVP.
**5. API & DATA FETCHING:**
- **API Routes:** Utilize Next.js API Routes (or Server Actions) for backend logic.
- `POST /api/auth/signup`, `POST /api/auth/login`: Handle user registration and login (integrated with NextAuth.js).
- `GET /api/farms`, `POST /api/farms`, `GET /api/farms/[farmId]`, `PUT /api/farms/[farmId]`, `DELETE /api/farms/[farmId]`: Farm CRUD operations.
- `POST /api/farms/[farmId]/fields`: Create a new field.
- `POST /api/fields/[fieldId]/readings`: Input new soil reading.
- `GET /api/fields/[fieldId]/readings`: Fetch historical readings for a field (with pagination).
- `GET /api/fields/[fieldId]/recommendations`: Fetch relevant recommendations for a field.
- **Data Fetching:** Primarily use React Server Components and Server Actions for fetching data directly on the server, reducing client-side JavaScript and improving performance. Use `fetch` with appropriate caching strategies. For dynamic data or mutations, use Server Actions directly from client components.
**6. COMPONENT BREAKDOWN:**
- **`app/layout.tsx`:** Root layout, includes global styles, AuthProvider, and main structure.
- **`app/page.tsx`:** Landing page (brief intro to SoilSense).
- **`app/(auth)/login/page.tsx`:** Login form component.
- **`app/(auth)/signup/page.tsx`:** Signup form component.
- **`app/(app)/dashboard/page.tsx`:** Main dashboard view. Fetches user's farms, recent alerts. Uses `FarmListSummary` and `AlertsFeed` components.
- **`app/(app)/farms/page.tsx`:** List of all user's farms. Uses `FarmListItem` and `AddFarmButton` components.
- **`app/(app)/farms/new/page.tsx`:** Form for creating a new farm (`FarmForm` component).
- **`app/(app)/farms/[farmId]/page.tsx`:** Farm detail page. Shows farm info, list of fields. Uses `FarmDetailsCard`, `FieldList` components.
- **`app/(app)/fields/[fieldId]/page.tsx`:** Field detail page. Shows field info, historical readings, recommendations. Uses `FieldDetailsCard`, `SoilReadingsChart`, `SoilReadingsTable`, `RecommendationsList`, `AddSoilReadingForm` (modal).
- **`app/(app)/resources/page.tsx`:** Resource center page. Displays articles/guides.
- **`app/components/ui/`:** All shadcn/ui components (Button, Input, Card, Table, Modal, etc.).
- **`app/components/layout/`:** `Navbar`, `Sidebar` (for app navigation), `Footer`.
- **`app/components/forms/`:** `LoginForm`, `SignupForm`, `FarmForm`, `FieldForm`, `SoilReadingForm`.
- **`app/components/charts/`:** `SoilReadingsChart` (using Recharts).
- **`app/components/table/`:** `SoilReadingsTable`, `RecommendationsTable`.
- **State Management:** Context API for theme/auth state. Zustand for potentially complex global states like form validation status or shared UI states.
**7. UI/UX DESIGN & VISUAL IDENTITY:**
- **Style:** Minimalist Clean with a touch of nature-inspired elements.
- **Color Palette:** Primary: Deep Green (#2E7D32), Secondary: Earthy Brown (#8D6E63), Accent: Sky Blue (#4FC3F7), Neutral: Off-white (#F5F5F5), Text: Dark Gray (#333333).
- **Typography:** Use a clean sans-serif font like 'Inter' or 'Roboto'. H1/H2 for main titles, body text for descriptions.
- **Layout:** Consistent layout with a sidebar for navigation in authenticated sections. Clear content hierarchy using cards and spacing. Responsive design adhering to mobile-first principles.
- **Interactions:** Subtle hover effects on buttons and cards. Smooth page transitions using Next.js's built-in capabilities or a library like `Framer Motion` (optional for MVP).
- **Visuals:** Use of icons representing soil, plants, water, and data. Minimal use of imagery, focusing on clean data presentation.
**8. SAMPLE/MOCK DATA:**
* **User:** `{ id: 1, name: 'Ahmet Yılmaz', email: 'ahmet.yilmaz@example.com' }`
* **Farm:** `{ id: 101, userId: 1, name: 'Güneşli Tarla', location: 'İzmir', sizeAcres: 50.5 }`
* **Field:** `{ id: 1001, farmId: 101, name: 'Mısır Tarlası Batı', coordinates: '38.4237, 27.1532' }`
* **Soil Reading (Good Condition):** `{ id: 10001, fieldId: 1001, timestamp: '2024-07-26T10:00:00Z', moisturePercent: 65.2, ph: 6.8, organicMatterPercent: 3.1, compactionIndex: 1.2, compactionRisk: 'low', nutrientDeficiencyRisk: 'low', moistureStressRisk: 'low' }`
* **Soil Reading (Compaction Risk):** `{ id: 10002, fieldId: 1001, timestamp: '2024-07-26T11:00:00Z', moisturePercent: 60.1, ph: 6.5, organicMatterPercent: 2.9, compactionIndex: 2.8, compactionRisk: 'high', nutrientDeficiencyRisk: 'medium', moistureStressRisk: 'medium' }`
* **Soil Reading (Nutrient Deficiency):** `{ id: 10003, fieldId: 1001, timestamp: '2024-07-26T12:00:00Z', moisturePercent: 55.0, ph: 6.2, organicMatterPercent: 2.5, compactionIndex: 2.1, nitrogen: 5.0, phosphorus: 10.0, potassium: 15.0, compactionRisk: 'medium', nutrientDeficiencyRisk: 'high', moistureStressRisk: 'medium' }`
* **Recommendation:** `{ id: 1, fieldId: 1001, recommendationText: 'Increase organic matter through cover cropping. Consider planting legumes like vetch.', type: 'Soil Health Improvement', generatedAt: '2024-07-26T13:00:00Z', isActive: true }`
**9. TURKISH TRANSLATIONS:**
- **SoilSense:** Toprak Algılayıcı / Toprak Zekası
- **Dashboard:** Kontrol Paneli
- **Farms:** Tarlalarım
- **Fields:** Tarlalar / Parseller
- **Add Farm:** Tarla Ekle
- **Add Field:** Parsel Ekle
- **Soil Readings:** Toprak Okumaları
- **Add Reading:** Okuma Ekle
- **Recommendations:** Öneriler
- **Resources:** Kaynaklar
- **Login:** Giriş Yap
- **Sign Up:** Kayıt Ol
- **Logout:** Çıkış Yap
- **Compaction Risk:** Sıkışma Riski
- **Nutrient Deficiency:** Besin Yetersizliği Riski
- **Moisture Stress:** Nem Stresi Riski
- **Low:** Düşük
- **Medium:** Orta
- **High:** Yüksek
- **Critical:** Kritik
- **Save:** Kaydet
- **Cancel:** İptal
- **Edit:** Düzenle
- **Delete:** Sil
- **Settings:** Ayarlar
- **Profile:** Profil
**10. EDGE CASES & VALIDATION:**
- **Authentication:** Handle invalid credentials, account lockout after multiple failed attempts (optional for MVP). Ensure session security.
- **Data Validation:** Implement robust server-side validation for all inputs (numeric ranges, required fields) using Zod with Drizzle ORM.
- **Empty States:** Design clear UI for when there are no farms, fields, or readings yet. Provide calls to action to create them.
- **Error Handling:** Gracefully handle API errors, database connection issues, and unexpected exceptions. Display user-friendly error messages.
- **Permissions:** Ensure users can only access and modify their own data.
- **Concurrency:** Handle potential race conditions if multiple users try to update the same record simultaneously (less critical for MVP, but consider optimistic updates or versioning for future). Ensure database transactions are used where necessary.
- **Sensor Data:** If using sensors, handle intermittent connections, missing data points, and data format discrepancies. Implement retry mechanisms and error logging.
- **Large Datasets:** For `SoilReadingsTable` and `SoilReadingsChart`, implement pagination and lazy loading to handle potentially large amounts of historical data efficiently.