Skip to content

ChanMeng666/biosecurity

Repository files navigation

Biosecurity Guide for Agricultural Pests & Weeds

A comprehensive digital platform for identifying, understanding, and managing agricultural pests and weeds.
Built for agronomists, staff, and administrators with role-based access control and a growing guide library.

Live Demo | Issues


Share Project Repository

Tech Stack:

Important

This project is a modern full-stack biosecurity information system built with Next.js 16, React 19, Better Auth, Drizzle ORM, and Neon PostgreSQL. It is deployed on Cloudflare Workers via the @opennextjs/cloudflare adapter for global edge performance. It provides role-based dashboards for administrators, staff, and agronomists to manage and browse pest and weed identification guides with detailed scientific data, images, and control methods.

Table of Contents

TOC


Introduction

About This Project

The Biosecurity Guide is a comprehensive digital platform designed to support agricultural professionals in identifying, understanding, and managing pests and weeds. The system provides a centralized guide library with detailed information on pest and weed characteristics, biology, impacts, and control methods — all backed by visual references.

The platform supports three distinct user roles — Administrator, Staff, and Agronomist — each with tailored dashboards and capabilities, ensuring the right level of access for every user.

Why This Project Exists

Agricultural biosecurity is critical for protecting crops, ecosystems, and food supply chains. Agronomists and field workers need quick, reliable access to pest and weed identification data to make timely decisions. This platform consolidates that information into a searchable, managed, and role-protected system — replacing scattered documents and outdated references with a modern, responsive web application.

Goals

  • Provide a centralized, searchable library of pest and weed identification guides
  • Enable role-based management of biosecurity information across organizations
  • Deliver a modern, responsive web experience for field and office use
  • Support data-driven decision making with structured scientific information

Note

  • Node.js >= 18.0 required
  • Neon PostgreSQL account required for database
  • Cloudflare account required for deployment

Key Features

1 Pest Identification

Detailed guides on agricultural pests including common and scientific names, key characteristics, biology, impacts, and control methods — all with visual image references to aid field identification.

Key capabilities:

  • Comprehensive pest profiles with scientific data
  • Multiple image support per guide entry
  • Structured control method recommendations
  • Impact assessment information

2 Weed Management

Comprehensive weed identification and control guides to protect agricultural productivity and biodiversity. Each entry includes lifecycle data, distinguishing characteristics, and recommended management strategies.

3 Role-Based Access Control

Three distinct user roles with tailored dashboards and permissions:

Role Capabilities
Administrator Full platform access — manage guides, staff, agronomists, and all system settings
Staff Create, edit, and delete guides; view agronomist profiles; manage own profile
Agronomist Browse and search the guide library; manage own profile

4 Guide Library & Smart Search

Browse and search through the guide library with powerful filtering capabilities:

  • Field-specific filtering (common name, scientific name, characteristics, biology, impacts, control)
  • Case-insensitive search matching
  • Pagination for large datasets
  • Filter by type (pest or weed)

* Additional Features

  • Secure authentication with server-side sessions (Better Auth)
  • Image carousel for visual guide references
  • Responsive design for desktop and mobile use
  • Light/dark theme support
  • Profile management for all user roles
  • Form validation with Zod schemas
  • Modern UI with shadcn/ui components

Architecture

System Overview

graph TB
    subgraph Client["Client (Browser)"]
        UI[React 19 UI<br/>shadcn/ui + Tailwind CSS 4]
        AuthClient[Better Auth Client]
    end

    subgraph CloudflareEdge["Cloudflare Workers (Edge)"]
        Worker[OpenNext Worker]
        Middleware[Next.js Middleware<br/>Session Cookie Check]
        SSR[Next.js SSR<br/>App Router]
        API[API Routes<br/>REST Endpoints]
        Assets[Static Assets<br/>Cloudflare CDN]
    end

    subgraph ExternalServices["External Services"]
        NeonDB[(Neon PostgreSQL<br/>Serverless HTTP)]
        R2[Cloudflare R2<br/>Incremental Cache]
        Pixabay[Pixabay CDN<br/>Guide Images]
    end

    UI -->|HTTPS| Worker
    AuthClient -->|Auth API| API
    Worker --> Middleware
    Middleware -->|Protected Routes| SSR
    Middleware -->|Public Routes| SSR
    Worker -->|Static Files| Assets
    SSR --> API
    API -->|Drizzle ORM| NeonDB
    API -->|Better Auth| NeonDB
    Worker -->|Cache| R2
    UI -->|Images| Pixabay
