Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion frontend/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
experimental: {
optimizeCss: true,
optimizePackageImports: ['lucide-react'],
},
images: {
domains: ['localhost'],
formats: ['image/webp', 'image/avif'],
},
compiler: {
removeConsole: process.env.NODE_ENV === 'production',
},
poweredByHeader: false,
reactStrictMode: true,
swcMinify: true,
}

export default nextConfig;
19 changes: 17 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,31 @@
"test": "jest --passWithNoTests"
},
"dependencies": {
"@hookform/resolvers": "^5.2.2",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-toast": "^1.2.15",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^1.7.0",
"next": "15.2.3",
"react": "^19.0.0",
"react-dom": "^19.0.0"
"react-dom": "^19.0.0",
"react-hook-form": "^7.72.0",
"tailwind-merge": "^3.5.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/node": "^22",
"@types/node": "^22.19.15",
"@types/react": "^19",
"autoprefixer": "^10.4.27",
"eslint": "^9",
"eslint-config-next": "15.2.3",
"jest": "^29",
"postcss": "^8.5.8",
"tailwindcss": "^4.2.2",
"typescript": "^5"
}
}
6 changes: 6 additions & 0 deletions frontend/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
79 changes: 79 additions & 0 deletions frontend/src/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96%;
--secondary-foreground: 222.2 84% 4.9%;
--muted: 210 40% 96%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96%;
--accent-foreground: 222.2 84% 4.9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.5rem;
--font-inter: 'Inter', system-ui, sans-serif;
--font-ibm-mono: 'IBM Plex Mono', monospace;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 217.2 91.2% 59.8%;
--primary-foreground: 222.2 84% 4.9%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 224.3 76.3% 94.1%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

@layer utilities {
.focus-ring {
@apply focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background;
}

.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
}
75 changes: 73 additions & 2 deletions frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,76 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "niffyInsur" };
import "./globals.css";
import { Toaster } from "@/components/ui/toaster";
import { inter, ibmPlexMono } from "@/lib/fonts";

export const metadata: Metadata = {
title: "NiffyInsur - Decentralized Insurance for Stellar Network",
description: "Parametric insurance powered by DAO governance. Get coverage for smart contract risks with transparent, community-driven claim voting on the Stellar blockchain.",
keywords: ["DeFi insurance", "parametric insurance", "Stellar blockchain", "DAO governance", "smart contract coverage", "decentralized insurance"],
authors: [{ name: "NiffyInsur Team" }],
creator: "NiffyInsur",
publisher: "NiffyInsur",
formatDetection: {
email: false,
address: false,
telephone: false,
},
metadataBase: new URL("https://niffyinsur.com"),
alternates: {
canonical: "/",
},
openGraph: {
type: "website",
locale: "en_US",
url: "https://niffyinsur.com",
title: "NiffyInsur - Decentralized Insurance for Stellar Network",
description: "Parametric insurance powered by DAO governance. Get coverage for smart contract risks with transparent, community-driven claim voting.",
siteName: "NiffyInsur",
images: [
{
url: "/og-image.png",
width: 1200,
height: 630,
alt: "NiffyInsur - Decentralized Insurance",
},
],
},
twitter: {
card: "summary_large_image",
title: "NiffyInsur - Decentralized Insurance for Stellar Network",
description: "Parametric insurance powered by DAO governance. Get coverage for smart contract risks with transparent, community-driven claim voting.",
images: ["/og-image.png"],
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
verification: {
google: "your-google-verification-code",
},
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
return <html lang="en"><body>{children}</body></html>;
return (
<html lang="en" className={`${inter.variable} ${ibmPlexMono.variable}`}>
<head>
<link rel="icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
</head>
<body className="font-sans">
{children}
<Toaster />
</body>
</html>
);
}
11 changes: 10 additions & 1 deletion frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import { Hero, HowItWorks, Security, CTA } from '@/components/landing'

export default function Home() {
return <main><h1>niffyInsur</h1></main>;
return (
<main>
<Hero />
<HowItWorks />
<Security />
<CTA />
</main>
)
}
5 changes: 5 additions & 0 deletions frontend/src/app/policy/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { PolicyInitiation } from '@/components/policy/policy-initiation'

export default function PolicyPage() {
return <PolicyInitiation />
}
54 changes: 54 additions & 0 deletions frontend/src/app/quote/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { QuoteForm } from '@/components/quote/quote-form'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Shield, Calculator } from 'lucide-react'

export default function QuotePage() {
return (
<div className="container mx-auto px-4 py-8">
<div className="text-center mb-8">
<div className="flex items-center justify-center mb-4">
<Calculator className="h-8 w-8 text-blue-600 mr-2" />
<h1 className="text-3xl font-bold text-gray-900">Get Insurance Quote</h1>
</div>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
Calculate your premium for smart contract insurance coverage on the Stellar network.
</p>
</div>

<div className="mb-8">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Shield className="h-5 w-5" />
How It Works
</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 text-sm">
<div>
<h3 className="font-semibold mb-2">1. Provide Details</h3>
<p className="text-gray-600">
Enter your contract address, coverage amount, and risk factors.
</p>
</div>
<div>
<h3 className="font-semibold mb-2">2. Get Quote</h3>
<p className="text-gray-600">
Our algorithm calculates your premium based on risk assessment.
</p>
</div>
<div>
<h3 className="font-semibold mb-2">3. Purchase Policy</h3>
<p className="text-gray-600">
Accept the quote and pay the premium to activate coverage.
</p>
</div>
</div>
</CardContent>
</Card>
</div>

<QuoteForm />
</div>
)
}
12 changes: 12 additions & 0 deletions frontend/src/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: ['/api/', '/admin/'],
},
sitemap: 'https://niffyinsur.com/sitemap.xml',
}
}
44 changes: 44 additions & 0 deletions frontend/src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { MetadataRoute } from 'next'

export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://niffyinsur.com'

return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
{
url: `${baseUrl}/quote`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.8,
},
{
url: `${baseUrl}/dashboard`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 0.7,
},
{
url: `${baseUrl}/terms`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.5,
},
{
url: `${baseUrl}/privacy`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.5,
},
{
url: `${baseUrl}/docs`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.6,
},
]
}
Loading
Loading