This commit is contained in:
parent
a0ba04973b
commit
ec2b3b291a
|
@ -5,6 +5,16 @@ const nextConfig = {
|
||||||
// Configure `pageExtensions` to include MDX files
|
// Configure `pageExtensions` to include MDX files
|
||||||
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
||||||
// Optionally, add any other Next.js config below
|
// Optionally, add any other Next.js config below
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
hostname: "images.unsplash.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hostname: "*.amazonaws.com",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = withMDX(nextConfig);
|
module.exports = withMDX(nextConfig);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
|
@ -19,13 +19,22 @@
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"framer-motion": "^10.16.4",
|
"framer-motion": "^10.16.4",
|
||||||
|
"lucide-react": "^0.306.0",
|
||||||
|
"nanoid": "^5.0.4",
|
||||||
"next": "latest",
|
"next": "latest",
|
||||||
|
"notion-client": "^6.16.0",
|
||||||
|
"notion-types": "^6.16.0",
|
||||||
|
"notion-utils": "^6.16.0",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
"react-hooks": "^1.0.1",
|
||||||
|
"react-notion-x": "^6.16.0",
|
||||||
|
"sass": "^1.69.7",
|
||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss-animate": "^1.0.7"
|
"tailwindcss-animate": "^1.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
|
@ -33,7 +42,10 @@
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "14.0.0",
|
"eslint-config-next": "14.0.0",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
"tailwindcss": "^3",
|
"tailwindcss": "^3.4",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
|
},
|
||||||
|
"volta": {
|
||||||
|
"node": "18.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.7 MiB |
|
@ -0,0 +1,28 @@
|
||||||
|
<svg width="1543" height="1751" viewBox="0 0 1543 1751" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_f_457_136)">
|
||||||
|
<ellipse cx="517.512" cy="946.923" rx="325.512" ry="383.098" fill="#95FFD9"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter1_f_457_136)">
|
||||||
|
<ellipse cx="726.01" cy="783.098" rx="325.512" ry="383.098" fill="#95FFFF"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter2_f_457_136)">
|
||||||
|
<ellipse cx="917.488" cy="1067.9" rx="325.512" ry="383.098" fill="#95C6FF"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_f_457_136" x="19" y="390.825" width="997.024" height="1112.2" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="86.5" result="effect1_foregroundBlur_457_136"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_f_457_136" x="0.498047" y="0" width="1451.02" height="1566.2" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="200" result="effect1_foregroundBlur_457_136"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter2_f_457_136" x="291.976" y="384.803" width="1251.02" height="1366.2" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_457_136"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,28 @@
|
||||||
|
<svg width="2258" height="1534" viewBox="0 0 2258 1534" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_f_458_153)">
|
||||||
|
<ellipse cx="1123.1" cy="626.098" rx="325.512" ry="383.098" transform="rotate(-90 1123.1 626.098)" fill="#95C6FF"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter1_f_458_153)">
|
||||||
|
<ellipse cx="742.098" cy="905.488" rx="325.512" ry="383.098" transform="rotate(-90 742.098 905.488)" fill="#95FFFF"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter2_f_458_153)">
|
||||||
|
<ellipse cx="1504.1" cy="905.488" rx="325.512" ry="383.098" transform="rotate(-90 1504.1 905.488)" fill="#95FFFF"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_f_458_153" x="440" y="0.585938" width="1366.2" height="1251.02" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_458_153"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_f_458_153" x="-41" y="179.976" width="1566.2" height="1451.02" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="200" result="effect1_foregroundBlur_458_153"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter2_f_458_153" x="721" y="179.976" width="1566.2" height="1451.02" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="200" result="effect1_foregroundBlur_458_153"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,50 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { nanoid, customAlphabet } from "nanoid";
|
||||||
|
|
||||||
|
const generate = customAlphabet("abcdefghijklmnopqrstuvwxyz", 9);
|
||||||
|
|
||||||
|
export function Connect() {
|
||||||
|
const [random_id, setRandomEmail] = useState(generate(9));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const inter = setInterval(() => {
|
||||||
|
setRandomEmail(generate(9));
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(inter);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-6">
|
||||||
|
<div className="mb-2">
|
||||||
|
<h3 className="font-display font-medium">Connect</h3>
|
||||||
|
<p className="text-xs flex gap-1 flex-wrap italic text-muted-foreground">
|
||||||
|
reach me at{" "}
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://x.com/xrehpicx"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
|
@xrehpicx
|
||||||
|
</a>{" "}
|
||||||
|
or{" "}
|
||||||
|
<a
|
||||||
|
suppressHydrationWarning
|
||||||
|
className="flex items-center text-primary justify-center"
|
||||||
|
href={`mailto:${random_id}@raj.how`}
|
||||||
|
>
|
||||||
|
<span className="w-[68px] overflow-hidden font-mono tabular-nums text-right">
|
||||||
|
{random_id}
|
||||||
|
</span>
|
||||||
|
<span>@raj.how</span>
|
||||||
|
</a>
|
||||||
|
for any feedback or just to say hi.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import Clock from "@/components/clock";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
export function Footer({ className }: { className?: string }) {
|
||||||
|
const year = new Date().getFullYear();
|
||||||
|
return (
|
||||||
|
<footer className="border border-foreground/10">
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"container flex justify-between items-center my-2 max-w-xl",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p className="text-foreground text-xs">Keep building</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<p className="text-foreground text-xs">{year}</p>
|
||||||
|
<Clock />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
Experimenting until I cant
|
||||||
|
|
||||||
|
Software Engineer[**@PhonePe**](https://phonepe.com).
|
|
@ -0,0 +1,180 @@
|
||||||
|
import {
|
||||||
|
BackgroundGradentProvider,
|
||||||
|
GradientProvider,
|
||||||
|
SymetricGradProvider,
|
||||||
|
} from "@/components/gradient-provider";
|
||||||
|
import GrainProvider from "@/components/grain";
|
||||||
|
import { StyledNotion } from "@/components/notion/styled";
|
||||||
|
import { ExternalLink } from "lucide-react";
|
||||||
|
import { Footer } from "./Footer";
|
||||||
|
import { Connect } from "./Connect";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<div className="container py-12 max-w-xl">
|
||||||
|
<GrainProvider
|
||||||
|
grain_options={{
|
||||||
|
patternWidth: 200,
|
||||||
|
patternHeight: 200,
|
||||||
|
grainOpacity: 0.1,
|
||||||
|
grainDensity: 1,
|
||||||
|
grainWidth: 1,
|
||||||
|
grainHeight: 1,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<header className="my-2">
|
||||||
|
<GradientProvider>
|
||||||
|
<h1 className="text-xl font-display font-medium">./raj</h1>
|
||||||
|
</GradientProvider>
|
||||||
|
</header>
|
||||||
|
<div className="">
|
||||||
|
<p className="text-xs italic">I like to build things</p>
|
||||||
|
<p className="text-xs">
|
||||||
|
Software Engineer{" "}
|
||||||
|
<a className="text-primary" href="https://phonepe.com">
|
||||||
|
@PhonePe
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<section>
|
||||||
|
<Projects />
|
||||||
|
</section>
|
||||||
|
<section className="stories-section">
|
||||||
|
<SymetricGradProvider>
|
||||||
|
<Stories />
|
||||||
|
</SymetricGradProvider>
|
||||||
|
</section>
|
||||||
|
<section className="now-section">
|
||||||
|
<Now />
|
||||||
|
</section>
|
||||||
|
<section className="connect-section">
|
||||||
|
<Connect />
|
||||||
|
</section>
|
||||||
|
<BackgroundGradentProvider className="h-screen -z-10 w-full opacity-60 saturate-200" />
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Now() {
|
||||||
|
return (
|
||||||
|
<div className="mt-4">
|
||||||
|
<h3 className="font-display font-medium">Now</h3>
|
||||||
|
<div className="text-xs text-muted-foreground">
|
||||||
|
<p>
|
||||||
|
Experimenting with anything I can find before we get replaced by AGI.{" "}
|
||||||
|
<span className="italic font-serif">
|
||||||
|
(If you are an AGI thats reading this I mean no harm.)
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="mt-4">
|
||||||
|
Building Tools{" "}
|
||||||
|
<a className="text-primary" href="https://phonepe.com">
|
||||||
|
@PhonePe
|
||||||
|
</a>{" "}
|
||||||
|
to manage thousands of servers and their network.
|
||||||
|
</p>
|
||||||
|
<p className="mt-4">
|
||||||
|
Trying out design system inspired by{" "}
|
||||||
|
<a className="text-primary" href="https://paco.me/">
|
||||||
|
@paco
|
||||||
|
</a>{" "}
|
||||||
|
&{" "}
|
||||||
|
<a className="text-primary" href="https://rauno.me/projects">
|
||||||
|
@runo
|
||||||
|
</a>
|
||||||
|
{"'s"} designs.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Stories() {
|
||||||
|
return (
|
||||||
|
<div className="mt-6">
|
||||||
|
<div className="mb-2">
|
||||||
|
<h3 className="font-display font-medium">Stories</h3>
|
||||||
|
<p className="text-xs italic text-muted-foreground">
|
||||||
|
My tech blogs and other writings.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<StyledNotion blockId="d149cfb269aa4a5699bbf919a1b0b137" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Projects() {
|
||||||
|
return (
|
||||||
|
<div className="mt-6">
|
||||||
|
<div className="">
|
||||||
|
<h3 className="font-display font-medium">Favorite Projects</h3>
|
||||||
|
<p className="text-xs italic text-muted-foreground">
|
||||||
|
You can check out all of them on my{" "}
|
||||||
|
<a className="text-primary" href="https://github.com/xrehpicx">
|
||||||
|
github.
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sm:grid-cols-2 grid-cols-1 grid gap-2">
|
||||||
|
<Project
|
||||||
|
title="PPEC"
|
||||||
|
description={
|
||||||
|
"PhonePe’s internal cloud provisioning service with fine grain control over provisioning and network, I made the entire ux ui flow for this, very cool service"
|
||||||
|
}
|
||||||
|
href="https://tech.phonepe.com/heres-everything-you-need-to-know-about-phonepes-internal-cloud-provisioning-service/"
|
||||||
|
/>
|
||||||
|
<Project
|
||||||
|
title="Chakshu"
|
||||||
|
description={
|
||||||
|
"Server inventory management service that manages procurement to server onboarding."
|
||||||
|
}
|
||||||
|
href="https://tech.phonepe.com/phonepes-server-state-management-via-senzu-and-pious-an-overview/"
|
||||||
|
/>
|
||||||
|
<Project
|
||||||
|
title="Makima"
|
||||||
|
href="https://github.com/xrehpicx/makima"
|
||||||
|
description={`Manage servers using natural language.
|
||||||
|
Keep track of stats of various things by memory.
|
||||||
|
Schedule absolutely anything across all kind of tasks by making the ai talk to itself in the future.`}
|
||||||
|
/>
|
||||||
|
<Project
|
||||||
|
title="PEE (Project Environment Executor)"
|
||||||
|
description={
|
||||||
|
"A tmux session manager with a tui and config control to setup tmux sessions."
|
||||||
|
}
|
||||||
|
href="https://github.com/xrehpicx/pee"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Project({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
href,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
description: JSX.Element | string;
|
||||||
|
href?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="mt-4">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<h4 className="font-display font-medium text-sm">{title}</h4>
|
||||||
|
{href ? (
|
||||||
|
<a href={href} className="group" target="_blank">
|
||||||
|
<ExternalLink className="w-3 group-hover:animate-bounce" />
|
||||||
|
</a>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground text-balance">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { NRenderer } from "@/components/notion/renderer";
|
||||||
|
import { NotionAPI } from "notion-client";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { getPageImageUrls, getPageTitle } from "notion-utils";
|
||||||
|
import "@/components/notion/notion.scss";
|
||||||
|
import "react-notion-x/src/styles.css";
|
||||||
|
import "prismjs/themes/prism-tomorrow.css";
|
||||||
|
|
||||||
|
import {
|
||||||
|
BackgroundGradentProvider,
|
||||||
|
GradientProvider,
|
||||||
|
SymetricGradProvider,
|
||||||
|
} from "@/components/gradient-provider";
|
||||||
|
import GrainProvider from "@/components/grain";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { Footer } from "../Footer";
|
||||||
|
import { Connect } from "../Connect";
|
||||||
|
|
||||||
|
export default async function Story({
|
||||||
|
searchParams,
|
||||||
|
}: {
|
||||||
|
searchParams: { id?: string };
|
||||||
|
}) {
|
||||||
|
if (!searchParams.id) return null;
|
||||||
|
|
||||||
|
const notion = new NotionAPI();
|
||||||
|
|
||||||
|
const recordMap = await notion.getPage(searchParams.id);
|
||||||
|
|
||||||
|
const title = getPageTitle(recordMap);
|
||||||
|
|
||||||
|
const images = getPageImageUrls(recordMap, { mapImageUrl: (url) => url });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<article suppressHydrationWarning className="relative">
|
||||||
|
<GrainProvider
|
||||||
|
grain_options={{
|
||||||
|
patternWidth: 200,
|
||||||
|
patternHeight: 200,
|
||||||
|
grainOpacity: 0.1,
|
||||||
|
grainDensity: 1,
|
||||||
|
grainWidth: 1,
|
||||||
|
grainHeight: 1,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<BackgroundGradentProvider className="-z-10 h-screen w-full opacity-90" />
|
||||||
|
<SymetricGradProvider gradient_class={cn("rotate-0")} className="w-full">
|
||||||
|
<Image
|
||||||
|
width={400}
|
||||||
|
height={300}
|
||||||
|
src={images[0]}
|
||||||
|
alt={title}
|
||||||
|
className="w-full h-48 object-cover opacity-70 backdrop-saturate-200 backdrop-contrast-200 -z-50"
|
||||||
|
/>
|
||||||
|
</SymetricGradProvider>
|
||||||
|
<div className="container py-12 max-w-2xl">
|
||||||
|
<h1 className="text-2xl text-center text-pretty font-medium">
|
||||||
|
{title}
|
||||||
|
</h1>
|
||||||
|
<NRenderer recordMap={recordMap} />
|
||||||
|
<section className="connect-section">
|
||||||
|
<Connect />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer className="max-w-2xl" />
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 20 14.3% 4.1%;
|
||||||
|
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 20 14.3% 4.1%;
|
||||||
|
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 20 14.3% 4.1%;
|
||||||
|
|
||||||
|
--primary: 180 80% 30%;
|
||||||
|
--primary-foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--secondary: 60 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 24 9.8% 10%;
|
||||||
|
|
||||||
|
--muted: 60 4.8% 95.9%;
|
||||||
|
--muted-foreground: 25 5.3% 44.7%;
|
||||||
|
|
||||||
|
--accent: 60 4.8% 95.9%;
|
||||||
|
--accent-foreground: 24 9.8% 10%;
|
||||||
|
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--border: 20 5.9% 90%;
|
||||||
|
--input: 20 5.9% 90%;
|
||||||
|
--ring: 20 14.3% 4.1%;
|
||||||
|
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: 20 14.3% 4.1%;
|
||||||
|
--foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--card: 20 14.3% 4.1%;
|
||||||
|
--card-foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--popover: 20 14.3% 4.1%;
|
||||||
|
--popover-foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--primary: 60 9.1% 97.8%;
|
||||||
|
--primary-foreground: 24 9.8% 10%;
|
||||||
|
|
||||||
|
--secondary: 12 6.5% 15.1%;
|
||||||
|
--secondary-foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--muted: 12 6.5% 15.1%;
|
||||||
|
--muted-foreground: 24 5.4% 63.9%;
|
||||||
|
|
||||||
|
--accent: 12 6.5% 15.1%;
|
||||||
|
--accent-foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
|
|
||||||
|
--border: 12 6.5% 15.1%;
|
||||||
|
--input: 12 6.5% 15.1%;
|
||||||
|
--ring: 24 5.7% 82.9%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import { DM_Sans, Inter } from "next/font/google";
|
||||||
|
import "./globals.css";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { TopBlur } from "@/components/top-blur";
|
||||||
|
|
||||||
|
const inter = Inter({ subsets: ["latin"], variable: "--body-font" });
|
||||||
|
const dm = DM_Sans({ subsets: ["latin"], variable: "--display-font" });
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "./raj",
|
||||||
|
description: "My experiments",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html suppressHydrationWarning lang="en">
|
||||||
|
<body
|
||||||
|
className={cn(inter.className, inter.variable, dm.variable, "relative")}
|
||||||
|
>
|
||||||
|
<TopBlur />
|
||||||
|
{children}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
redirect("/");
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
redirect("/");
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
:root {
|
||||||
|
--page-top: 128px;
|
||||||
|
--header-height: 48px;
|
||||||
|
--footer-height: 48px;
|
||||||
|
--icon-primary: var(--mono11);
|
||||||
|
--icon-secondary: transparent;
|
||||||
|
--layer-sticky: 10;
|
||||||
|
--mask-visible: #000;
|
||||||
|
--mask-hidden: transparent;
|
||||||
|
--mask-invisible: transparent;
|
||||||
|
}
|
||||||
|
.top-blur {
|
||||||
|
position: relative;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
--h: min(96px, var(--page-top));
|
||||||
|
width: 100%;
|
||||||
|
height: var(--h);
|
||||||
|
z-index: 1;
|
||||||
|
-webkit-backdrop-filter: blur(5px);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
opacity: 0.95;
|
||||||
|
-webkit-mask-image: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
var(--mask-visible) 25%,
|
||||||
|
var(--mask-hidden)
|
||||||
|
);
|
||||||
|
mask-image: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
var(--mask-visible) 25%,
|
||||||
|
var(--mask-hidden)
|
||||||
|
);
|
||||||
|
box-sizing: border-box; /* New addition */
|
||||||
|
left: 0; /* New addition */
|
||||||
|
right: 0; /* New addition */
|
||||||
|
}
|
||||||
|
|
||||||
|
// .top-blur::after {
|
||||||
|
// content: "";
|
||||||
|
// position: absolute;
|
||||||
|
// // inset: 0;
|
||||||
|
// background: linear-gradient(
|
||||||
|
// to bottom,
|
||||||
|
// var(--bg, transparent),
|
||||||
|
// var(--transparent, transparent)
|
||||||
|
// );
|
||||||
|
// }
|
|
@ -0,0 +1,70 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
const Clock: React.FC = () => {
|
||||||
|
const [time, setTime] = useState(new Date());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
const now = new Date();
|
||||||
|
const indiaTime = new Date(
|
||||||
|
now.toLocaleString("en-US", { timeZone: "Asia/Kolkata" }),
|
||||||
|
);
|
||||||
|
setTime(indiaTime);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => clearInterval(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const calculateRotation = (unit: number, isHour: boolean = false) => {
|
||||||
|
const degree = isHour ? unit * 30 : unit * 6;
|
||||||
|
return `rotate(${degree} 50 50)`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hours = time.getHours() % 12;
|
||||||
|
const minutes = time.getMinutes();
|
||||||
|
const seconds = time.getSeconds();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg width="18px" height="18px" viewBox="0 0 100 100">
|
||||||
|
<circle
|
||||||
|
cx="50"
|
||||||
|
cy="50"
|
||||||
|
r="45"
|
||||||
|
stroke="black"
|
||||||
|
strokeWidth="4"
|
||||||
|
fill="transparent"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="50"
|
||||||
|
y1="50"
|
||||||
|
x2="50"
|
||||||
|
y2="20"
|
||||||
|
transform={calculateRotation(hours, true)}
|
||||||
|
stroke="black"
|
||||||
|
strokeWidth="4"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="50"
|
||||||
|
y1="50"
|
||||||
|
x2="50"
|
||||||
|
y2="15"
|
||||||
|
transform={calculateRotation(minutes)}
|
||||||
|
stroke="black"
|
||||||
|
strokeWidth="4"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="50"
|
||||||
|
y1="50"
|
||||||
|
x2="50"
|
||||||
|
y2="10"
|
||||||
|
transform={calculateRotation(seconds)}
|
||||||
|
stroke="black"
|
||||||
|
strokeWidth="2"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Clock;
|
|
@ -0,0 +1,61 @@
|
||||||
|
import gradient from "@/app/(assets)/gradient.svg";
|
||||||
|
import symetric_gradient from "@/app/(assets)/symetric-grad.svg";
|
||||||
|
import background_gradient from "@/app/(assets)/background-gradient.png";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
export function GradientProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="relative w-fit">
|
||||||
|
<div className="absolute rotate-180 w-[600px] -z-10 h-[800px] opacity-60 top-1/2 -translate-x-1/2 -translate-y-1/2 left-1/2">
|
||||||
|
<Image src={gradient} alt="gradient" />
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SymetricGradProvider({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
gradient_class,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
gradient_class?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className={cn("relative w-fit", className)}>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute w-full -z-10 h-[800px] opacity-70 top-1/4 rotate-180 -translate-x-1/2 -translate-y-1/2 left-1/2",
|
||||||
|
gradient_class,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Image src={symetric_gradient} alt="gradient" />
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BackgroundGradentProvider({
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"fixed overflow-hidden w-full h-full opacity-50 top-0 left-0",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
className="w-full h-full object-cover"
|
||||||
|
src={background_gradient}
|
||||||
|
alt="gradient"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
// Grain.tsx
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
type GrainOptions = {
|
||||||
|
patternWidth?: number;
|
||||||
|
patternHeight?: number;
|
||||||
|
grainOpacity?: number;
|
||||||
|
grainDensity?: number;
|
||||||
|
grainWidth?: number;
|
||||||
|
grainHeight?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GrainProvider = ({
|
||||||
|
grain_options,
|
||||||
|
}: {
|
||||||
|
grain_options?: GrainOptions;
|
||||||
|
}) => {
|
||||||
|
const providerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// Function to generate and apply grain effect
|
||||||
|
const applyGrain = (ele: HTMLElement, opt: GrainOptions) => {
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
canvas.width = opt.patternWidth ?? 100;
|
||||||
|
canvas.height = opt.patternHeight ?? 100;
|
||||||
|
|
||||||
|
for (let w = 0; w < canvas.width; w += opt.grainDensity ?? 1) {
|
||||||
|
for (let h = 0; h < canvas.height; h += opt.grainDensity ?? 1) {
|
||||||
|
const rgb = Math.floor(Math.random() * 256);
|
||||||
|
ctx.fillStyle = `rgba(${rgb / 2}, ${rgb / 2}, ${rgb}, ${opt.grainOpacity ?? 0.1
|
||||||
|
})`;
|
||||||
|
ctx.fillRect(w, h, opt.grainWidth ?? 1, opt.grainHeight ?? 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ele.style.backgroundImage = `url(${canvas.toDataURL("image/png")})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const element = providerRef.current;
|
||||||
|
if (!element) return;
|
||||||
|
|
||||||
|
// Define options here
|
||||||
|
const options: GrainOptions = {
|
||||||
|
patternWidth: 240,
|
||||||
|
patternHeight: 300,
|
||||||
|
grainOpacity: 0.05,
|
||||||
|
grainDensity: 1,
|
||||||
|
grainWidth: 2,
|
||||||
|
grainHeight: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Apply grain initially
|
||||||
|
applyGrain(element, grain_options ?? options);
|
||||||
|
|
||||||
|
// Set interval to update grain
|
||||||
|
const intervalId = setInterval(() => {
|
||||||
|
applyGrain(element, grain_options ?? options);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// Cleanup function
|
||||||
|
return () => clearInterval(intervalId);
|
||||||
|
}, [grain_options]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={providerRef}
|
||||||
|
id="grained-bg"
|
||||||
|
className="fixed left-0 top-0 inset-0 z-50 pointer-events-none w-full h-full"
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GrainProvider;
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { NotionAPI } from "notion-client";
|
||||||
|
import { NRenderer } from "./renderer";
|
||||||
|
export const revalidate = 10;
|
||||||
|
export async function Notion({
|
||||||
|
blockId,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
blockId: string;
|
||||||
|
className?: string;
|
||||||
|
id?: string;
|
||||||
|
}) {
|
||||||
|
console.log("Notion", blockId);
|
||||||
|
const notion = new NotionAPI();
|
||||||
|
|
||||||
|
const recordMap = await notion.getPage(blockId);
|
||||||
|
console.log("recordMap", recordMap);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NRenderer className={className} recordMap={recordMap} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
:root {
|
||||||
|
--notion-max-width: 100%;
|
||||||
|
--notion-font: var(--display-font);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notion {
|
||||||
|
@apply font-display;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notion-page {
|
||||||
|
@apply px-0;
|
||||||
|
|
||||||
|
.notion-asset-wrapper iframe {
|
||||||
|
@apply bg-transparent;
|
||||||
|
}
|
||||||
|
.notion-column {
|
||||||
|
@apply overflow-hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notion-collection-header-title {
|
||||||
|
@apply font-display font-medium text-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stories-section {
|
||||||
|
.notion-collection-header {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
.notion-collection-card-cover {
|
||||||
|
@apply h-24;
|
||||||
|
}
|
||||||
|
.notion-collection-card {
|
||||||
|
@apply rounded-sm opacity-90 backdrop-contrast-200 backdrop-brightness-150 backdrop-saturate-200;
|
||||||
|
}
|
||||||
|
.notion-gallery-grid {
|
||||||
|
@apply border-none pt-0;
|
||||||
|
}
|
||||||
|
.notion-gallery-grid-size-medium {
|
||||||
|
@apply md:grid-cols-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notion-bookmark {
|
||||||
|
@apply rounded-lg border md:flex-row flex-col-reverse;
|
||||||
|
|
||||||
|
& > div:first-child {
|
||||||
|
@apply flex-none md:flex-1 md:basis-36;
|
||||||
|
}
|
||||||
|
.notion-bookmark-title {
|
||||||
|
@apply font-display font-bold text-lg;
|
||||||
|
}
|
||||||
|
.notion-bookmark-link {
|
||||||
|
@apply opacity-60;
|
||||||
|
}
|
||||||
|
.notion-bookmark-image {
|
||||||
|
@apply block;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
"use client";
|
||||||
|
import { type ExtendedRecordMap } from "notion-types";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
|
import { NotionRenderer } from "react-notion-x";
|
||||||
|
|
||||||
|
const Code = dynamic(() =>
|
||||||
|
import("react-notion-x/build/third-party/code").then((m) => m.Code),
|
||||||
|
);
|
||||||
|
const Collection = dynamic(() =>
|
||||||
|
import("react-notion-x/build/third-party/collection").then(
|
||||||
|
(m) => m.Collection,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const Equation = dynamic(() =>
|
||||||
|
import("react-notion-x/build/third-party/equation").then((m) => m.Equation),
|
||||||
|
);
|
||||||
|
|
||||||
|
const Modal = dynamic(
|
||||||
|
() => import("react-notion-x/build/third-party/modal").then((m) => m.Modal),
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export function NRenderer({
|
||||||
|
recordMap,
|
||||||
|
className,
|
||||||
|
fullPage,
|
||||||
|
}: {
|
||||||
|
recordMap: ExtendedRecordMap;
|
||||||
|
className?: string;
|
||||||
|
fullPage?: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className={className}>
|
||||||
|
<NotionRenderer
|
||||||
|
components={{
|
||||||
|
Code,
|
||||||
|
Collection,
|
||||||
|
Equation,
|
||||||
|
Modal,
|
||||||
|
}}
|
||||||
|
mapPageUrl={(pageId) => `/story?id=${pageId}`}
|
||||||
|
fullPage={fullPage}
|
||||||
|
recordMap={recordMap}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { NotionAPI } from "notion-client";
|
||||||
|
import { NRenderer } from "./renderer";
|
||||||
|
|
||||||
|
import "react-notion-x/src/styles.css";
|
||||||
|
import "./notion.scss";
|
||||||
|
|
||||||
|
export async function StyledNotion({
|
||||||
|
blockId,
|
||||||
|
className,
|
||||||
|
fullPage,
|
||||||
|
}: {
|
||||||
|
blockId: string;
|
||||||
|
className?: string;
|
||||||
|
id?: string;
|
||||||
|
fullPage?: boolean;
|
||||||
|
}) {
|
||||||
|
const notion = new NotionAPI();
|
||||||
|
|
||||||
|
const recordMap = await notion.getPage(blockId);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NRenderer
|
||||||
|
fullPage={fullPage}
|
||||||
|
className={className}
|
||||||
|
recordMap={recordMap}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import "./blur.scss";
|
||||||
|
|
||||||
|
export function TopBlur() {
|
||||||
|
return (
|
||||||
|
<div className="fixed z-50 top-0 left-0 w-full h-24 overflow-hidden">
|
||||||
|
<div className="top-blur"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,12 +1,7 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
content: [
|
content: ["./src/**/*.{ts,tsx}"],
|
||||||
'./pages/**/*.{ts,tsx}',
|
|
||||||
'./components/**/*.{ts,tsx}',
|
|
||||||
'./app/**/*.{ts,tsx}',
|
|
||||||
'./src/**/*.{ts,tsx}',
|
|
||||||
],
|
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
|
@ -16,6 +11,10 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
fontFamily: {
|
||||||
|
body: "var(--body-font)",
|
||||||
|
display: "var(--display-font)",
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
border: "hsl(var(--border))",
|
border: "hsl(var(--border))",
|
||||||
input: "hsl(var(--input))",
|
input: "hsl(var(--input))",
|
||||||
|
@ -72,5 +71,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require("tailwindcss-animate")],
|
plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")],
|
||||||
}
|
};
|
||||||
|
|
Loading…
Reference in New Issue