Loading

Request Flow

sequenceDiagram
    actor User
    participant CF as Cloudflare Worker
    participant MW as Middleware
    participant Page as Next.js Page
    participant API as API Route
    participant Auth as Better Auth
    participant DB as Neon PostgreSQL

    User->>CF: HTTPS Request
    CF->>MW: Route Request

    alt Static Asset
        CF-->>User: Serve from CDN Cache
    else Public Route (/, /login, /sources)
        MW->>Page: Allow Access
        Page-->>User: Render Page
    else Protected Route (/admin/*, /staff/*, etc.)
        MW->>MW: Check Session Cookie
        alt No Session Cookie
            MW-->>User: Redirect to /login
        else Has Session Cookie
            MW->>Page: Allow Access
            Page->>API: Fetch Data
            API->>Auth: Verify Session
            Auth->>DB: Query Session
            DB-->>Auth: Session Data
            API->>DB: Query Data
            DB-->>API: Results
            API-->>Page: JSON Response
            Page-->>User: Render Page
        end
    end
Loading

Database Schema

erDiagram
    user {
        text id PK
        text name
        text email UK
        text username UK
        text role "administrator | staff | agronomist"
        text status "active | inactive"
        boolean emailVerified
        text image
        timestamp createdAt
        timestamp updatedAt
    }

    session {
        text id PK
        text userId FK
        text token UK
        text ipAddress
        text userAgent
        timestamp expiresAt
        timestamp createdAt
        timestamp updatedAt
    }

    account {
        text id PK
        text userId FK
        text accountId
        text providerId
    }

    verification {
        text id PK
        text identifier
        text value
        timestamp expiresAt
        timestamp createdAt
        timestamp updatedAt
    }

    agronomists {
        serial id PK
        text userId FK
        text firstName
        text lastName
        text phoneNumber
        text address
    }

    staff_and_administrators {
        serial id PK
        text userId FK
        text firstName
        text lastName
        text position
        text department
    }

    agriculture_items {
        serial id PK
        enum itemType "pest | weed"
        text commonName
        text scientificName
        text keyCharacteristics
        text biology
        text impacts
        text control
        text source
    }

    images {
        serial id PK
        integer itemId FK
        text url
        text altText
        boolean isPrimary
    }

    user ||--o{ session : "has"
    user ||--o{ account : "has"
    user ||--o| agronomists : "profile"
    user ||--o| staff_and_administrators : "profile"
    agriculture_items ||--o{ images : "has"
Loading

Tech Stack

Next.js
Next.js 16
React
React 19
TypeScript
TypeScript 5
Tailwind CSS
Tailwind CSS 4
PostgreSQL
Neon PostgreSQL
Drizzle
Drizzle ORM
Cloudflare
Cloudflare

Frontend:

  • Framework: Next.js 16 with App Router
  • Language: TypeScript for type safety
  • Styling: Tailwind CSS 4 + tw-animate-css
  • UI Components: shadcn/ui (Base UI React)
  • Icons: Lucide React
  • Themes: next-themes for light/dark mode
  • Notifications: Sonner toast system

Backend:

  • Runtime: Next.js API Routes on Cloudflare Workers (edge)
  • Authentication: Better Auth with email/password and server-side sessions
  • Database ORM: Drizzle ORM with type-safe queries
  • Validation: Zod schema validation

Database:

  • Provider: Neon serverless PostgreSQL (HTTP driver, edge-compatible)
  • Migrations: Drizzle Kit
  • Schema: Custom tables for users, guides, images, profiles with role-based enums

Infrastructure:

  • Hosting: Cloudflare Workers via @opennextjs/cloudflare adapter
  • Static Assets: Cloudflare CDN (automatic edge caching)
  • Incremental Cache: Cloudflare R2 bucket
  • Build: Webpack bundler (required for Cloudflare compatibility)

Getting Started

Prerequisites

Important

Ensure you have the following installed:

Quick Installation

1. Clone Repository

git clone https://github.com/ChanMeng666/biosecurity.git
cd biosecurity

2. Install Dependencies

npm install

Environment Setup

3. Configure Environment Variables

# Copy environment template
cp .env.example .env.local

# Edit environment variables
nano .env.local

Create .env.local with the following variables:

# Neon Database (get from neonctl connection-string)
DATABASE_URL=postgresql://user:password@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require

# Better Auth (generate a random 32+ character secret)
BETTER_AUTH_SECRET=your-random-secret-here
BETTER_AUTH_URL=http://localhost:3000

# App URL
NEXT_PUBLIC_APP_URL=http://localhost:3000

Quick Reference:

Variable Required Purpose
DATABASE_URL Yes Neon PostgreSQL connection string
BETTER_AUTH_SECRET Yes Auth encryption key (32+ chars)
BETTER_AUTH_URL Yes Auth base URL
NEXT_PUBLIC_APP_URL Yes Public-facing app URL (inlined at build time)

Tip

Use openssl rand -base64 32 to generate a secure random secret for BETTER_AUTH_SECRET.

Database Setup

4. Run Database Migrations

# Generate migration files from schema
npm run db:generate

# Push schema to database
npm run db:push

Tip

Use npm run db:studio to open the Drizzle Studio GUI for browsing your database.

Development Mode

5. Start Development Server

npm run dev

Open http://localhost:3000 to view the application.

Available Scripts:

npm run dev          # Start dev server with hot reload
npm run build        # Production build (webpack)
npm run start        # Start production server (local Node.js)
npm run build:worker # Build for Cloudflare Workers
npm run preview      # Preview Cloudflare build locally
npm run cf:deploy    # Build and deploy to Cloudflare Workers
npm run lint         # Run ESLint
npm run db:generate  # Generate Drizzle migration files
npm run db:push      # Push schema changes to database
npm run db:migrate   # Run pending migrations
npm run db:studio    # Open Drizzle Studio database GUI

Deployment

This project is deployed on Cloudflare Workers using the @opennextjs/cloudflare adapter.

Live URL: https://biosecurity.chanmeng-dev.workers.dev

Deployment Architecture

graph LR
    subgraph Build["Build Pipeline"]
        Next["next build --webpack"]
        OpenNext["opennextjs-cloudflare build"]
        Next --> OpenNext
    end

    subgraph Output["Build Output (.open-next/)"]
        WorkerJS["worker.js<br/>Entry Point"]
        ServerFn["server-functions/<br/>SSR + API"]
        StaticAssets["assets/<br/>CSS, JS, Fonts"]
    end

    subgraph Cloudflare["Cloudflare Edge Network"]
        CDN["CDN<br/>Static Assets"]
        Workers["Workers Runtime<br/>nodejs_compat"]
        R2["R2 Bucket<br/>Incremental Cache"]
    end

    subgraph External["External"]
        Neon["Neon PostgreSQL<br/>HTTP Driver"]
    end

    OpenNext --> WorkerJS
    OpenNext --> ServerFn
    OpenNext --> StaticAssets

    StaticAssets -->|wrangler deploy| CDN
    WorkerJS -->|wrangler deploy| Workers
    ServerFn -->|bundled into| Workers
    Workers -->|Cache Read/Write| R2
    Workers -->|SQL over HTTP| Neon
Loading

Deploy Steps

# 1. Set Cloudflare secrets (first time only)
wrangler secret put DATABASE_URL
wrangler secret put BETTER_AUTH_SECRET

# 2. Build and deploy
NEXT_PUBLIC_APP_URL=https://biosecurity.chanmeng-dev.workers.dev npm run cf:deploy

Note

  • NEXT_PUBLIC_APP_URL must be set at build time (it is inlined into client JavaScript bundles).
  • The build uses --webpack instead of Turbopack for Cloudflare compatibility.
  • The nodejs_compat compatibility flag is enabled in wrangler.jsonc to support Node.js APIs used by Better Auth.

Key Configuration Files

File Purpose
wrangler.jsonc Cloudflare Worker configuration (bindings, compatibility flags, env vars)
open-next.config.ts OpenNext adapter configuration
next.config.ts Next.js config (standalone output, custom image loader)
src/lib/image-loader.ts Custom image loader for Cloudflare (pass-through for external URLs)

Project Structure

biosecurity/
├── src/
│   ├── app/                          # Next.js App Router
│   │   ├── (auth)/                   # Authentication routes
│   │   │   ├── login/                # Login page
│   │   │   └── register/             # Registration pages
│   │   │       ├── admin/            # Admin registration
│   │   │       ├── agronomist/       # Agronomist registration
│   │   │       └── staff/            # Staff registration
│   │   ├── (dashboard)/              # Protected dashboard routes
│   │   │   ├── admin/                # Admin dashboard
│   │   │   │   ├── manage-guides/    # Guide CRUD management
│   │   │   │   ├── manage-agronomists/ # Agronomist management
│   │   │   │   └── manage-staff/     # Staff management
│   │   │   ├── agronomist/           # Agronomist dashboard
│   │   │   │   └── guides/           # Guide browsing
│   │   │   └── staff/                # Staff dashboard
│   │   │       ├── manage-guides/    # Guide CRUD management
│   │   │       └── view-agronomists/ # View agronomist profiles
│   │   ├── api/                      # API routes
│   │   │   ├── auth/[...all]/        # Better Auth handler
│   │   │   ├── guides/               # Guide CRUD endpoints
│   │   │   ├── agronomists/          # Agronomist endpoints
│   │   │   ├── staff/                # Staff endpoints
│   │   │   └── profile/              # Profile endpoints
│   │   └── sources/                  # Sources & credits page
│   ├── components/
│   │   ├── ui/                       # shadcn/ui base components
│   │   ├── guides/                   # Guide-specific components
│   │   ├── layout/                   # Navbar, dashboard shell
│   │   ├── shared/                   # Confirm dialog, data table
│   │   └── users/                    # Profile editor
│   └── lib/
│       ├── auth/                     # Better Auth config & helpers
│       ├── db/                       # Drizzle ORM, schema, migrations
│       ├── image-loader.ts           # Custom Cloudflare image loader
│       └── validators/               # Zod validation schemas
├── wrangler.jsonc                    # Cloudflare Worker configuration
├── open-next.config.ts               # OpenNext adapter configuration
├── next.config.ts                    # Next.js configuration
├── drizzle.config.ts                 # Drizzle ORM configuration
├── package.json                      # Dependencies and scripts
└── tsconfig.json                     # TypeScript configuration

Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Guidelines:

  • Follow TypeScript best practices
  • Use the existing code style and ESLint configuration
  • Test your changes locally before submitting
  • Write clear commit messages

Contributors

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Chan Meng

LinkedIn GitHub Email Website


Protecting Agriculture Through Knowledge
A comprehensive biosecurity guide for agricultural pest and weed management

GitHub stars GitHub forks GitHub watchers

About

【Hit that ⭐️ if you like what you see!】A Flask-based web application serving as a comprehensive biosecurity guide for agricultural pests and weeds in New Zealand. Features role-based access control, detailed pest/weed information management, and responsive design for agronomists, staff, and administrators.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors