├── frontend ├── app │ ├── (dashboard) │ │ ├── schemes │ │ │ └── loading.tsx │ │ ├── community │ │ │ ├── agent │ │ │ │ └── page.tsx │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── market │ │ │ └── page.tsx │ │ └── results │ │ │ └── [id] │ │ │ └── page.tsx │ ├── page.tsx │ ├── (auth) │ │ └── layout.tsx │ ├── api │ │ ├── news │ │ │ └── route.ts │ │ ├── schemes │ │ │ ├── query │ │ │ │ └── route.ts │ │ │ └── list │ │ │ │ └── route.ts │ │ ├── weather │ │ │ └── route.ts │ │ ├── upload │ │ │ └── route.ts │ │ ├── health │ │ │ └── route.ts │ │ ├── profile │ │ │ ├── stats │ │ │ │ └── route.ts │ │ │ └── route.ts │ │ ├── analyze-image │ │ │ └── route.ts │ │ └── diagnose │ │ │ └── route.ts │ ├── layout.tsx │ └── welcome │ │ └── page.tsx ├── public │ ├── apple-icon.png │ ├── placeholder.jpg │ ├── icon-dark-32x32.png │ ├── icon-light-32x32.png │ ├── placeholder-logo.png │ ├── placeholder-user.jpg │ ├── icon.svg │ ├── placeholder-logo.svg │ └── placeholder.svg ├── pnpm-lock.yaml ├── postcss.config.mjs ├── lib │ ├── utils.ts │ ├── supabase │ │ ├── client.ts │ │ ├── admin.ts │ │ ├── server.ts │ │ └── proxy.ts │ ├── actions │ │ ├── weather.ts │ │ ├── profile.ts │ │ ├── market.ts │ │ ├── diagnoses.ts │ │ └── auth.ts │ └── ai │ │ ├── openrouter.ts │ │ └── gemini.ts ├── next.config.mjs ├── components │ ├── ui │ │ ├── aspect-ratio.tsx │ │ ├── skeleton.tsx │ │ ├── spinner.tsx │ │ ├── use-mobile.tsx │ │ ├── sonner.tsx │ │ ├── label.tsx │ │ ├── separator.tsx │ │ ├── textarea.tsx │ │ ├── progress.tsx │ │ ├── toaster.tsx │ │ ├── collapsible.tsx │ │ ├── kbd.tsx │ │ ├── input.tsx │ │ ├── switch.tsx │ │ ├── avatar.tsx │ │ ├── checkbox.tsx │ │ ├── radio-group.tsx │ │ ├── hover-card.tsx │ │ ├── toggle.tsx │ │ ├── badge.tsx │ │ ├── popover.tsx │ │ ├── scroll-area.tsx │ │ ├── alert.tsx │ │ ├── tooltip.tsx │ │ ├── tabs.tsx │ │ ├── toggle-group.tsx │ │ ├── slider.tsx │ │ ├── resizable.tsx │ │ ├── accordion.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── button-group.tsx │ │ ├── input-otp.tsx │ │ ├── breadcrumb.tsx │ │ ├── empty.tsx │ │ ├── table.tsx │ │ ├── pagination.tsx │ │ ├── form.tsx │ │ ├── alert-dialog.tsx │ │ ├── dialog.tsx │ │ ├── sheet.tsx │ │ ├── drawer.tsx │ │ └── use-toast.ts │ ├── theme-provider.tsx │ ├── dashboard │ │ ├── mobile-header.tsx │ │ ├── mobile-nav.tsx │ │ └── sidebar.tsx │ └── community │ │ └── expert-chat-button.tsx ├── proxy.ts ├── components.json ├── hooks │ ├── use-mobile.ts │ └── use-toast.ts ├── tsconfig.json ├── scripts │ ├── 001-create-analysis-table.sql │ ├── health-check.js │ ├── 002_create_plant_diagnosis.sql │ ├── 009_create_post_likes.sql │ ├── 005_create_farm_records.sql │ ├── 004_create_market_rates.sql │ ├── 006_create_weather_alerts.sql │ ├── 007_create_post_comments.sql │ ├── 001_create_users_and_profiles.sql │ ├── 008_create_expert_chats.sql │ ├── setup-env.sh │ ├── 003_create_community_posts.sql │ ├── validate-env.ts │ └── 010_seed_dev_user.sql ├── .env.example └── package.json ├── assets └── dashboard-screenshot.png ├── backend ├── package.json ├── .env.example └── index.js ├── .gitignore └── ENV_SETUP.md /frontend/app/(dashboard)/schemes/loading.tsx: -------------------------------------------------------------------------------- 1 | export default function Loading() { 2 | return null 3 | } 4 | -------------------------------------------------------------------------------- /assets/dashboard-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxprogrammer007/KISAAN_APP/master/assets/dashboard-screenshot.png -------------------------------------------------------------------------------- /frontend/public/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxprogrammer007/KISAAN_APP/master/frontend/public/apple-icon.png -------------------------------------------------------------------------------- /frontend/public/placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxprogrammer007/KISAAN_APP/master/frontend/public/placeholder.jpg -------------------------------------------------------------------------------- /frontend/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false -------------------------------------------------------------------------------- /frontend/public/icon-dark-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxprogrammer007/KISAAN_APP/master/frontend/public/icon-dark-32x32.png -------------------------------------------------------------------------------- /frontend/public/icon-light-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxprogrammer007/KISAAN_APP/master/frontend/public/icon-light-32x32.png -------------------------------------------------------------------------------- /frontend/public/placeholder-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxprogrammer007/KISAAN_APP/master/frontend/public/placeholder-logo.png -------------------------------------------------------------------------------- /frontend/public/placeholder-user.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxprogrammer007/KISAAN_APP/master/frontend/public/placeholder-user.jpg -------------------------------------------------------------------------------- /frontend/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation" 2 | 3 | export default function HomePage() { 4 | redirect("/dashboard") 5 | } 6 | -------------------------------------------------------------------------------- /frontend/app/(auth)/layout.tsx: -------------------------------------------------------------------------------- 1 | import type React from "react" 2 | export default function AuthLayout({ children }: { children: React.ReactNode }) { 3 | return children 4 | } 5 | -------------------------------------------------------------------------------- /frontend/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | '@tailwindcss/postcss': {}, 5 | }, 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /frontend/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /frontend/lib/supabase/client.ts: -------------------------------------------------------------------------------- 1 | import { createBrowserClient } from "@supabase/ssr" 2 | 3 | export function createClient() { 4 | return createBrowserClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!) 5 | } 6 | -------------------------------------------------------------------------------- /frontend/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | typescript: { 4 | ignoreBuildErrors: true, 5 | }, 6 | images: { 7 | unoptimized: true, 8 | }, 9 | } 10 | 11 | export default nextConfig 12 | -------------------------------------------------------------------------------- /frontend/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio' 4 | 5 | function AspectRatio({ 6 | ...props 7 | }: React.ComponentProps) { 8 | return 9 | } 10 | 11 | export { AspectRatio } 12 | -------------------------------------------------------------------------------- /frontend/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils' 2 | 3 | function Skeleton({ className, ...props }: React.ComponentProps<'div'>) { 4 | return ( 5 |
10 | ) 11 | } 12 | 13 | export { Skeleton } 14 | -------------------------------------------------------------------------------- /frontend/proxy.ts: -------------------------------------------------------------------------------- 1 | import type { NextRequest } from "next/server" 2 | 3 | export async function proxy(request: NextRequest) { 4 | // Authentication bypassed for development - all routes are accessible 5 | return 6 | } 7 | 8 | export const config = { 9 | matcher: ["/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)"], 10 | } 11 | -------------------------------------------------------------------------------- /frontend/app/(dashboard)/community/agent/page.tsx: -------------------------------------------------------------------------------- 1 | import { KisaanMitraChatFloater } from "@/components/kisaan-mitra/chat-floater"; 2 | 3 | export default function AgentPage() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /frontend/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import { 5 | ThemeProvider as NextThemesProvider, 6 | type ThemeProviderProps, 7 | } from 'next-themes' 8 | 9 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 10 | return {children} 11 | } 12 | -------------------------------------------------------------------------------- /frontend/components/ui/spinner.tsx: -------------------------------------------------------------------------------- 1 | import { Loader2Icon } from 'lucide-react' 2 | 3 | import { cn } from '@/lib/utils' 4 | 5 | function Spinner({ className, ...props }: React.ComponentProps<'svg'>) { 6 | return ( 7 | 13 | ) 14 | } 15 | 16 | export { Spinner } 17 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "@google/generative-ai": "^0.24.1", 14 | "aws-sdk": "^2.1693.0", 15 | "cors": "^2.8.5", 16 | "dotenv": "^17.2.3", 17 | "express": "^5.2.1", 18 | "socket.io": "^4.8.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .pnp 4 | .pnp.js 5 | 6 | # Build outputs 7 | .next/ 8 | out/ 9 | build/ 10 | dist/ 11 | 12 | # Environment variables 13 | .env 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | # Debug logs 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | 24 | # IDE 25 | .idea/ 26 | .vscode/ 27 | *.swp 28 | *.swo 29 | 30 | # OS files 31 | .DS_Store 32 | Thumbs.db 33 | 34 | # Testing 35 | coverage/ 36 | 37 | # TypeScript 38 | *.tsbuildinfo 39 | next-env.d.ts 40 | 41 | # Misc 42 | *.pem 43 | -------------------------------------------------------------------------------- /frontend/hooks/use-mobile.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener('change', onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener('change', onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /frontend/components/ui/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener('change', onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener('change', onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /frontend/lib/actions/weather.ts: -------------------------------------------------------------------------------- 1 | "use server" 2 | 3 | import { createClient } from "@/lib/supabase/server" 4 | 5 | export async function getWeatherAlerts(location?: string) { 6 | const supabase = await createClient() 7 | 8 | let query = supabase 9 | .from("weather_alerts") 10 | .select("*") 11 | .eq("is_active", true) 12 | .order("severity", { ascending: false }) 13 | .order("start_date", { ascending: false }) 14 | 15 | if (location) { 16 | query = query.ilike("location", `%${location}%`) 17 | } 18 | 19 | const { data, error } = await query 20 | 21 | if (error) { 22 | return { error: error.message } 23 | } 24 | 25 | return { data } 26 | } 27 | -------------------------------------------------------------------------------- /frontend/components/ui/sonner.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useTheme } from 'next-themes' 4 | import { Toaster as Sonner, ToasterProps } from 'sonner' 5 | 6 | const Toaster = ({ ...props }: ToasterProps) => { 7 | const { theme = 'system' } = useTheme() 8 | 9 | return ( 10 | 22 | ) 23 | } 24 | 25 | export { Toaster } 26 | -------------------------------------------------------------------------------- /backend/.env.example: -------------------------------------------------------------------------------- 1 | # Kisaan Mitra LLM Keys (2025 Standards) 2 | # Amazon Bedrock (for scalable, low-latency AI; e.g., Claude for Hindi responses) 3 | BEDROCK_ACCESS_KEY=your-aws-access-key-id # From AWS IAM 4 | BEDROCK_SECRET_KEY=your-aws-secret-access-key 5 | BEDROCK_REGION=us-east-1 # Or eu-west-1 for India latency 6 | BEDROCK_MODEL_ID=anthropic.claude-3-sonnet-20240229-v1:0 # Top for agri advice 7 | 8 | # Google Gemini (for vision/multimodal; e.g., plant diagnosis) 9 | GEMINI_API_KEY=your-gemini-api-key # From aistudio.google.com 10 | GEMINI_MODEL=gemini-pro # Stable model for text generation 11 | 12 | # General 13 | NODE_ENV=development 14 | PORT=5000 15 | JWT_SECRET=your-jwt-secret-for-auth 16 | -------------------------------------------------------------------------------- /frontend/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as LabelPrimitive from '@radix-ui/react-label' 5 | 6 | import { cn } from '@/lib/utils' 7 | 8 | function Label({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 21 | ) 22 | } 23 | 24 | export { Label } 25 | -------------------------------------------------------------------------------- /frontend/components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as SeparatorPrimitive from '@radix-ui/react-separator' 5 | 6 | import { cn } from '@/lib/utils' 7 | 8 | function Separator({ 9 | className, 10 | orientation = 'horizontal', 11 | decorative = true, 12 | ...props 13 | }: React.ComponentProps) { 14 | return ( 15 | 25 | ) 26 | } 27 | 28 | export { Separator } 29 | -------------------------------------------------------------------------------- /frontend/lib/supabase/admin.ts: -------------------------------------------------------------------------------- 1 | import { createClient as createSupabaseClient } from "@supabase/supabase-js" 2 | 3 | /** 4 | * Admin Supabase client that bypasses RLS 5 | * Use this ONLY for server-side operations in development 6 | * when authentication is bypassed 7 | */ 8 | export function createAdminClient() { 9 | const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL! 10 | const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY! 11 | 12 | if (!serviceRoleKey) { 13 | console.warn("[v0] SUPABASE_SERVICE_ROLE_KEY not set, falling back to anon key") 14 | return createSupabaseClient(supabaseUrl, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!) 15 | } 16 | 17 | return createSupabaseClient(supabaseUrl, serviceRoleKey, { 18 | auth: { 19 | autoRefreshToken: false, 20 | persistSession: false, 21 | }, 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /frontend/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { cn } from '@/lib/utils' 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) { 6 | return ( 7 |