Repository: sujalmu2004/zerocarbon Files analyzed: 37 Estimated tokens: 12.2k Directory structure: └── sujalmu2004-zerocarbon/ ├── README.md ├── eslint.config.mjs ├── middleware.ts ├── next.config.ts ├── package.json ├── postcss.config.mjs ├── tsconfig.json ├── public/ ├── src/ │ ├── app/ │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.tsx │ │ ├── cookie-policy/ │ │ │ └── page.tsx │ │ ├── dashboard/ │ │ │ ├── actions.ts │ │ │ └── page.tsx │ │ ├── how-it-works/ │ │ │ └── page.tsx │ │ ├── how-to-offset-emissions/ │ │ │ └── page.tsx │ │ ├── list-project/ │ │ │ └── page.tsx │ │ ├── login/ │ │ │ └── page.tsx │ │ ├── privacy-policy/ │ │ │ └── page.tsx │ │ ├── projects/ │ │ │ └── page.tsx │ │ ├── register-company/ │ │ │ └── page.tsx │ │ ├── resources/ │ │ │ ├── carbon-market-integrity/ │ │ │ │ └── page.tsx │ │ │ ├── faq/ │ │ │ │ └── page.tsx │ │ │ ├── how-carbon-credits-work/ │ │ │ │ └── page.tsx │ │ │ └── sustainability-reports/ │ │ │ └── page.tsx │ │ └── terms-of-service/ │ │ └── page.tsx │ ├── components/ │ │ ├── auth/ │ │ │ └── login-form.tsx │ │ └── ui/ │ │ ├── demo.tsx │ │ ├── global-tiles-background.tsx │ │ ├── tiles.tsx │ │ ├── zerocarbon-footer.tsx │ │ └── zerocarbon-navbar.tsx │ └── lib/ │ ├── utils.ts │ └── supabase/ │ ├── client.ts │ ├── env.ts │ ├── middleware.ts │ └── server.ts └── supabase/ └── seed_profiles.sql ================================================ FILE: README.md ================================================ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). ## Getting Started First, run the development server: ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. ## Learn More To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! ## Deploy on Vercel The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. ================================================ FILE: eslint.config.mjs ================================================ import { defineConfig, globalIgnores } from "eslint/config"; import nextVitals from "eslint-config-next/core-web-vitals"; import nextTs from "eslint-config-next/typescript"; const eslintConfig = defineConfig([ ...nextVitals, ...nextTs, // Override default ignores of eslint-config-next. globalIgnores([ // Default ignores of eslint-config-next: ".next/**", "out/**", "build/**", "next-env.d.ts", ]), ]); export default eslintConfig; ================================================ FILE: middleware.ts ================================================ import type { NextRequest } from "next/server"; import { updateSession } from "@/lib/supabase/middleware"; export async function middleware(request: NextRequest) { return updateSession(request); } export const config = { matcher: [ // Exclude static assets and common image/font file extensions. "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|woff|woff2|ttf|eot)$).*)", ], }; ================================================ FILE: next.config.ts ================================================ import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ }; export default nextConfig; ================================================ FILE: package.json ================================================ { "name": "zerocarbon", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "eslint" }, "dependencies": { "@supabase/ssr": "^0.8.0", "@supabase/supabase-js": "^2.97.0", "clsx": "^2.1.1", "framer-motion": "^12.34.3", "next": "16.1.6", "react": "19.2.3", "react-dom": "19.2.3", "tailwind-merge": "^3.5.0" }, "devDependencies": { "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "16.1.6", "tailwindcss": "^4", "typescript": "^5" } } ================================================ FILE: postcss.config.mjs ================================================ const config = { plugins: { "@tailwindcss/postcss": {}, }, }; export default config; ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "target": "ES2017", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "react-jsx", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./src/*"] } }, "include": [ "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts", "**/*.mts" ], "exclude": ["node_modules"] } ================================================ FILE: src/app/globals.css ================================================ @import "tailwindcss"; :root { --tile: rgb(16 185 129 / 0.18); } html { scroll-behavior: smooth; } html, body { min-height: 100%; max-width: 100%; } body { overflow-x: hidden; } *, *::before, *::after { box-sizing: border-box; } img, svg, video, canvas { max-width: 100%; height: auto; } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; transition-duration: 0.01ms !important; } } ================================================ FILE: src/app/layout.tsx ================================================ import type { Metadata } from "next"; import "./globals.css"; import { ZeroCarbonFooter } from "@/components/ui/zerocarbon-footer"; import { ZeroCarbonNavbar } from "@/components/ui/zerocarbon-navbar"; import { GlobalTilesBackground } from "@/components/ui/global-tiles-background"; export const metadata: Metadata = { title: "ZeroCarbon", description: "ZeroCarbon | Offset emissions, discover verified climate projects, and scale climate action", keywords: "carbon credits, climate tech, carbon offset, carbon marketplace, sustainability, emissions", }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return (
{children}
); } ================================================ FILE: src/app/page.tsx ================================================ import Link from "next/link"; export default function Page() { return (

ZeroCarbon

Premium climate-tech marketplace for verified carbon impact.

Offset emissions, fund transparent projects, and move your organization toward measurable net-zero outcomes.

How To Offset Emissions

Learn how to measure your footprint, choose trusted projects, and retire credits with transparent records.

Learn more

How It Works

See how ZeroCarbon verifies projects, simplifies purchasing, and tracks measurable climate impact.

Learn more

Projects

Explore climate initiatives across categories, with clear standards and comparability.

Learn more
); } ================================================ FILE: src/app/cookie-policy/page.tsx ================================================ export default function CookiePolicyPage() { return (

Cookie Policy

Last updated: February 21, 2026.

This placeholder policy explains how ZeroCarbon uses cookies and similar technologies to improve product performance, analytics, and user experience.

); } ================================================ FILE: src/app/dashboard/actions.ts ================================================ "use server"; import { redirect } from "next/navigation"; import { createServerSupabaseClient } from "@/lib/supabase/server"; export async function logout() { const supabase = await createServerSupabaseClient(); await supabase.auth.signOut(); redirect("/"); } ================================================ FILE: src/app/dashboard/page.tsx ================================================ import { redirect } from "next/navigation"; import { createServerSupabaseClient } from "@/lib/supabase/server"; import { logout } from "@/app/dashboard/actions"; function formatCreatedAt(value: string | null): string { if (!value) { return "Unavailable"; } const date = new Date(value); if (Number.isNaN(date.getTime())) { return "Unavailable"; } return new Intl.DateTimeFormat("en-US", { year: "numeric", month: "short", day: "2-digit", }).format(date); } export default async function DashboardPage() { const supabase = await createServerSupabaseClient(); const { data: { user }, } = await supabase.auth.getUser(); if (!user) { redirect("/login"); } const { data: profile, error: profileError } = await supabase .from("profiles") .select("role, created_at") .eq("id", user.id) .maybeSingle(); const role = profileError ? "Not set" : profile?.role ?? "Not set"; const createdAt = profileError ? "Unavailable" : formatCreatedAt(profile?.created_at ?? null); return (

Dashboard

Your account overview and profile details.

Email

{user.email ?? "Unavailable"}

Role

{role}

Created At

{createdAt}

); } ================================================ FILE: src/app/how-it-works/page.tsx ================================================ export default function HowItWorksPage() { return (

How It Works

ZeroCarbon curates high-integrity projects, validates issuance quality, and provides a clean buying flow for individuals and companies.

Every purchase is tracked in your dashboard with project-level transparency so you can measure climate impact over time.

); } ================================================ FILE: src/app/how-to-offset-emissions/page.tsx ================================================ export default function HowToOffsetEmissionsPage() { return (

How To Offset Emissions

Start by estimating your emissions footprint, then select verified climate projects that align with your impact goals and region.

Purchase certified credits and retire them transparently so every offset is traceable and tied to real climate outcomes.

); } ================================================ FILE: src/app/list-project/page.tsx ================================================ export default function ListProjectPage() { return (

List Your Project

Submit your climate project details to start onboarding with ZeroCarbon.

); } ================================================ FILE: src/app/login/page.tsx ================================================ import { LoginForm } from "@/components/auth/login-form"; export default function LoginPage() { return (

Login

Sign in to access your ZeroCarbon dashboard and climate impact activity.

); } ================================================ FILE: src/app/privacy-policy/page.tsx ================================================ export default function PrivacyPolicyPage() { return (

Privacy Policy

Last updated: February 21, 2026.

This placeholder policy outlines how ZeroCarbon collects, uses, and protects user and company data on the marketplace platform.

); } ================================================ FILE: src/app/projects/page.tsx ================================================ export default function ProjectsPage() { return (

Projects

Explore reforestation, blue-carbon, and carbon-removal initiatives with verified data and clear methodology details.

Filter by region, project type, and certification standard to find options that match your climate strategy.

); } ================================================ FILE: src/app/register-company/page.tsx ================================================ export default function RegisterCompanyPage() { return (

Register Company

Create your company profile to manage emission goals and procurement workflows.

); } ================================================ FILE: src/app/resources/carbon-market-integrity/page.tsx ================================================ export default function CarbonMarketIntegrityPage() { return (

Carbon Market Integrity

ZeroCarbon prioritizes quality controls including additionality screening, methodology checks, and registry verification before projects are listed.

We align with transparent retirement workflows to reduce over-claiming risk and maintain enterprise-grade confidence in climate disclosures.

); } ================================================ FILE: src/app/resources/faq/page.tsx ================================================ export default function FaqPage() { return (

FAQ

Find answers to common questions on project verification, purchasing workflow, retirement tracking, and company onboarding.

This section is a starter placeholder and can be expanded into a searchable knowledge base.

); } ================================================ FILE: src/app/resources/how-carbon-credits-work/page.tsx ================================================ export default function HowCarbonCreditsWorkPage() { return (

How Carbon Credits Work

Carbon credits represent verified reductions or removals of greenhouse gases, issued under recognized methodologies and standards.

Credits are purchased, transferred, and retired in registries to prevent double counting and ensure each claim is backed by transparent records.

); } ================================================ FILE: src/app/resources/sustainability-reports/page.tsx ================================================ export default function SustainabilityReportsPage() { return (

Sustainability Reports

Access ZeroCarbon reporting templates and climate impact summaries for internal governance and external stakeholder communication.

Reports include retirement references and project-level context to support audit-ready sustainability disclosures.

); } ================================================ FILE: src/app/terms-of-service/page.tsx ================================================ export default function TermsOfServicePage() { return (

Terms of Service

Last updated: February 21, 2026.

This placeholder terms document defines platform usage conditions, account obligations, and marketplace participation requirements for ZeroCarbon users.

); } ================================================ FILE: src/components/auth/login-form.tsx ================================================ "use client"; import { useState, type FormEvent } from "react"; import { useRouter } from "next/navigation"; import type { AuthError } from "@supabase/supabase-js"; import { createBrowserSupabaseClient } from "@/lib/supabase/client"; function getFriendlyErrorMessage(error: AuthError): string { const message = error.message ?? ""; const status = error.status; if (status === 401 || /invalid login credentials/i.test(message)) { return "Invalid email or password."; } if (/email not confirmed/i.test(message)) { return "Please confirm your email before logging in."; } if (/invalid api key|jwt|api key/i.test(message)) { return "Authentication service configuration error. Please contact support."; } if (/failed to fetch|network/i.test(message)) { return "Network error while connecting to authentication service. Please try again."; } return "Unable to sign in right now. Please try again."; } export function LoginForm() { const router = useRouter(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); async function handleSubmit(event: FormEvent) { event.preventDefault(); setError(null); setIsLoading(true); try { const supabase = createBrowserSupabaseClient(); const { error: signInError } = await supabase.auth.signInWithPassword({ email: email.trim(), password, }); if (signInError) { setError(getFriendlyErrorMessage(signInError)); setIsLoading(false); return; } router.replace("/dashboard"); router.refresh(); } catch (caughtError) { if (caughtError instanceof Error && /missing required environment variable/i.test(caughtError.message)) { setError("Authentication service configuration error. Please contact support."); } else { setError("Network error while connecting to authentication service. Please try again."); } setIsLoading(false); } } return (
setEmail(event.target.value)} className="w-full rounded-xl border border-slate-300 bg-white px-4 py-2.5 text-slate-900 outline-none transition-colors duration-200 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-200 disabled:cursor-not-allowed disabled:opacity-70" placeholder="you@company.com" />
setPassword(event.target.value)} className="w-full rounded-xl border border-slate-300 bg-white px-4 py-2.5 text-slate-900 outline-none transition-colors duration-200 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-200 disabled:cursor-not-allowed disabled:opacity-70" placeholder="Enter your password" />
{error ? (

{error}

) : null}
); } ================================================ FILE: src/components/ui/demo.tsx ================================================ "use client"; import { Tiles } from "@/components/ui/tiles"; export function TilesDemo() { return (
); } ================================================ FILE: src/components/ui/global-tiles-background.tsx ================================================ export function GlobalTilesBackground() { return (
{/* Layer 1: repeating subtle grid that scales with full page height */}
{/* Layer 2: soft depth tint for premium SaaS look */}
{/* Bottom fade into page background to avoid harsh cutoff */}
); } ================================================ FILE: src/components/ui/tiles.tsx ================================================ "use client"; import React from "react"; import { motion } from "framer-motion"; import { cn } from "@/lib/utils"; interface TilesProps { className?: string; rows?: number; cols?: number; tileClassName?: string; tileSize?: "sm" | "md" | "lg"; } const tileSizes = { sm: "w-8 h-8", md: "w-9 h-9 md:w-12 md:h-12", lg: "w-12 h-12 md:w-16 md:h-16", }; export function Tiles({ className, rows = 100, cols = 10, tileClassName, tileSize = "md", }: TilesProps) { const rowsArray = new Array(rows).fill(1); const colsArray = new Array(cols).fill(1); return (
{rowsArray.map((_, i) => ( {colsArray.map((_, j) => ( ))} ))}
); } ================================================ FILE: src/components/ui/zerocarbon-footer.tsx ================================================ import Link from "next/link"; const companyLinks = [ { label: "Offset Emissions", href: "/how-to-offset-emissions" }, { label: "How To Offset Emissions", href: "/how-to-offset-emissions" }, { label: "Projects", href: "/projects" }, ]; const resourceLinks = [ { label: "How Carbon Credits Work", href: "/resources/how-carbon-credits-work" }, { label: "Carbon Market Integrity", href: "/resources/carbon-market-integrity" }, { label: "FAQ", href: "/resources/faq" }, { label: "Sustainability Reports", href: "/resources/sustainability-reports" }, ]; const legalLinks = [ { label: "Privacy Policy", href: "/privacy-policy" }, { label: "Terms of Service", href: "/terms-of-service" }, { label: "Cookie Policy", href: "/cookie-policy" }, ]; export function ZeroCarbonFooter() { return (

ZeroCarbon

ZeroCarbon is a transparent carbon credit marketplace enabling industries to offset emissions and empowering farmers to monetize climate projects.

For Companies

    {companyLinks.map((item) => (
  • {item.label}
  • ))}

Resources

    {resourceLinks.map((item) => (
  • {item.label}
  • ))}

Marketplace Pulse

CO2 Offset Counter

12,480 tCO2e

Placeholder metric updated in real time.

© 2026 ZeroCarbon. All rights reserved.

); } ================================================ FILE: src/components/ui/zerocarbon-navbar.tsx ================================================ "use client"; import Image from "next/image"; import Link from "next/link"; import { useEffect, useState } from "react"; import type { JSX } from "react"; type NavLink = { label: string; href: string }; type ActionLink = { label: string; href: string; variant: "primary" | "secondary" | "ghost"; }; const navLinks: NavLink[] = [ { label: "How To Offset Emissions", href: "/how-to-offset-emissions" }, { label: "How It Works", href: "/how-it-works" }, { label: "Projects", href: "/projects" }, ]; const actionLinks: ActionLink[] = [ { label: "List Your Project", href: "/list-project", variant: "primary" }, { label: "Register Company", href: "/register-company", variant: "secondary" }, { label: "Login", href: "/login", variant: "ghost" }, ]; function actionClass(variant: ActionLink["variant"]): string { if (variant === "primary") { return "border border-emerald-400/45 bg-gradient-to-r from-emerald-500 to-green-500 text-white shadow-[0_8px_24px_rgba(16,185,129,0.3)] hover:-translate-y-0.5 hover:from-emerald-400 hover:to-green-400"; } if (variant === "secondary") { return "border border-sky-400/45 bg-gradient-to-r from-sky-500 to-blue-500 text-white shadow-[0_8px_24px_rgba(59,130,246,0.3)] hover:-translate-y-0.5 hover:from-sky-400 hover:to-blue-400"; } return "border border-white/35 bg-white/10 text-slate-800 hover:bg-white/20"; } export function ZeroCarbonNavbar(): JSX.Element { const [isMenuOpen, setIsMenuOpen] = useState(false); useEffect(() => { if (!isMenuOpen) return; const onKeyDown = (event: KeyboardEvent) => { if (event.key === "Escape") setIsMenuOpen(false); }; window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }, [isMenuOpen]); return (
); } ================================================ FILE: src/lib/utils.ts ================================================ import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } ================================================ FILE: src/lib/supabase/client.ts ================================================ import { createBrowserClient } from "@supabase/ssr"; import { getSupabaseAnonKey, getSupabaseUrl } from "@/lib/supabase/env"; // Browser-only client for auth actions initiated from client components. export function createBrowserSupabaseClient() { return createBrowserClient(getSupabaseUrl(), getSupabaseAnonKey()); } ================================================ FILE: src/lib/supabase/env.ts ================================================ export function getSupabaseUrl(): string { const url = process.env.NEXT_PUBLIC_SUPABASE_URL; if (!url) { throw new Error("Missing required environment variable: NEXT_PUBLIC_SUPABASE_URL"); } return url; } export function getSupabaseAnonKey(): string { const anonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; if (!anonKey) { throw new Error("Missing required environment variable: NEXT_PUBLIC_SUPABASE_ANON_KEY"); } return anonKey; } ================================================ FILE: src/lib/supabase/middleware.ts ================================================ import { createServerClient } from "@supabase/ssr"; import { NextResponse, type NextRequest } from "next/server"; import { getSupabaseAnonKey, getSupabaseUrl } from "@/lib/supabase/env"; export async function updateSession(request: NextRequest) { let response = NextResponse.next({ request, }); const supabase = createServerClient(getSupabaseUrl(), getSupabaseAnonKey(), { cookies: { getAll() { return request.cookies.getAll(); }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value }) => { request.cookies.set(name, value); }); response = NextResponse.next({ request, }); cookiesToSet.forEach(({ name, value, options }) => { response.cookies.set(name, value, options); }); }, }, }); // Refresh auth state and keep cookies synchronized for server-side protection. await supabase.auth.getUser(); return response; } ================================================ FILE: src/lib/supabase/server.ts ================================================ import { createServerClient } from "@supabase/ssr"; import { cookies } from "next/headers"; import { getSupabaseAnonKey, getSupabaseUrl } from "@/lib/supabase/env"; export async function createServerSupabaseClient() { const cookieStore = await cookies(); return createServerClient(getSupabaseUrl(), getSupabaseAnonKey(), { cookies: { getAll() { return cookieStore.getAll(); }, setAll(cookiesToSet) { // setAll can be called in read-only contexts (e.g. Server Components). try { cookiesToSet.forEach(({ name, value, options }) => { cookieStore.set(name, value, options); }); } catch { // Middleware handles cookie refresh when direct writes are not available. } }, }, }); } ================================================ FILE: supabase/seed_profiles.sql ================================================ -- One-time seed for profile rows from existing auth users. -- Run this in Supabase SQL Editor. -- Create profiles table if it doesn't exist yet. create table if not exists public.profiles ( id uuid primary key references auth.users (id) on delete cascade ); -- Ensure expected columns exist for dashboard rendering. alter table public.profiles add column if not exists role text; alter table public.profiles add column if not exists created_at timestamptz not null default now(); -- RLS can be enabled safely even if already enabled. alter table public.profiles enable row level security; insert into public.profiles (id, role) select u.id, 'company' from auth.users u left join public.profiles p on p.id = u.id where p.id is null;