<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ManashAnand</title>
    <description>The latest articles on DEV Community by ManashAnand (@manash_anand).</description>
    <link>https://dev.to/manash_anand</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F946078%2Fdc91f784-5be3-4cb8-8756-c6cd88f5a59e.jpeg</url>
      <title>DEV Community: ManashAnand</title>
      <link>https://dev.to/manash_anand</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manash_anand"/>
    <language>en</language>
    <item>
      <title>Using Nextjs, Aceternity UI and Shadcn-UI all together</title>
      <dc:creator>ManashAnand</dc:creator>
      <pubDate>Fri, 22 Mar 2024 22:00:16 +0000</pubDate>
      <link>https://dev.to/manash_anand/using-nextjs-aceternity-ui-and-shadcn-ui-all-together-2dbn</link>
      <guid>https://dev.to/manash_anand/using-nextjs-aceternity-ui-and-shadcn-ui-all-together-2dbn</guid>
      <description>&lt;p&gt;Hey Folks,&lt;br&gt;
I am Manash Anand .&lt;br&gt;
Let’s came directly to the topic&lt;br&gt;
Here is my webapp hosted :- &lt;a href="https://aicarnival.vercel.app/"&gt;AI-Carnival&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
Here is github link :- &lt;a href="https://github.com/ManashAnand/aicarnival"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So , I was wondering how to make a cool looking webapp with next&lt;br&gt;
Two things came in my mind&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to use prebuilt components -&amp;gt; &lt;a href="https://ui.shadcn.com/docs/installation/next"&gt;Shadcn-ui&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;How to use cool looking components -&amp;gt; &lt;a href="https://ui.aceternity.com/"&gt;Aceternity UI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best part&lt;br&gt;
Both are made on top of tailwind which is compatible with Nextjs&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, first lets start with shadcn ui&lt;/strong&gt;&lt;br&gt;
Here are the commands&lt;br&gt;
( I’m using npm for my perference , you can use any npm ,yarn, pnpm ,bun also use command from official sites for better copy pasting here there are some restrictions)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app@latest my-app — typescript — tailwind — eslint

npx shadcn-ui@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will ask you some question , you decide whatever suits you better&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now let’s go for Aceternity UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;step 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i framer-motion clsx tailwind-merge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;( this will install framer-motion clsx and tailwind-merge )&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Framer Motion provides smooth animations&lt;/li&gt;
&lt;li&gt;clsx generates dynamic CSS class names&lt;/li&gt;
&lt;li&gt;tailwind-merge simplifies merging Tailwind CSS classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;step 2:&lt;/p&gt;

&lt;p&gt;Now some more dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i three three-globe @react-three/fiber @react-three/drei
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;( this packages are used to render different important package )&lt;/p&gt;

&lt;p&gt;step 3:&lt;/p&gt;

&lt;p&gt;Make a file in root level&lt;br&gt;
&lt;strong&gt;utils/cn.ts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;step 4:&lt;/p&gt;

&lt;p&gt;put this code into the cn.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ClassValue, clsx } from “clsx”;
import { twMerge } from “tailwind-merge”;

