AETHONIX
1.0.0
AETHONIX is a futuristic AI SaaS platform designed to feel like the marketing site of a $1B-valuation startup. It blends cinematic 3D visuals, neon glassmorphism, and a fully functional admin backend into a single, deployable Next.js 15 application.
The visitor should feel they've entered a holographic command center: dark cosmic backgrounds, soft purple glows pulsing in the periphery, a 3D logo orbiting in space, and content that fades and floats into view as they scroll. Every interaction — hover, click, scroll — should feel premium, intentional, and weightless.
npx create-next-app@latest aethonix --typescript --tailwind --app --import-alias "@/*"
cd aethonix
npm install framer-motion gsap three @react-three/fiber @react-three/drei \
@react-three/postprocessing swiper lenis zustand mongoose jsonwebtoken \
bcryptjs cloudinary lucide-react recharts clsx tailwind-merge \
class-variance-authority
npm install -D @types/jsonwebtoken @types/bcryptjs @types/three
npx shadcn@latest init
npx shadcn@latest add button card input textarea label dialog toast
npm run dev
Create .env.example at the project root:
# MongoDB
MONGODB_URI=your_mongodb_connection_string_here
# Authentication (JWT)
JWT_SECRET=replace_with_a_strong_32_character_minimum_secret_string
JWT_EXPIRES_IN=7d
# Admin Seed Credentials
ADMIN_EMAIL=admin@aethonix.ai
ADMIN_PASSWORD=Admin@123
# Cloudinary (uploads)
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# Public
NEXT_PUBLIC_PORTFOLIO_URL=https://praveen-kannan-4607.vercel.app/
NEXT_PUBLIC_SITE_URL=https://aethonix.vercel.app
aethonix/
├── app/
│ ├── layout.tsx
│ ├── page.tsx
│ ├── globals.css
│ ├── loading.tsx
│ ├── not-found.tsx
│ ├── about/page.tsx
│ ├── solutions/page.tsx
│ ├── products/page.tsx
│ ├── resources/page.tsx
│ ├── contact/page.tsx
│ │
│ ├── admin/
│ │ ├── login/page.tsx
│ │ └── dashboard/
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ ├── payments/page.tsx
│ │ ├── feedback/page.tsx
│ │ ├── projects/page.tsx
│ │ ├── messages/page.tsx
│ │ └── resume/page.tsx
│ │
│ └── api/
│ ├── auth/
│ │ ├── login/route.ts
│ │ ├── verify/route.ts
│ │ └── logout/route.ts
│ ├── contact/route.ts
│ ├── feedback/route.ts
│ ├── projects/route.ts
│ ├── payments/route.ts
│ ├── resume/route.ts
│ └── upload/route.ts
│
├── components/
│ ├── layout/
│ │ ├── Navbar.tsx
│ │ ├── Footer.tsx
│ │ ├── ScrollProgress.tsx
│ │ ├── CursorGlow.tsx
│ │ ├── LoadingScreen.tsx
│ │ └── ParticleBg.tsx
│ ├── sections/
│ │ ├── Hero.tsx
│ │ ├── TrustedBrands.tsx
│ │ ├── About.tsx
│ │ ├── Solutions.tsx
│ │ ├── Projects.tsx
│ │ ├── Payments.tsx
│ │ ├── Feedback.tsx
│ │ ├── Resources.tsx
│ │ ├── Contact.tsx
│ │ └── CTABanner.tsx
│ ├── 3d/
│ │ ├── HeroLogo3D.tsx
│ │ ├── OrbitRings.tsx
│ │ └── ParticleField.tsx
│ ├── ui/
│ │ ├── GlowCard.tsx
│ │ ├── NeonButton.tsx
│ │ ├── GradientText.tsx
│ │ ├── StatCard.tsx
│ │ └── button.tsx # shadcn
│ └── admin/
│ ├── Sidebar.tsx
│ ├── StatCard.tsx
│ ├── DataTable.tsx
│ └── Charts.tsx
│
├── lib/
│ ├── mongodb.ts
│ ├── auth.ts
│ ├── cloudinary.ts
│ ├── utils.ts
│ ├── motion.ts # framer-motion variants
│ └── mockData.ts
│
├── models/
│ ├── User.ts
│ ├── Contact.ts
│ ├── Feedback.ts
│ ├── Project.ts
│ ├── Payment.ts
│ └── Resume.ts
│
├── store/
│ └── useUIStore.ts
│
├── public/
│ ├── logos/
│ │ ├── google.svg
│ │ ├── microsoft.svg
│ │ ├── nvidia.svg
│ │ ├── aws.svg
│ │ └── meta.svg
│ └── favicon.ico
│
├── middleware.ts
├── tailwind.config.ts
├── next.config.js
├── tsconfig.json
├── .env.example
├── .env.local # gitignored
└── package.json
import type { Config } from "tailwindcss";
const config: Config = {
darkMode: "class",
content: [
"./app/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
],
theme: {
extend: {
colors: {
bg: {
DEFAULT: "#050816",
secondary: "#0a0a1a",
},
primary: {
DEFAULT: "#7c3aed",
glow: "#a855f7",
light: "#c084fc",
},
accent: {
cyan: "#22d3ee",
},
glass: {
DEFAULT: "rgba(255,255,255,0.05)",
border: "rgba(255,255,255,0.10)",
},
},
fontFamily: {
sans: ["var(--font-inter)", "system-ui"],
display: ["var(--font-space)", "system-ui"],
mono: ["JetBrains Mono", "monospace"],
},
keyframes: {
"glow-pulse": {
"0%, 100%": { boxShadow: "0 0 20px rgba(168,85,247,0.4)" },
"50%": { boxShadow: "0 0 40px rgba(168,85,247,0.8)" },
},
float: {
"0%, 100%": { transform: "translateY(0px)" },
"50%": { transform: "translateY(-12px)" },
},
"gradient-shift": {
"0%, 100%": { backgroundPosition: "0% 50%" },
"50%": { backgroundPosition: "100% 50%" },
},
shimmer: {
"0%": { backgroundPosition: "-200% 0" },
"100%": { backgroundPosition: "200% 0" },
},
},
animation: {
"glow-pulse": "glow-pulse 3s ease-in-out infinite",
float: "float 4s ease-in-out infinite",
"gradient-shift": "gradient-shift 8s ease infinite",
shimmer: "shimmer 2s linear infinite",
},
backgroundImage: {
"radial-glow": "radial-gradient(ellipse at top, rgba(124,58,237,0.25) 0%, transparent 60%)",
"grid-pattern": "linear-gradient(rgba(168,85,247,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(168,85,247,0.05) 1px, transparent 1px)",
},
},
},
plugins: [require("tailwindcss-animate")],
};
export default config;
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--bg: #050816;
--primary: #7c3aed;
--primary-glow: #a855f7;
}
html { scroll-behavior: smooth; }
body {
@apply bg-bg text-white antialiased;
font-family: var(--font-inter);
background-image:
radial-gradient(ellipse 80% 50% at 50% -20%, rgba(124,58,237,0.3), transparent),
radial-gradient(ellipse 60% 50% at 80% 50%, rgba(34,211,238,0.08), transparent);
}
h1, h2, h3, h4 { font-family: var(--font-space); @apply font-bold tracking-tight; }
::selection { @apply bg-primary/40 text-white; }
}
@layer components {
.glass {
@apply bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl;
box-shadow: 0 8px 32px 0 rgba(0,0,0,0.37);
}
.glass-hover {
@apply glass transition-all duration-300;
}
.glass-hover:hover {
@apply border-primary-glow/40 -translate-y-1;
box-shadow: 0 12px 40px rgba(168,85,247,0.25);
}
.neon-glow {
box-shadow:
0 0 20px rgba(168,85,247,0.4),
0 0 40px rgba(168,85,247,0.2);
}
.gradient-text {
@apply bg-clip-text text-transparent;
background-image: linear-gradient(135deg, #c084fc 0%, #a855f7 50%, #7c3aed 100%);
}
.gradient-border {
position: relative;
}
.gradient-border::before {
content: '';
position: absolute; inset: 0;
padding: 1px;
border-radius: inherit;
background: linear-gradient(135deg, #7c3aed, #22d3ee);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
.section-padding { @apply px-6 py-24 md:px-12 lg:px-20; }
}
@layer utilities {
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
}
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
remotePatterns: [
{ protocol: "https", hostname: "res.cloudinary.com" },
{ protocol: "https", hostname: "api.dicebear.com" },
{ protocol: "https", hostname: "images.unsplash.com" },
],
},
experimental: {
optimizePackageImports: ["lucide-react", "framer-motion"],
},
};
module.exports = nextConfig;
{
"compilerOptions": {
"target": "ES2022",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] }
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
import mongoose from "mongoose";
const MONGODB_URI = process.env.MONGODB_URI;
interface CachedConnection {
conn: typeof mongoose | null;
promise: Promise<typeof mongoose> | null;
}
declare global {
// eslint-disable-next-line no-var
var mongooseCache: CachedConnection | undefined;
}
const cached: CachedConnection =
global.mongooseCache ?? { conn: null, promise: null };
export async function connectDB(): Promise<typeof mongoose> {
if (!MONGODB_URI) {
throw new Error("MONGODB_URI not configured");
}
if (cached.conn) return cached.conn;
if (!cached.promise) {
cached.promise = mongoose.connect(MONGODB_URI, {
bufferCommands: false,
});
}
cached.conn = await cached.promise;
return cached.conn;
}
import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";
const SECRET = process.env.JWT_SECRET || "dev-secret-change-me-32chars-min";
const EXPIRES_IN = process.env.JWT_EXPIRES_IN || "7d";
export interface JWTPayload {
userId: string;
email: string;
role: "admin" | "user";
}
export const signToken = (payload: JWTPayload): string =>
jwt.sign(payload, SECRET, { expiresIn: EXPIRES_IN });
export const verifyToken = (token: string): JWTPayload | null => {
try {
return jwt.verify(token, SECRET) as JWTPayload;
} catch {
return null;
}
};
export const hashPassword = (plain: string): Promise<string> =>
bcrypt.hash(plain, 10);
export const comparePassword = (
plain: string,
hashed: string
): Promise<boolean> => bcrypt.compare(plain, hashed);
import { v2 as cloudinary } from "cloudinary";
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
export async function uploadToCloudinary(
fileBuffer: Buffer,
folder = "aethonix"
): Promise<string> {
return new Promise((resolve, reject) => {
cloudinary.uploader
.upload_stream({ folder, resource_type: "auto" }, (err, result) => {
if (err || !result) return reject(err);
resolve(result.secure_url);
})
.end(fileBuffer);
});
}
export default cloudinary;
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
import mongoose, { Schema, model, models } from "mongoose";
const UserSchema = new Schema(
{
email: { type: String, required: true, unique: true, lowercase: true },
password: { type: String, required: true },
role: { type: String, enum: ["admin", "user"], default: "user" },
},
{ timestamps: true }
);
export default models.User || model("User", UserSchema);
import { Schema, model, models } from "mongoose";
const ContactSchema = new Schema(
{
name: { type: String, required: true },
email: { type: String, required: true },
subject: { type: String, required: true },
message: { type: String, required: true },
},
{ timestamps: true }
);
export default models.Contact || model("Contact", ContactSchema);
import { Schema, model, models } from "mongoose";
const FeedbackSchema = new Schema(
{
name: { type: String, required: true },
email: { type: String, required: true },
type: { type: String, enum: ["general", "bug", "feature", "praise"], default: "general" },
rating: { type: Number, min: 1, max: 5, required: true },
message: { type: String, required: true, maxlength: 1000 },
},
{ timestamps: true }
);
export default models.Feedback || model("Feedback", FeedbackSchema);
import { Schema, model, models } from "mongoose";
const ProjectSchema = new Schema(
{
title: { type: String, required: true },
category: { type: String, enum: ["ai-ml", "web", "dashboard", "automation", "system"], required: true },
description: { type: String, required: true },
image: { type: String, required: true },
tech: { type: [String], default: [] },
link: { type: String, default: "" },
featured: { type: Boolean, default: false },
},
{ timestamps: true }
);
export default models.Project || model("Project", ProjectSchema);
import { Schema, model, models } from "mongoose";
const PaymentSchema = new Schema(
{
clientName: { type: String, required: true },
amount: { type: Number, required: true },
transactionId: { type: String, required: true, unique: true },
date: { type: Date, default: Date.now },
status: { type: String, enum: ["pending", "verified", "failed"], default: "verified" },
proofUrl: { type: String, default: "" },
},
{ timestamps: true }
);
export default models.Payment || model("Payment", PaymentSchema);
import { Schema, model, models } from "mongoose";
const ResumeSchema = new Schema(
{
url: { type: String, required: true },
version: { type: String, default: "v1.0" },
uploadedAt: { type: Date, default: Date.now },
},
{ timestamps: true }
);
export default models.Resume || model("Resume", ResumeSchema);
import { NextResponse } from "next/server";
import { cookies } from "next/headers";
import { connectDB } from "@/lib/mongodb";
import { signToken, comparePassword, hashPassword } from "@/lib/auth";
import User from "@/models/User";
export async function POST(req: Request) {
const { email, password } = await req.json();
try {
await connectDB();
let user = await User.findOne({ email });
// Seed admin on first request if missing
if (!user && email === process.env.ADMIN_EMAIL) {
const hashed = await hashPassword(process.env.ADMIN_PASSWORD!);
user = await User.create({ email, password: hashed, role: "admin" });
}
if (!user) return NextResponse.json({ error: "Invalid credentials" }, { status: 401 });
const ok = await comparePassword(password, user.password);
if (!ok) return NextResponse.json({ error: "Invalid credentials" }, { status: 401 });
const token = signToken({ userId: user._id.toString(), email: user.email, role: user.role });
cookies().set("aethonix_token", token, {
httpOnly: true, secure: true, sameSite: "lax", maxAge: 60 * 60 * 24 * 7, path: "/",
});
return NextResponse.json({ success: true, user: { email: user.email, role: user.role } });
} catch {
// Demo fallback when no MongoDB
if (email === "admin@aethonix.ai" && password === "Admin@123") {
const token = signToken({ userId: "demo", email, role: "admin" });
cookies().set("aethonix_token", token, { httpOnly: true, secure: true, sameSite: "lax", maxAge: 604800, path: "/" });
return NextResponse.json({ success: true, mock: true });
}
return NextResponse.json({ error: "Invalid credentials" }, { status: 401 });
}
}
import { NextResponse } from "next/server";
import { cookies } from "next/headers";
import { verifyToken } from "@/lib/auth";
export async function GET() {
const token = cookies().get("aethonix_token")?.value;
if (!token) return NextResponse.json({ authenticated: false }, { status: 401 });
const payload = verifyToken(token);
if (!payload) return NextResponse.json({ authenticated: false }, { status: 401 });
return NextResponse.json({ authenticated: true, user: payload });
}
import { NextResponse } from "next/server";
import { connectDB } from "@/lib/mongodb";
import Contact from "@/models/Contact";
export async function POST(req: Request) {
const body = await req.json();
try {
await connectDB();
const doc = await Contact.create(body);
return NextResponse.json({ success: true, data: doc });
} catch {
return NextResponse.json({ success: true, mock: true });
}
}
export async function GET() {
try {
await connectDB();
const data = await Contact.find().sort({ createdAt: -1 }).limit(50);
return NextResponse.json({ data });
} catch {
return NextResponse.json({ data: [], mock: true });
}
}
import { NextResponse } from "next/server";
import { connectDB } from "@/lib/mongodb";
import Feedback from "@/models/Feedback";
import { MOCK_FEEDBACK } from "@/lib/mockData";
export async function POST(req: Request) {
const body = await req.json();
try {
await connectDB();
const doc = await Feedback.create(body);
return NextResponse.json({ success: true, data: doc });
} catch {
return NextResponse.json({ success: true, mock: true });
}
}
export async function GET() {
try {
await connectDB();
const data = await Feedback.find().sort({ createdAt: -1 });
return NextResponse.json({ data });
} catch {
return NextResponse.json({ data: MOCK_FEEDBACK, mock: true });
}
}
import { NextResponse } from "next/server";
import { connectDB } from "@/lib/mongodb";
import Project from "@/models/Project";
import { MOCK_PROJECTS } from "@/lib/mockData";
export async function GET() {
try {
await connectDB();
const data = await Project.find().sort({ createdAt: -1 });
return NextResponse.json({ data: data.length ? data : MOCK_PROJECTS });
} catch {
return NextResponse.json({ data: MOCK_PROJECTS, mock: true });
}
}
export async function POST(req: Request) {
const body = await req.json();
try {
await connectDB();
const doc = await Project.create(body);
return NextResponse.json({ success: true, data: doc });
} catch {
return NextResponse.json({ error: "DB unavailable" }, { status: 503 });
}
}
import { NextResponse } from "next/server";
import { connectDB } from "@/lib/mongodb";
import Payment from "@/models/Payment";
import { MOCK_PAYMENTS } from "@/lib/mockData";
export async function GET() {
try {
await connectDB();
const data = await Payment.find().sort({ date: -1 });
return NextResponse.json({ data: data.length ? data : MOCK_PAYMENTS });
} catch {
return NextResponse.json({ data: MOCK_PAYMENTS, mock: true });
}
}
export async function POST(req: Request) {
const body = await req.json();
try {
await connectDB();
const doc = await Payment.create(body);
return NextResponse.json({ success: true, data: doc });
} catch {
return NextResponse.json({ error: "DB unavailable" }, { status: 503 });
}
}
import { NextResponse } from "next/server";
import { connectDB } from "@/lib/mongodb";
import Resume from "@/models/Resume";
export async function GET() {
try {
await connectDB();
const latest = await Resume.findOne().sort({ uploadedAt: -1 });
return NextResponse.json({ data: latest });
} catch {
return NextResponse.json({ data: { url: "/resume-praveen.pdf", version: "v1.0", mock: true } });
}
}
export async function POST(req: Request) {
const body = await req.json();
try {
await connectDB();
const doc = await Resume.create(body);
return NextResponse.json({ success: true, data: doc });
} catch {
return NextResponse.json({ error: "DB unavailable" }, { status: 503 });
}
}
import { NextResponse } from "next/server";
import { uploadToCloudinary } from "@/lib/cloudinary";
export async function POST(req: Request) {
try {
const formData = await req.formData();
const file = formData.get("file") as File | null;
if (!file) return NextResponse.json({ error: "No file" }, { status: 400 });
const buffer = Buffer.from(await file.arrayBuffer());
const url = await uploadToCloudinary(buffer);
return NextResponse.json({ success: true, url });
} catch (err) {
return NextResponse.json({ error: "Upload failed" }, { status: 500 });
}
}
import { NextResponse, type NextRequest } from "next/server";
import { verifyToken } from "@/lib/auth";
export function middleware(req: NextRequest) {
const { pathname } = req.nextUrl;
// Only guard /admin/dashboard/*
if (pathname.startsWith("/admin/dashboard")) {
const token = req.cookies.get("aethonix_token")?.value;
const payload = token ? verifyToken(token) : null;
if (!payload || payload.role !== "admin") {
const loginUrl = new URL("/admin/login", req.url);
return NextResponse.redirect(loginUrl);
}
}
return NextResponse.next();
}
export const config = {
matcher: ["/admin/dashboard/:path*"],
};
components/layout/LoadingScreen.tsxcomponents/layout/CursorGlow.tsxcomponents/layout/ScrollProgress.tsxcomponents/layout/ParticleBg.tsxcomponents/layout/Navbar.tsxcomponents/sections/Hero.tsxcomponents/3d/HeroLogo3D.tsxcomponents/sections/TrustedBrands.tsxcomponents/sections/About.tsxcomponents/sections/Solutions.tsxcomponents/sections/Projects.tsxcomponents/sections/Payments.tsxcomponents/sections/Feedback.tsxcomponents/sections/Resources.tsxcomponents/sections/Contact.tsxcomponents/sections/CTABanner.tsxcomponents/layout/Footer.tsxcomponents/layout/Navbar.tsxcomponents/sections/Hero.tsxMIT
Praveen Kannan
Dark Neon Cyberpunk · Futuristic AI SaaS
2025
No comments yet. Be the first!