108 |
Featured Projects
} 17 | 18 |-
21 | {projects.map(project => (
22 |
32 | {description} 33 |
34 | 35 |38 | Table of Contents{' '} 39 | (Click to {tocValue ? 'Close' : 'Open'}) 40 |
41 |46 | {stacks.join(' / ')} 47 |
48 | 49 |55 | {description} 56 |
57 | 58 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
116 | Design & Developed by ❤️ 117 |
118 | -------------------------------------------------------------------------------- /src/lib/shadcn-ui.ts: -------------------------------------------------------------------------------- 1 | import animatePlugin from 'tailwindcss-animate' 2 | import plugin from 'tailwindcss/plugin' 3 | import {fontFamily} from 'tailwindcss/defaultTheme' 4 | import type {Config} from 'tailwindcss' 5 | 6 | const shadcnPlugin = plugin( 7 | function ({addBase}) { 8 | addBase({ 9 | ':root': { 10 | '--background': '240 10% 3.9%', 11 | '--foreground': '0 0% 98%', 12 | '--card': '240 10% 3.9%', 13 | '--card-foreground': '0 0% 98%', 14 | '--popover': '240 10% 3.9%', 15 | '--popover-foreground': '0 0% 98%', 16 | '--primary': '0 0% 98%', 17 | '--primary-foreground': '240 5.9% 10%', 18 | '--secondary': '240 3.7% 15.9%', 19 | '--secondary-foreground': '0 0% 98%', 20 | '--muted': '240 3.7% 15.9%', 21 | '--muted-foreground': '240 5% 64.9%', 22 | '--accent': '240 3.7% 15.9%', 23 | '--accent-foreground': '0 0% 98%', 24 | '--destructive': '0 62.8% 30.6%', 25 | '--destructive-foreground': '0 0% 98%', 26 | '--border': '240 3.7% 15.9%', 27 | '--input': '240 3.7% 15.9%', 28 | '--ring': '182.7 100.0% 35.5%', 29 | '--radius': '0.5rem', 30 | }, 31 | }), 32 | addBase({ 33 | '*': { 34 | '@apply border-border': {}, 35 | }, 36 | body: { 37 | '@apply bg-background text-foreground': {}, 38 | }, 39 | }) 40 | }, 41 | 42 | { 43 | theme: { 44 | container: { 45 | center: true, 46 | padding: '1rem', 47 | screens: { 48 | xl: '57rem', 49 | }, 50 | }, 51 | extend: { 52 | typography: { 53 | DEFAULT: { 54 | css: { 55 | maxWidth: '100ch', 56 | }, 57 | }, 58 | }, 59 | fontFamily: { 60 | sans: ['var(--font-sans)', ...fontFamily.sans], 61 | ubuntu: 'var(--font-ubuntu)', 62 | dank: 'var(--font-dank)', 63 | }, 64 | screens: { 65 | xs: '380px', 66 | sm: '500px', 67 | }, 68 | colors: { 69 | border: 'hsl(var(--border))', 70 | input: 'hsl(var(--input))', 71 | ring: 'hsl(var(--ring))', 72 | background: 'hsl(var(--background))', 73 | foreground: 'hsl(var(--foreground))', 74 | primary: { 75 | DEFAULT: 'hsl(var(--primary))', 76 | foreground: 'hsl(var(--primary-foreground))', 77 | }, 78 | secondary: { 79 | DEFAULT: 'hsl(var(--secondary))', 80 | foreground: 'hsl(var(--secondary-foreground))', 81 | }, 82 | destructive: { 83 | DEFAULT: 'hsl(var(--destructive))', 84 | foreground: 'hsl(var(--destructive-foreground))', 85 | }, 86 | muted: { 87 | DEFAULT: 'hsl(var(--muted))', 88 | foreground: 'hsl(var(--muted-foreground))', 89 | }, 90 | accent: { 91 | DEFAULT: 'hsl(var(--accent))', 92 | foreground: 'hsl(var(--accent-foreground))', 93 | }, 94 | popover: { 95 | DEFAULT: 'hsl(var(--popover))', 96 | foreground: 'hsl(var(--popover-foreground))', 97 | }, 98 | card: { 99 | DEFAULT: 'hsl(var(--card))', 100 | foreground: 'hsl(var(--card-foreground))', 101 | }, 102 | }, 103 | borderRadius: { 104 | lg: 'var(--radius)', 105 | md: 'calc(var(--radius) - 2px)', 106 | sm: 'calc(var(--radius) - 4px)', 107 | }, 108 | keyframes: { 109 | 'accordion-down': { 110 | from: {height: '0'}, 111 | to: {height: 'var(--radix-accordion-content-height)'}, 112 | }, 113 | 'accordion-up': { 114 | from: {height: 'var(--radix-accordion-content-height)'}, 115 | to: {height: '0'}, 116 | }, 117 | }, 118 | animation: { 119 | 'accordion-down': 'accordion-down 0.2s ease-out', 120 | 'accordion-up': 'accordion-up 0.2s ease-out', 121 | }, 122 | }, 123 | }, 124 | }, 125 | ) 126 | 127 | export const shadcnPreset = { 128 | prefix: '', 129 | darkMode: ['selector'], 130 | content: [], 131 | plugins: [animatePlugin, shadcnPlugin], 132 | } satisfies Config 133 | -------------------------------------------------------------------------------- /src/components/about-section.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import {useEffect, useRef} from 'react' 3 | import {annotate, annotationGroup} from 'rough-notation' 4 | import { 5 | RoughAnnotationConfig, 6 | RoughAnnotationGroup, 7 | } from 'rough-notation/lib/model' 8 | 9 | import config from '~/config' 10 | import {useMediaQuery} from '~/hooks' 11 | import {cn} from '~/lib/utils' 12 | import {typo} from './ui/typograpghy' 13 | import Image from 'next/image' 14 | import dubaiCon from '~/assets/images/f-dubai-police.webp' 15 | import {annotationsConfig} from '~/constants/anime' 16 | 17 | const AboutSection = () => { 18 | const isSmallDevice = useMediaQuery('(max-width: 500px)') 19 | const annotationRefs = annotationsConfig.map(() => 20 | // eslint-disable-next-line react-hooks/rules-of-hooks 21 | useRef51 | Experienced self-taught developer with over{' '} 52 | 53 | 7+ years 54 | {' '} 55 | of crafting advanced SaaS products and B2B solutions, specializing in 56 | transforming imaginative designs into robust, scalable web solutions 57 | that set new standards. 58 |
59 | 60 |61 | I Love building tools that are{' '} 62 | 63 | user friendly, simple 64 | {' '} 65 | and{' '} 66 | 67 | delightful 68 | 69 | . 70 |
71 | 72 |73 | Through these experiences, I had the opportunity to work with both 74 | small and large companies, as well as specialized and cross-functional 75 | teams across different time zones & developed a working style that 76 | prioritizes{' '} 77 | 78 | flexibility, clarity 79 | {' '} 80 | and{' '} 81 | 82 | collaboration. 83 | 84 |
85 | 86 |89 | I'm currently looking for a new role as a developer.{' '} 90 | } 92 | href={`mailto:${config.social.email}`} 93 | aria-label="Hire me" 94 | className="text-ring el-focus-styles" 95 | > 96 | Hire me? 97 | 98 |
99 |
39 | If you have any inquiries, please feel free to reach out. You can contact us via email
40 | at{' '}
41 |
158 | {body} 159 |
160 | ) 161 | }) 162 | FormMessage.displayName = 'FormMessage' 163 | 164 | export { 165 | useFormField, 166 | Form, 167 | FormItem, 168 | FormLabel, 169 | FormControl, 170 | FormDescription, 171 | FormMessage, 172 | FormField, 173 | } 174 | -------------------------------------------------------------------------------- /src/components/ui/sheet.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as SheetPrimitive from "@radix-ui/react-dialog" 5 | import { cva, type VariantProps } from "class-variance-authority" 6 | import { X } from "lucide-react" 7 | 8 | import { cn } from "~/lib/utils" 9 | 10 | const Sheet = SheetPrimitive.Root 11 | 12 | const SheetTrigger = SheetPrimitive.Trigger 13 | 14 | const SheetClose = SheetPrimitive.Close 15 | 16 | const SheetPortal = SheetPrimitive.Portal 17 | 18 | const SheetOverlay = React.forwardRef< 19 | React.ElementRefInternal Server Error
104 | 105 |106 | {error?.message} 107 |
108 | 109 |97 | This page doesn't exist 98 |
99 | 100 |101 | Oops! It seems like you've stumbled upon a page that doesn't 102 | exist Don't worry, even the best of us get lost sometimes. Feel 103 | free to navigate back to Home or contact us if you need help 104 |
105 | 106 |