export function cn(…inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;step 5:&lt;/p&gt;

&lt;p&gt;copy this &lt;a href="https://gist.github.com/manuarora700/4f03b7767a9431f2589c14c47377328a"&gt;json file&lt;/a&gt; ( hover over it )&lt;/p&gt;

&lt;p&gt;step 5: copy the source code in components/ui/globe.tsx ( at root level )&lt;/p&gt;

&lt;p&gt;the source code is below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“use client”;
import { useEffect, useRef, useState } from “react”;
import { Color, Scene, Fog, PerspectiveCamera, Vector3 } from “three”;
import ThreeGlobe from “three-globe”;
import { useThree, Object3DNode, Canvas, extend } from “@react-three/fiber”;
import { OrbitControls } from “@react-three/drei”;
import countries from “@/data/globe.json”;
declare module “@react-three/fiber” {
interface ThreeElements {
threeGlobe: Object3DNode&amp;lt;ThreeGlobe, typeof ThreeGlobe&amp;gt;;
}
}

extend({ ThreeGlobe });

const RING_PROPAGATION_SPEED = 3;
const aspect = 1.2;
const cameraZ = 300;

type Position = {
order: number;
startLat: number;
startLng: number;
endLat: number;
endLng: number;
arcAlt: number;
color: string;
};

export type GlobeConfig = {
pointSize?: number;
globeColor?: string;
showAtmosphere?: boolean;
atmosphereColor?: string;
atmosphereAltitude?: number;
emissive?: string;
emissiveIntensity?: number;
shininess?: number;
polygonColor?: string;
ambientLight?: string;
directionalLeftLight?: string;
directionalTopLight?: string;
pointLight?: string;
arcTime?: number;
arcLength?: number;
rings?: number;
maxRings?: number;
initialPosition?: {
lat: number;
lng: number;
};
autoRotate?: boolean;
autoRotateSpeed?: number;
};

interface WorldProps {
globeConfig: GlobeConfig;
data: Position[];
}

let numbersOfRings = [0];

export function Globe({ globeConfig, data }: WorldProps) {
const [globeData, setGlobeData] = useState&amp;lt;
| {
size: number;
order: number;
color: (t: number) =&amp;gt; string;
lat: number;
lng: number;
}[]
| null
&amp;gt;(null);

const globeRef = useRef&amp;lt;ThreeGlobe | null&amp;gt;(null);

const defaultProps = {
pointSize: 1,
atmosphereColor: “#ffffff”,
showAtmosphere: true,
atmosphereAltitude: 0.1,
polygonColor: “rgba(255,255,255,0.7)”,
globeColor: “#1d072e”,
emissive: “#000000”,
emissiveIntensity: 0.1,
shininess: 0.9,
arcTime: 2000,
arcLength: 0.9,
rings: 1,
maxRings: 3,
…globeConfig,
};

useEffect(() =&amp;gt; {
if (globeRef.current) {
_buildData();
_buildMaterial();
}
}, [globeRef.current]);

const _buildMaterial = () =&amp;gt; {
if (!globeRef.current) return;

const globeMaterial = globeRef.current.globeMaterial() as unknown as {
color: Color;
emissive: Color;
emissiveIntensity: number;
shininess: number;
};
globeMaterial.color = new Color(globeConfig.globeColor);
globeMaterial.emissive = new Color(globeConfig.emissive);
globeMaterial.emissiveIntensity = globeConfig.emissiveIntensity || 0.1;
globeMaterial.shininess = globeConfig.shininess || 0.9;
};

const _buildData = () =&amp;gt; {
const arcs = data;
let points = [];
for (let i = 0; i &amp;lt; arcs.length; i++) {
const arc = arcs[i];
const rgb = hexToRgb(arc.color) as { r: number; g: number; b: number };
points.push({
size: defaultProps.pointSize,
order: arc.order,
color: (t: number) =&amp;gt; `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${1 — t})`,
lat: arc.startLat,
lng: arc.startLng,
});
points.push({
size: defaultProps.pointSize,
order: arc.order,
color: (t: number) =&amp;gt; `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${1 — t})`,
lat: arc.endLat,
lng: arc.endLng,
});
}

// remove duplicates for same lat and lng
const filteredPoints = points.filter(
(v, i, a) =&amp;gt;
a.findIndex((v2) =&amp;gt;
[“lat”, “lng”].every(
(k) =&amp;gt; v2[k as “lat” | “lng”] === v[k as “lat” | “lng”]
)
) === i
);

setGlobeData(filteredPoints);
};

useEffect(() =&amp;gt; {
if (globeRef.current &amp;amp;&amp;amp; globeData) {
globeRef.current
.hexPolygonsData(countries.features)
.hexPolygonResolution(3)
.hexPolygonMargin(0.7)
.showAtmosphere(defaultProps.showAtmosphere)
.atmosphereColor(defaultProps.atmosphereColor)
.atmosphereAltitude(defaultProps.atmosphereAltitude)
.hexPolygonColor((e) =&amp;gt; {
return defaultProps.polygonColor;
});
startAnimation();
}
}, [globeData]);

const startAnimation = () =&amp;gt; {
if (!globeRef.current || !globeData) return;

globeRef.current
.arcsData(data)
.arcStartLat((d) =&amp;gt; (d as { startLat: number }).startLat * 1)
.arcStartLng((d) =&amp;gt; (d as { startLng: number }).startLng * 1)
.arcEndLat((d) =&amp;gt; (d as { endLat: number }).endLat * 1)
.arcEndLng((d) =&amp;gt; (d as { endLng: number }).endLng * 1)
.arcColor((e: any) =&amp;gt; (e as { color: string }).color)
.arcAltitude((e) =&amp;gt; {
return (e as { arcAlt: number }).arcAlt * 1;
})
.arcStroke((e) =&amp;gt; {
return [0.32, 0.28, 0.3][Math.round(Math.random() * 2)];
})
.arcDashLength(defaultProps.arcLength)
.arcDashInitialGap((e) =&amp;gt; (e as { order: number }).order * 1)
.arcDashGap(15)
.arcDashAnimateTime((e) =&amp;gt; defaultProps.arcTime);

globeRef.current
.pointsData(data)
.pointColor((e) =&amp;gt; (e as { color: string }).color)
.pointsMerge(true)
.pointAltitude(0.0)
.pointRadius(2);

globeRef.current
.ringsData([])
.ringColor((e: any) =&amp;gt; (t: any) =&amp;gt; e.color(t))
.ringMaxRadius(defaultProps.maxRings)
.ringPropagationSpeed(RING_PROPAGATION_SPEED)
.ringRepeatPeriod(
(defaultProps.arcTime * defaultProps.arcLength) / defaultProps.rings
);
};

useEffect(() =&amp;gt; {
if (!globeRef.current || !globeData) return;

const interval = setInterval(() =&amp;gt; {
if (!globeRef.current || !globeData) return;
numbersOfRings = genRandomNumbers(
0,
data.length,
Math.floor((data.length * 4) / 5)
);

globeRef.current.ringsData(
globeData.filter((d, i) =&amp;gt; numbersOfRings.includes(i))
);
}, 2000);

return () =&amp;gt; {
clearInterval(interval);
};
}, [globeRef.current, globeData]);

return (
&amp;lt;&amp;gt;
&amp;lt;threeGlobe ref={globeRef} /&amp;gt;
&amp;lt;/&amp;gt;
);
}

export function WebGLRendererConfig() {
const { gl, size } = useThree();

useEffect(() =&amp;gt; {
gl.setPixelRatio(window.devicePixelRatio);
gl.setSize(size.width, size.height);
gl.setClearColor(0xffaaff, 0);
}, []);

return null;
}

export function World(props: WorldProps) {
const { globeConfig } = props;
const scene = new Scene();
scene.fog = new Fog(0xffffff, 400, 2000);
return (
&amp;lt;Canvas scene={scene} camera={new PerspectiveCamera(50, aspect, 180, 1800)}&amp;gt;
&amp;lt;WebGLRendererConfig /&amp;gt;
&amp;lt;ambientLight color={globeConfig.ambientLight} intensity={0.6} /&amp;gt;
&amp;lt;directionalLight
color={globeConfig.directionalLeftLight}
position={new Vector3(-400, 100, 400)}
/&amp;gt;
&amp;lt;directionalLight
color={globeConfig.directionalTopLight}
position={new Vector3(-200, 500, 200)}
/&amp;gt;
&amp;lt;pointLight
color={globeConfig.pointLight}
position={new Vector3(-200, 500, 200)}
intensity={0.8}
/&amp;gt;
&amp;lt;Globe {…props} /&amp;gt;
&amp;lt;OrbitControls
enablePan={false}
enableZoom={false}
minDistance={cameraZ}
maxDistance={cameraZ}
autoRotateSpeed={1}
autoRotate={true}
minPolarAngle={Math.PI / 3.5}
maxPolarAngle={Math.PI — Math.PI / 3}
/&amp;gt;
&amp;lt;/Canvas&amp;gt;
);
}

export function hexToRgb(hex: string) {
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});

var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
}

export function genRandomNumbers(min: number, max: number, count: number) {
const arr = [];
while (arr.length &amp;lt; count) {
const r = Math.floor(Math.random() * (max — min)) + min;
if (arr.indexOf(r) === -1) arr.push(r);
}

return arr;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And done everything work fine&lt;/p&gt;

&lt;p&gt;If you find something interesting and helpfull&lt;br&gt;
give my repo a star &lt;a href="https://github.com/ManashAnand/aicarnival"&gt;REPO_LINK&lt;/a&gt;&lt;br&gt;
You can follow me for interesting stuff&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/manash-anand-479812227/"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/manashanand2"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://manash-folio.netlify.app/"&gt;Portfolio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ManashAnand"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mail: &lt;a href="mailto:anandmanash321@gmail.com"&gt;anandmanash321@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am also a&lt;br&gt;
Client ( who can provide jobs/Intern/Gigs )&lt;/p&gt;

&lt;p&gt;Freelancer ( who will solve your problem )&lt;/p&gt;

&lt;p&gt;Looking for full time job role ( as I am a student 😄)&lt;/p&gt;

&lt;p&gt;Thanks for reading …&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>react</category>
    </item>
  </channel>
</rss>
