├── .eslintrc.json
├── public
├── favicon.ico
├── assets
│ ├── CV.pdf
│ ├── atzinescandia.png
│ ├── devfolio-banner.png
│ ├── send.svg
│ ├── linkedin.svg
│ ├── insta.svg
│ ├── download.svg
│ ├── link.svg
│ ├── web.svg
│ └── git.svg
└── logo.svg
├── next.config.js
├── postcss.config.js
├── lib
└── utils.ts
├── components.json
├── .gitignore
├── components
├── ui
│ ├── Socials.tsx
│ ├── Reveal.tsx
│ ├── DownloadCV.tsx
│ ├── FloatingBar.tsx
│ ├── Button.tsx
│ ├── Spotlight.tsx
│ ├── NavBar.tsx
│ ├── Sparkle.tsx
│ └── BentoGrid.tsx
├── Projects.tsx
├── Contact.tsx
├── Footer.tsx
├── Hero.tsx
├── Experience.tsx
└── About.tsx
├── tsconfig.json
├── app
├── page.tsx
├── globals.css
└── layout.tsx
├── package.json
├── tailwind.config.ts
├── README.md
└── data
└── index.ts
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atzin-escandia/devfolio/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/assets/CV.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atzin-escandia/devfolio/HEAD/public/assets/CV.pdf
--------------------------------------------------------------------------------
/public/assets/atzinescandia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atzin-escandia/devfolio/HEAD/public/assets/atzinescandia.png
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {};
3 |
4 | module.exports = nextConfig;
5 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/public/assets/devfolio-banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atzin-escandia/devfolio/HEAD/public/assets/devfolio-banner.png
--------------------------------------------------------------------------------
/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { type ClassValue, clsx } from "clsx";
2 | import { twMerge } from "tailwind-merge";
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs));
6 | }
7 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "default",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "tailwind.config.ts",
8 | "css": "app/globals.css",
9 | "baseColor": "zinc",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils"
16 | }
17 | }
--------------------------------------------------------------------------------
/public/assets/send.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/assets/linkedin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/assets/insta.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/assets/download.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/components/ui/Socials.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 | import { socialMedia } from "@/data";
5 |
6 | export const Socials = (): JSX.Element => (
7 |
8 | {socialMedia.map(({ id, link, img }) => (
9 |
16 |
17 |
18 | ))}
19 |
20 | );
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": true,
7 | "noEmit": true,
8 | "esModuleInterop": true,
9 | "module": "esnext",
10 | "moduleResolution": "bundler",
11 | "resolveJsonModule": true,
12 | "isolatedModules": true,
13 | "jsx": "preserve",
14 | "incremental": true,
15 | "plugins": [
16 | {
17 | "name": "next"
18 | }
19 | ],
20 | "paths": {
21 | "@/*": ["./*"]
22 | }
23 | },
24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
25 | "exclude": ["node_modules"]
26 | }
27 |
--------------------------------------------------------------------------------
/public/assets/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/components/ui/Reveal.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { ReactNode, useRef } from 'react';
4 | import { motion } from 'framer-motion';
5 |
6 | interface RevealProps {
7 | children: ReactNode;
8 | className?: string;
9 | }
10 |
11 | const Reveal = ({ children, className = '' }: RevealProps) => {
12 | const ref = useRef(null);
13 |
14 | return (
15 |
16 |
22 | {children}
23 |
24 |
25 | );
26 | };
27 |
28 | export default Reveal;
29 |
--------------------------------------------------------------------------------
/components/ui/DownloadCV.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 | import Button from "./Button";
5 |
6 | interface DownloadCVProps {
7 | fileUrl: string;
8 | fileName: string;
9 | }
10 |
11 | const DownloadCV: React.FC = ({ fileUrl, fileName }) => {
12 | return (
13 |
16 | }
17 | position="right"
18 | handleClick={() => {
19 | const link = document.createElement("a");
20 | link.href = fileUrl;
21 | link.download = fileName;
22 | link.click();
23 | }}
24 | />
25 | );
26 | };
27 |
28 | export default DownloadCV;
29 |
--------------------------------------------------------------------------------
/components/Projects.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { projects } from "@/data";
4 | import { BentoGrid, BentoGridItem } from "./ui/BentoGrid";
5 | import Reveal from "./ui/Reveal";
6 |
7 | const Projects = () => {
8 | return (
9 |
10 |
11 |
12 | Recent{" "}
13 |
14 | projects.
15 |
16 |
17 |
18 | {projects.map((item, i) => (
19 |
23 | ))}
24 |
25 |
26 | );
27 | };
28 |
29 | export default Projects;
30 |
--------------------------------------------------------------------------------
/public/assets/web.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/assets/git.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import FloatingBar from "@/components/ui/FloatingBar";
4 | import Hero from "@/components/Hero";
5 | import About from "@/components/About";
6 | import Projects from "@/components/Projects";
7 | import Experience from "@/components/Experience";
8 | import Contact from "@/components/Contact";
9 | import Footer from "@/components/Footer";
10 | import NavBar from "@/components/ui/NavBar";
11 |
12 | const Home = () => {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 | };
31 |
32 | export default Home;
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "atzin-escandia-devfolio",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint",
10 | "deploy": "vercel --prod"
11 | },
12 | "dependencies": {
13 | "clsx": "^2.1.0",
14 | "framer-motion": "^11.0.25",
15 | "mini-svg-data-uri": "^1.4.4",
16 | "next": "14.1.4",
17 | "react": "^18",
18 | "react-dom": "^18",
19 | "tailwind-merge": "^2.2.2",
20 | "tailwindcss-animate": "^1.0.7",
21 | "vercel": "^34.0.0"
22 | },
23 | "devDependencies": {
24 | "@types/node": "^20",
25 | "@types/react": "^18",
26 | "@types/react-dom": "^18",
27 | "@types/react-lottie": "^1.2.10",
28 | "autoprefixer": "^10.0.1",
29 | "eslint": "^8",
30 | "eslint-config-next": "14.1.4",
31 | "postcss": "^8",
32 | "tailwindcss": "^3.3.0",
33 | "typescript": "^5"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | :root {
7 | --background: 0 0% 100%;
8 | --foreground: 350 15% 10%;
9 |
10 | --card: 0 0% 100%;
11 | --card-foreground: 350 15% 10%;
12 |
13 | --popover: 0 0% 100%;
14 | --popover-foreground: 350 15% 10%;
15 |
16 | --primary: 350 65% 40%;
17 | --primary-foreground: 0 0% 98%;
18 |
19 | --secondary: 350 60% 95%;
20 | --secondary-foreground: 350 65% 40%;
21 | }
22 | }
23 |
24 | @layer base {
25 | * {
26 | @apply !scroll-smooth;
27 | }
28 | body {
29 | @apply text-white;
30 | }
31 | button {
32 | @apply active:outline-none;
33 | }
34 | }
35 |
36 | @layer utilities {
37 | h2 {
38 | @apply text-5xl sm:text-6xl md:text-8xl lg:text-9xl font-extrabold;
39 | }
40 | h3 {
41 | @apply text-4xl sm:text-5xl md:text-6xl text-center font-extrabold;
42 | }
43 | p{
44 | @apply text-sm sm:text-lg;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/components/ui/FloatingBar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 | import { motion, AnimatePresence } from "framer-motion";
5 | import { cn } from "@/lib/utils";
6 | import DownloadCV from "./DownloadCV";
7 | import { Socials } from "./Socials";
8 |
9 | const NAV_CONTAINER_CLASSES = cn(
10 | "flex fixed z-[5000] top-10 right-0 sm:gap-5 p-2 sm:px-5 sm:py-4 rounded-l-full border border-white/20"
11 | );
12 |
13 | const NAV_CONTAINER_STYLES: React.CSSProperties = {
14 | backgroundColor: "rgba(255, 255, 255, 0.1)",
15 | backdropFilter: "blur(10px)",
16 | };
17 |
18 | const FloatingBar = () => {
19 | return (
20 |
21 |
29 |
30 |
31 |
32 |
33 | );
34 | };
35 |
36 | export default FloatingBar;
37 |
--------------------------------------------------------------------------------
/components/ui/Button.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Button = ({
4 | title,
5 | icon,
6 | position,
7 | handleClick,
8 | otherClasses,
9 | }: {
10 | title: string;
11 | icon: React.ReactNode;
12 | position: string;
13 | handleClick?: () => void;
14 | otherClasses?: string;
15 | }) => {
16 | return (
17 |
21 |
22 |
26 | {position === "left" && icon}
27 |
28 | {title}
29 | {position === "right" && icon}
30 |
31 |
32 | );
33 | };
34 |
35 | export default Button;
36 |
--------------------------------------------------------------------------------
/components/Contact.tsx:
--------------------------------------------------------------------------------
1 | import Button from "./ui/Button";
2 | import Reveal from "./ui/Reveal";
3 |
4 | const Contact = () => {
5 | return (
6 |
36 | );
37 | };
38 |
39 | export default Contact;
40 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Poppins } from "next/font/google";
3 | import "./globals.css";
4 |
5 | const poppins = Poppins({ subsets: ["latin"], weight: ["100", "200", "400", "700", '900'] });
6 |
7 | export default function RootLayout({
8 | children,
9 | }: Readonly<{
10 | children: React.ReactNode;
11 | }>) {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 | {children}
19 |
20 |
21 | );
22 | }
23 |
24 |
25 | // Change this data with your own 🤭
26 | export const metadata: Metadata = {
27 | title: {
28 | default: 'Atzin Escandia ✷ Portfolio',
29 | template: '%s - Atzin Escandia',
30 | },
31 | description:
32 | 'A customizable portfolio template for frontend developers, created by Atzin Escandia. Showcase your skills, projects, and experience with a clean and modern design.',
33 | icons: {
34 | icon: './favicon.ico',
35 | },
36 | applicationName: 'Frontend Portfolio Template by Atzin Escandia',
37 | authors: [
38 | {
39 | name: 'Atzin Escandia',
40 | url: 'https://www.linkedin.com/in/atzin-escandia/',
41 | },
42 | ],
43 | generator: 'Next.js',
44 | referrer: 'origin',
45 | themeColor: '#120012',
46 | colorScheme: 'dark',
47 | viewport: 'width=device-width, initial-scale=1',
48 | creator: 'Atzin Escandia',
49 | publisher: 'Atzin Escandia',
50 | };
51 |
--------------------------------------------------------------------------------
/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | import { Socials } from "./ui/Socials";
2 |
3 | const Footer = () => {
4 | return (
5 |
38 | );
39 | };
40 |
41 | export default Footer;
42 |
--------------------------------------------------------------------------------
/components/ui/Spotlight.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from "@/lib/utils";
2 | import React from "react";
3 |
4 | type SpotlightProps = {
5 | className?: string;
6 | fill?: string;
7 | };
8 |
9 | export const Spotlight = ({ className, fill }: SpotlightProps) => {
10 | return (
11 |
20 |
21 |
30 |
31 |
32 |
41 |
42 |
48 |
52 |
53 |
54 |
55 | );
56 | };
57 |
--------------------------------------------------------------------------------
/components/Hero.tsx:
--------------------------------------------------------------------------------
1 | import Button from "./ui/Button";
2 | import Reveal from "./ui/Reveal";
3 | import { Spotlight } from "./ui/Spotlight";
4 |
5 | const Hero = () => {
6 | return (
7 |
8 |
9 |
13 |
17 |
18 |
19 |
20 |
21 |
22 | Hey, I'm {''}
23 |
24 | Atzin Escandia!
25 |
26 |
27 |
28 |
29 | I'm a Software Developer
30 |
31 |
32 | A designer, developer and fitness enthusiast who spends way too much time creating websites that look cool. If you're into tech, fitness, or just want to chat DM me - let's make your brand everyone's crush! 🍓
33 |
34 |
35 | }
38 | position="right"
39 | />
40 |
41 |
42 |
43 | );
44 | };
45 |
46 | export default Hero;
47 |
--------------------------------------------------------------------------------
/components/Experience.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { workExperience } from "@/data";
3 | import { Sparkle } from "./ui/Sparkle";
4 |
5 | const Experience = (): JSX.Element => (
6 |
7 |
8 | My{' '}
9 |
10 | experience.
11 |
12 |
13 |
14 |
15 | {workExperience.map(({ id, company, title, period, location, desc, skills }) => (
16 |
17 |
18 |
19 |
20 |
21 |
{company}
22 |
23 |
24 | {title}
25 |
26 |
27 |
28 |
29 |
30 |
{period}
31 |
{location}
32 |
33 |
34 |
{desc}
35 |
36 |
37 | {skills.map((skill) => (
38 |
42 | {skill}
43 |
44 | ))}
45 |
46 |
47 |
48 |
49 | ))}
50 |
51 |
52 | );
53 |
54 | export default Experience;
55 |
--------------------------------------------------------------------------------
/components/ui/NavBar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, { useEffect, useState } from "react";
4 | import Link from "next/link";
5 | import { cn } from "@/lib/utils";
6 | import { navItems } from "@/data";
7 |
8 | const NavBar = (): JSX.Element => {
9 | const [activeSection, setActiveSection] = useState("");
10 |
11 | useEffect(() => {
12 | const observer = new IntersectionObserver((entries) => {
13 | entries.forEach((entry) => {
14 | if (entry.isIntersecting) {
15 | const id = entry.target.getAttribute("id");
16 | if (id) setActiveSection(id);
17 | }
18 | });
19 | });
20 |
21 | document.querySelectorAll("section").forEach((section) => observer.observe(section));
22 |
23 | return () => observer.disconnect();
24 | }, []);
25 |
26 | return (
27 |
34 | {navItems.map(({ name, link }, index) => {
35 | const isActive = `#${activeSection}` === link;
36 |
37 | return (
38 |
46 |
54 | {name}
55 |
56 |
57 | );
58 | })}
59 |
60 | );
61 | };
62 |
63 | export default NavBar;
64 |
--------------------------------------------------------------------------------
/components/About.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Sparkle } from "./ui/Sparkle";
3 | import { myTechStack } from "@/data";
4 | import Reveal from "./ui/Reveal";
5 |
6 | const About = () => (
7 |
8 |
9 |
10 | About{' '}
11 |
12 | me.
13 |
14 |
15 |
16 |
17 |
21 |
22 | Hey! I'm Atzin, web designer, developer, fitness lover (& accidental content creator)
23 |
24 |
25 | My background in design and development gives me the tools to bring ideas to life, but my heart is in
26 | connecting with people, I love sharing my journey and what I've learned along the way.
27 |
28 |
29 | Got something in mind or just want to chat? Whether it's a new project or a fitness tip, I'd love to
30 | connect, don't be shy!
31 |
32 |
33 |
34 |
37 |
38 |
39 | My tech Stack!
40 |
41 |
42 |
43 |
44 | {myTechStack.map((skill) => (
45 |
49 | {skill}
50 |
51 | ))}
52 |
53 |
54 |
55 |
56 | );
57 |
58 | export default About;
59 |
--------------------------------------------------------------------------------
/components/ui/Sparkle.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, { useRef } from "react";
4 | import {
5 | motion,
6 | useAnimationFrame,
7 | useMotionTemplate,
8 | useMotionValue,
9 | useTransform,
10 | } from "framer-motion";
11 | import { cn } from "@/lib/utils";
12 |
13 | type SparkleProps = {
14 | children: React.ReactNode;
15 | as?: React.ElementType;
16 | duration?: number;
17 | className?: string;
18 | [key: string]: any;
19 | };
20 |
21 | export function Sparkle({
22 | children,
23 | as: Component = "button",
24 | duration = 2000,
25 | className = "",
26 | ...otherProps
27 | }: SparkleProps) {
28 |
29 | return (
30 |
34 |
43 |
49 | {children}
50 |
51 |
52 | );
53 | }
54 |
55 | type SparkleBoxProps = {
56 | children: React.ReactNode;
57 | duration?: number;
58 | rx?: string;
59 | ry?: string;
60 | [key: string]: any;
61 | };
62 |
63 | export const SparkleBox = ({
64 | children,
65 | duration = 2000,
66 | rx = "0%",
67 | ry = "0%",
68 | ...otherProps
69 | }: SparkleBoxProps) => {
70 | const pathRef = useRef(null);
71 | const progress = useMotionValue(0);
72 |
73 | useAnimationFrame((time) => {
74 | const length = pathRef.current?.getTotalLength();
75 | if (length) {
76 | const pxPerMs = length / duration;
77 | progress.set((time * pxPerMs) % length);
78 | }
79 | });
80 |
81 | const x = useTransform(progress, (val) =>
82 | pathRef.current?.getPointAtLength(val).x
83 | );
84 | const y = useTransform(progress, (val) =>
85 | pathRef.current?.getPointAtLength(val).y
86 | );
87 |
88 | const transform = useMotionTemplate`translateX(${x}px) translateY(${y}px) translateX(-50%) translateY(-50%)`;
89 |
90 | return (
91 | <>
92 |
98 |
99 |
100 |
108 | {children}
109 |
110 | >
111 | );
112 | };
113 |
--------------------------------------------------------------------------------
/components/ui/BentoGrid.tsx:
--------------------------------------------------------------------------------
1 | import { skills } from "@/data";
2 | import { cn } from "@/lib/utils";
3 |
4 | interface BentoGridProps {
5 | className?: string;
6 | children?: React.ReactNode;
7 | }
8 |
9 | export const BentoGrid: React.FC = ({ className, children }) => (
10 |
16 | {children}
17 |
18 | );
19 |
20 | interface BentoGridItemProps {
21 | className?: string;
22 | id: number;
23 | title?: string | React.ReactNode;
24 | description?: string | React.ReactNode;
25 | link?: string;
26 | github?: string;
27 | img?: string;
28 | titleClassName?: string;
29 | }
30 |
31 |
32 | export const BentoGridItem: React.FC = ({
33 | className,
34 | id,
35 | title,
36 | description,
37 | link,
38 | github,
39 | img,
40 | titleClassName,
41 | }) => (
42 |
48 |
49 | {img && (
50 |
51 |
56 |
57 | )}
58 |
59 |
60 |
61 |
67 |
68 |
99 |
100 |
101 |
{title}
102 |
103 | {description}
104 |
105 |
106 |
107 | {skills.map((skill) => (
108 |
112 | {skill}
113 |
114 | ))}
115 |
116 |
117 |
118 |
119 |
120 |
121 | );
122 |
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const svgToDataUri = require("mini-svg-data-uri");
4 |
5 | const {
6 | default: flattenColorPalette,
7 | } = require("tailwindcss/lib/util/flattenColorPalette");
8 |
9 | const config = {
10 | content: [
11 | "./pages/**/*.{ts,tsx}",
12 | "./components/**/*.{ts,tsx}",
13 | "./app/**/*.{ts,tsx}",
14 | "./src/**/*.{ts,tsx}",
15 | "./data/**/*.{ts,tsx}",
16 | ],
17 | prefix: "",
18 | theme: {
19 | container: {
20 | center: true,
21 | padding: "2rem",
22 | screens: {
23 | "2xl": "1400px",
24 | },
25 | },
26 | extend: {
27 | colors: {
28 | black: {
29 | DEFAULT: "#000",
30 | 100: "#000319",
31 | 200: "rgba(17, 25, 40, 0.75)",
32 | 300: "rgba(255, 255, 255, 0.125)",
33 | },
34 | white: {
35 | DEFAULT: "#FFF",
36 | 100: "#BEC1DD",
37 | 200: "#C1C2D3",
38 | },
39 | blue: {
40 | "100": "#E4ECFF",
41 | },
42 | purple: "#9B4D96",
43 | ring: "hsl(var(--ring))",
44 | background: "hsl(var(--background))",
45 | foreground: "hsl(var(--foreground))",
46 | primary: {
47 | DEFAULT: "hsl(var(--primary))",
48 | foreground: "hsl(var(--primary-foreground))",
49 | },
50 | secondary: {
51 | DEFAULT: "hsl(var(--secondary))",
52 | foreground: "hsl(var(--secondary-foreground))",
53 | },
54 | },
55 | keyframes: {
56 | spotlight: {
57 | "0%": {
58 | opacity: "0",
59 | transform: "translate(-72%, -62%) scale(0.5)",
60 | },
61 | "100%": {
62 | opacity: "1",
63 | transform: "translate(-50%,-40%) scale(1)",
64 | },
65 | },
66 | scroll: {
67 | to: {
68 | transform: "translate(calc(-50% - 0.5rem))",
69 | },
70 | },
71 | },
72 | animation: {
73 | "accordion-down": "accordion-down 0.2s ease-out",
74 | "accordion-up": "accordion-up 0.2s ease-out",
75 | spotlight: "spotlight 2s ease .75s 1 forwards",
76 | scroll:
77 | "scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite",
78 | },
79 | },
80 | },
81 | plugins: [
82 | require("tailwindcss-animate"),
83 | addVariablesForColors,
84 | function ({ matchUtilities, theme }: any) {
85 | matchUtilities(
86 | {
87 | "bg-grid": (value: any) => ({
88 | backgroundImage: `url("${svgToDataUri(
89 | ` `
90 | )}")`,
91 | }),
92 | "bg-grid-small": (value: any) => ({
93 | backgroundImage: `url("${svgToDataUri(
94 | ` `
95 | )}")`,
96 | }),
97 | "bg-dot": (value: any) => ({
98 | backgroundImage: `url("${svgToDataUri(
99 | ` `
100 | )}")`,
101 | }),
102 | },
103 | { values: flattenColorPalette(theme("backgroundColor")), type: "color" }
104 | );
105 | },
106 | ],
107 | } satisfies Config;
108 |
109 | function addVariablesForColors({ addBase, theme }: any) {
110 | let allColors = flattenColorPalette(theme("colors"));
111 | let newVars = Object.fromEntries(
112 | Object.entries(allColors).map(([key, val]) => [`--${key}`, val])
113 | );
114 |
115 | addBase({
116 | ":root": newVars,
117 | });
118 | }
119 |
120 | export default config;
121 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
19 |
20 |
Atzin Escandia's Devfolio
21 |
A super easy, simple, and neon purple (pretty me) ready to create your developer portfolio. Because who has time for complicated setups?
22 |
23 |
24 | ## 📋 Table of Contents
25 |
26 | 1. 💡 [Why This Project?](#why-this-project)
27 | 2. ⚙️ [Tech Stack](#tech-stack)
28 | 3. 🛠️ [Features](#features)
29 | 4. 🚀 [Getting Started](#getting-started)
30 | 5. 🌟 [Portfolio Inspiration](#portfolio-inspiration)
31 | 6. 📝 [More Resources](#more-resources)
32 |
33 | ## 💡 Why This Project?
34 |
35 | Hey there, dev! 👋
36 |
37 | You know that feeling when you're ready to show off your skills but get overwhelmed trying to build the _perfect_ portfolio? I’ve been there. You start searching for the right design, the best tools, the _ideal_ way to present your awesomeness... only to get stuck in a rabbit hole.
38 |
39 | So, I thought: **why not create something that makes this super simple, fast, and, dare I say, fun?** This portfolio template is for developers who want to get their work online without spending days tweaking code and layouts.
40 |
41 | ## ⚙️ Tech Stack
42 |
43 | - **Next.js**: Because who doesn’t love fast, production-ready sites that _just work_?
44 | - **Framer Motion**: Transform your portfolio into an interactive experience with smooth animations.
45 | - **TailwindCSS**: The magic wand for styling without the headache.
46 | - **TypeScript**: Because you deserve to code with confidence and zero guesswork.
47 |
48 | ## 🛠️ Features
49 |
50 | ✨ **Responsive Design**: Your portfolio will look great on any device—bye-bye, broken layouts!
51 |
52 | 🎨 **Clean & Stylish UI**: Simple yet stunning—designed to let your work take center stage. No frills, just results.
53 |
54 | 💡 **Customization Made Easy**: Want to change colors, fonts, or content? Do it without pulling your hair out. Seriously.
55 |
56 | 🎬 **Smooth Animations**: Thanks to Framer Motion, your portfolio will glide and flip like a pro.
57 |
58 | 🔧 **Developer Friendly**: Built with devs in mind, using the best tools and practices. You'll feel right at home.
59 |
60 | 💌 **Easy Contact Section**: Let potential employers, collaborators, or even fans reach out. No need to complicate things!
61 |
62 | ## 🚀 Getting Started
63 |
64 | Ready to launch your portfolio? Follow these simple steps, and you’ll be live in a flash!
65 |
66 | ### Prerequisites
67 |
68 | Before you get started, make sure you have:
69 |
70 | - [Git](https://git-scm.com/) installed on your machine.
71 | - [Node.js](https://nodejs.org/) (and Yarn) to manage dependencies.
72 |
73 | ### Clone the Repository
74 |
75 | ```bash
76 | git clone https://github.com/atzinescandia/atzin-escandia-devfolio.git
77 | cd atzin-escandia-devfolio
78 | ```
79 |
80 | ### Install Dependencies
81 |
82 | Run this command to install all the necessary dependencies:
83 |
84 | ```bash
85 | yarn install
86 | ```
87 |
88 | ### Run the Development Server
89 |
90 | Once you’re all set, fire up the server with:
91 |
92 | ```bash
93 | yarn dev
94 | ```
95 |
96 | Now, head to [http://localhost:3000](http://localhost:3000) in your browser and _boom_, your portfolio is ready to shine!
97 |
98 | ## 🌟 Portfolio Inspiration
99 |
100 | Looking for some inspo? Check out these amazing portfolios made using this template!
101 |
102 | - [Atzin Escandia Portfolio](https://atzinescandia.dev) - My personal site, where I show off my journey as a web dev and showcase my projects.
103 | - [The Plum Up Purple Neon](https://vscodethemes.com/e/atzinescandia.theplumup/theplumup) - A collection of portfolios by talented devs around the globe.
104 |
105 | ## 📝 More Resources
106 |
107 | - [Next.js Docs](https://nextjs.org/docs) - For when you need to level up your Next.js skills.
108 | - [Framer Motion](https://www.framer.com/motion/) - Bring your animations to life!
109 | - [TailwindCSS Docs](https://tailwindcss.com/docs) - The most efficient way to style your projects without the fuss.
110 |
111 | ---
112 |
113 | Feel free to fork this repo, tweak it to your heart's content, and start showing off your work! If you’ve got any questions or want to contribute, don’t hesitate to open an issue or submit a pull request. I’m always up for some collaboration! 🎉
114 |
--------------------------------------------------------------------------------
/data/index.ts:
--------------------------------------------------------------------------------
1 | export const navItems = [
2 | { name: "About", link: "#about" },
3 | { name: "Projects", link: "#projects" },
4 | { name: "Experience", link: "#experience" },
5 | { name: "Contact", link: "#contact" },
6 | ];
7 |
8 | export const myTechStack = [
9 | "JavaScript (ES6+)",
10 | "React",
11 | "Next.js",
12 | "TypeScript",
13 | "Jest",
14 | "Cypress",
15 | "Storybook",
16 | "Performance Testing",
17 | "HTML",
18 | "CSS",
19 | "SCSS",
20 | "Tailwind",
21 | "ShadCn/UI",
22 | "Figma",
23 | "Framer",
24 | "Git",
25 | "TanStack Query",
26 | "CI/CD",
27 | "Jira",
28 | "Agile",
29 | ];
30 |
31 | export const projects = [
32 | {
33 | id: 1,
34 | title: "FitLife: Your Gym Buddy in Code",
35 | description:
36 | "What if your fitness app could help you design websites while tracking your push-ups? This is it. Built with love, sweat, and a bit of JavaScript magic!",
37 | className: "lg:col-span-3 md:col-span-6 md:row-span-4 lg:min-h-[60vh]",
38 | titleClassName: "justify-end",
39 | img: "https://i.pinimg.com/originals/be/f4/1a/bef41a7d5a877841bbf7d8f9f0d42f14.gif",
40 | github: "https://github.com/atzin-escandia",
41 | link: "https://www.instagram.com/atzinescandia",
42 | techs: [
43 | "JavaScript",
44 | "React",
45 | "NodeJS",
46 | "Express",
47 | "MongoDB",
48 | "Tailwind",
49 | ],
50 | },
51 | {
52 | id: 2,
53 | title: "Timezone Buddy: Never Miss a Workout",
54 | description:
55 | "You can’t train for a marathon if you're confused about timezones! Sync with your squad no matter where they are and never miss a coding session or a yoga flow.",
56 | className: "lg:col-span-2 md:col-span-3 md:row-span-2",
57 | titleClassName: "justify-start",
58 | img: "https://i.pinimg.com/originals/84/f6/d1/84f6d14f1f88d34d3956150d19060d3a.gif",
59 | github: "https://github.com/atzin-escandia",
60 | link: "https://www.threads.net/@atzinescandia",
61 | techs: ["JavaScript", "React", "NodeJS", "AWS", "GitHub", "Jira"],
62 | },
63 | {
64 | id: 3,
65 | title: "Code & Paint: A Creative Playground",
66 | description:
67 | "What if coding met art? This interactive web builder lets you design while you create. Whether you’re coding a landing page or painting a masterpiece, this is where your creativity comes to life.",
68 | className: "lg:col-span-2 md:col-span-3 md:row-span-2",
69 | titleClassName: "justify-center",
70 | img: "https://i.pinimg.com/originals/54/b5/24/54b52468335fd6eb935e330eb3197b25.gif",
71 | github: "https://github.com/atzin-escandia",
72 | link: "https://atzinescandia.dev",
73 | techs: ["TypeScript", "React", "NextJS", "CSS", "AWS", "GitHub"],
74 | },
75 | {
76 | id: 4,
77 | title: "JavaScript Quest: Level Up Your Code",
78 | description:
79 | "Time to put your JavaScript skills to the test in an RPG-style adventure. Solve puzzles, defeat bugs, and unlock pro tips as you level up to coding mastery.",
80 | className: "lg:col-span-2 md:col-span-3 md:row-span-1",
81 | titleClassName: "justify-start",
82 | img: "https://i.pinimg.com/736x/c7/de/01/c7de016c811fa5fae9d7120402f27645.jpg",
83 | github: "https://github.com/atzin-escandia",
84 | link: "https://atzinescandia.dev",
85 | techs: ["JavaScript", "NodeJS", "Express", "React", "Heroku", "GitHub"],
86 | },
87 | {
88 | id: 5,
89 | title: "JS Animation Magic: Making Transitions Dance",
90 | description:
91 | "No more boring fades or slides. Animate your website with smooth, interactive animations that will have users tapping their feet. It's magic, but with code!",
92 | className: "md:col-span-3 md:row-span-2",
93 | titleClassName: "justify-center md:justify-start lg:justify-center",
94 | img: "https://i.pinimg.com/736x/09/2e/25/092e252b5562c7e5eb576215c6d9db8d.jpg",
95 | github: "https://github.com/atzin-escandia",
96 | link: "https://atzinescandia.dev/about",
97 | techs: ["JavaScript", "CSS", "React", "Tailwind", "GitHub", "AWS"],
98 | },
99 | {
100 | id: 6,
101 | title: "Space Explorer App: Code Your Way Through the Cosmos",
102 | description:
103 | "Ever wanted to explore space? Now you can—without leaving your desk. Navigate through galaxies, discover planets, and learn about the universe, all while building your dream website.",
104 | className: "lg:col-span-2 md:col-span-3 md:row-span-1",
105 | img: "https://i.pinimg.com/originals/bf/c3/fb/bfc3fb764ff5f4d8d9ecb6da8544709c.gif",
106 | github: "https://github.com/atzin-escandia",
107 | link: "https://atzinescandia.com/contact",
108 | techs: ["JavaScript", "React", "NodeJS", "CSS", "NextJS", "GitHub"],
109 | },
110 | ];
111 |
112 | export const workExperience = [
113 | {
114 | id: 1,
115 | company: "LumoTech",
116 | title: "UX/UI Sorcerer",
117 | desc: "Transformed the user dashboard with a sleek design that boosted engagement by 35%. Optimized the onboarding flow to make new users feel like wizards on their first try.",
118 | className: "md:col-span-2",
119 | location: "Los Angeles",
120 | period: "2022 - Present",
121 | skills: [
122 | "Figma",
123 | "Sketch",
124 | "Prototyping",
125 | "User Testing",
126 | "Illustrator",
127 | "Adobe XD",
128 | ],
129 | },
130 | {
131 | id: 2,
132 | company: "PixelMinds",
133 | title: "Product Design Genius",
134 | desc: "Revamped the interface with intuitive controls, increasing user retention by 28%. Pioneered AR features for interactive learning experiences—because education should be fun and engaging.",
135 | className: "md:col-span-2",
136 | location: "San Francisco",
137 | period: "2020 - 2022",
138 | skills: [
139 | "Figma",
140 | "User Research",
141 | "Wireframing",
142 | "Prototyping",
143 | "Usability Testing",
144 | "CSS",
145 | ],
146 | },
147 | {
148 | id: 3,
149 | company: "DesignHub",
150 | title: "Design Systems Guru",
151 | desc: "Crafted design systems that were so organized they could be put in a museum. Pushed for consistent, user-friendly components that made developers’ lives easier.",
152 | className: "md:col-span-2",
153 | location: "Remote",
154 | period: "2016 - 2020",
155 | skills: [
156 | "Figma",
157 | "React",
158 | "Design Tokens",
159 | "Accessibility",
160 | "Storybook",
161 | "Collaboration",
162 | ],
163 | },
164 | ];
165 |
166 | export const socialMedia = [
167 | {
168 | id: 1,
169 | img: "assets/git.svg",
170 | link: "https://github.com/atzin-escandia",
171 | },
172 | {
173 | id: 2,
174 | img: "assets/linkedin.svg",
175 | link: "https://www.linkedin.com/in/atzin-escandia/",
176 | },
177 | {
178 | id: 3,
179 | img: "assets/web.svg",
180 | link: "https://atzinescandia.dev/",
181 | },
182 | {
183 | id: 3,
184 | img: "assets/insta.svg",
185 | link: "https://www.instagram.com/atzinescandia.dev/",
186 | },
187 | {
188 | id: 3,
189 | img: "assets/link.svg",
190 | link: "https://github.com/atzin-escandia/devfolio",
191 | },
192 | ];
193 |
194 | export const skills = [
195 | "TypeScript",
196 | "React",
197 | "Redux",
198 | "NodeJS",
199 | "NextJS",
200 | "Tailwind",
201 | ];
202 |
--------------------------------------------------------------------------------
/public/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------