├── postcss.config.js ├── vite.config.js ├── tailwind.config.js ├── src ├── index.css ├── main.jsx ├── components │ ├── Reel.jsx │ ├── ProjectCard.jsx │ ├── Navbar.jsx │ ├── Hero.jsx │ ├── FollowUs.jsx │ ├── Services.jsx │ ├── Philosophy.jsx │ ├── ContactDetails.jsx │ ├── Projects.jsx │ └── SocialMediaLinks.jsx ├── App.jsx └── assets │ └── react.svg ├── .gitignore ├── README.md ├── .eslintrc.cjs ├── package.json └── index.html /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | * { 6 | font-family: "Poppins", sans-serif; 7 | } 8 | 9 | #design { 10 | font-family: "Roboto Flex", sans-serif; 11 | font-style: italic; 12 | /* letter-spacing: 0.2rem; */ 13 | } -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /src/components/Reel.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Reel = () => { 4 | return ( 5 |
6 | 12 |
13 | ); 14 | }; 15 | 16 | export default Reel; 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/components/ProjectCard.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const ProjectCard = ({ title, url }) => { 4 | return ( 5 |
6 |
7 | 8 |
9 |

{title}

10 |
11 | ); 12 | }; 13 | 14 | export default ProjectCard; 15 | -------------------------------------------------------------------------------- /src/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { HiOutlineMenuAlt4 } from "react-icons/hi"; 3 | 4 | const Navbar = () => { 5 | return ( 6 |
7 | cuberto 8 | 9 |
10 | ) 11 | } 12 | 13 | export default Navbar; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ochi", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "framer-motion": "^11.3.19", 14 | "gsap": "^3.12.5", 15 | "locomotive-scroll": "^5.0.0-beta.13", 16 | "react": "^18.3.1", 17 | "react-dom": "^18.3.1", 18 | "react-icons": "^5.2.1" 19 | }, 20 | "devDependencies": { 21 | "@types/react": "^18.3.3", 22 | "@types/react-dom": "^18.3.0", 23 | "@vitejs/plugin-react": "^4.3.1", 24 | "autoprefixer": "^10.4.19", 25 | "eslint": "^8.57.0", 26 | "eslint-plugin-react": "^7.34.3", 27 | "eslint-plugin-react-hooks": "^4.6.2", 28 | "eslint-plugin-react-refresh": "^0.4.7", 29 | "postcss": "^8.4.40", 30 | "tailwindcss": "^3.4.7", 31 | "vite": "^5.3.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/components/Hero.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Hero = () => { 4 | return ( 5 |
6 |
We are a digital
7 |
8 |
9 | 15 |
16 |
17 | 21 |  design  22 | 23 | and 24 |
25 |
26 |
motion agency
27 |
28 | ); 29 | }; 30 | 31 | export default Hero; 32 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import Navbar from "./components/Navbar"; 3 | import Hero from "./components/Hero"; 4 | import Reel from "./components/Reel"; 5 | import Services from "./components/Services"; 6 | import Projects from "./components/Projects"; 7 | import Philosophy from "./components/Philosophy"; 8 | import FollowUs from "./components/FollowUs"; 9 | import SocialMediaLinks from "./components/SocialMediaLinks"; 10 | import ContactDetails from "./components/ContactDetails"; 11 | 12 | const App = () => { 13 | 14 | useEffect(() => { 15 | (async () => { 16 | const LocomotiveScroll = (await import('locomotive-scroll')).default; 17 | const locomotiveScroll = new LocomotiveScroll(); 18 | })(); 19 | }, []); 20 | 21 | return ( 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | ); 34 | }; 35 | 36 | export default App; 37 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 17 | 18 | cuberto 19 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/components/FollowUs.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import { AiFillTwitterCircle } from "react-icons/ai"; 3 | import { LiaGithub } from "react-icons/lia"; 4 | import { ImLinkedin } from "react-icons/im"; 5 | import { motion, useScroll, useTransform } from "framer-motion"; 6 | 7 | const FollowUs = () => { 8 | const containerRef = useRef(null); 9 | const { scrollYProgress } = useScroll({ 10 | target: containerRef, 11 | offset: ["start end", "end start"], 12 | }); 13 | const x = useTransform(scrollYProgress, [0, 1], [0, -800]); 14 | 15 | return ( 16 |
20 | 24 | 25 | Follow Us{" "} 26 | 27 | 28 | 29 | Follow Us{" "} 30 | 31 | 32 | 33 | Follow Us 34 | 35 | Follow Us 36 | 37 |
38 | ); 39 | }; 40 | 41 | export default FollowUs; 42 | -------------------------------------------------------------------------------- /src/components/Services.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { motion } from "framer-motion"; 3 | 4 | const Services = () => { 5 | return ( 6 |
7 | 14 |
15 |

16 | Cuberto is a leading digital product{" "} 17 |
18 | agency focused on branding, UI/UX
19 | design, mobile, and web
20 | development. 21 |

22 | 28 | 36 | How we work 37 | 38 | 46 | How we work 47 | 48 | 49 |
50 |
51 | ); 52 | }; 53 | 54 | export default Services; 55 | -------------------------------------------------------------------------------- /src/components/Philosophy.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Philosophy = () => { 4 | return ( 5 |
6 |
7 |

Our

8 |

12 | philosophy 13 |

14 |
15 |
16 | 23 |
24 |

25 | In our team, developers work alongside   26 |
27 | designers, strategists and analysts.{" "} 28 |
29 | Cuberto doesn't do cookie-cutter
30 | solutions and we build products exactly{" "} 31 |
32 | as they were during the design phase, No   33 |
34 | short cuts or simplifications. 35 |

36 |

37 | We're driven by user-centered design{" "} 38 |
39 | that drives productivity and increases{" "} 40 |
41 | revenue. Our expertise and ingenuity are{" "} 42 |
43 | remarkable, yet we always strive to outdo{" "} 44 |
45 | and outperform our previous
46 | achievements. 47 |

48 |
49 |
50 |
51 | ); 52 | }; 53 | 54 | export default Philosophy; 55 | -------------------------------------------------------------------------------- /src/components/ContactDetails.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { motion } from "framer-motion"; 3 | 4 | const ContactDetails = () => { 5 | return ( 6 |
7 |
8 | 14 | 22 | vikasipar4@gmail.com 23 | 24 | 32 | vikasipar4@gmail.com 33 | 34 | 35 | 36 | 42 | 50 | +91 8329909096 51 | 52 | 60 | +91 8329909096 61 | 62 | 63 |
64 |
65 | ); 66 | }; 67 | 68 | export default ContactDetails; 69 | -------------------------------------------------------------------------------- /src/components/Projects.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ProjectCard from "./ProjectCard"; 3 | 4 | const Projects = () => { 5 | const leftColumnProjects = [ 6 | { 7 | title: "Punto Pago", 8 | url: "https://cdn.cuberto.com/cb/projects/puntopago/cover.mp4", 9 | }, 10 | { 11 | title: "Riyadh", 12 | url: "https://cdn.cuberto.com/cb/projects/riyadh/cover.mp4", 13 | }, 14 | { 15 | title: "Qvino", 16 | url: "https://cdn.cuberto.com/cb/projects/qvino/cover.mp4", 17 | }, 18 | { 19 | title: "Zelt", 20 | url: "https://cdn.cuberto.com/cb/projects/zelt/cover.mp4", 21 | }, 22 | { 23 | title: "Cisco", 24 | url: "https://cdn.cuberto.com/cb/projects/cisco/cover.mp4", 25 | } 26 | ]; 27 | 28 | const rightColumnProjects = [ 29 | { 30 | title: "Kelvin Zero", 31 | url: "https://cdn.cuberto.com/cb/projects/kzero/cover.mp4?2", 32 | }, 33 | { 34 | title: "Magma", 35 | url: "https://cdn.cuberto.com/cb/projects/magma/cover.mp4", 36 | }, 37 | { 38 | title: "Flipaclip", 39 | url: "https://cdn.cuberto.com/cb/projects/flipaclip/cover.mp4", 40 | }, 41 | { 42 | title: "Potion", 43 | url: "https://cdn.cuberto.com/cb/projects/potion/cover.mp4", 44 | }, 45 | { 46 | title: "Ferrumpipe", 47 | url: "https://cdn.cuberto.com/cb/projects/ferrumpipe/cover.mp4", 48 | } 49 | ]; 50 | 51 | return ( 52 |
53 |
54 |
Featured
55 |
56 |
57 | 64 |
65 |
66 | 70 |  projects 71 | 72 |
73 |
74 |
75 |
76 |
77 | {leftColumnProjects.map((project) => ( 78 | 79 | ))} 80 |
81 |
82 | {rightColumnProjects.map((project) => ( 83 | 84 | ))} 85 |
86 |
87 |
88 | ); 89 | }; 90 | 91 | export default Projects; 92 | -------------------------------------------------------------------------------- /src/components/SocialMediaLinks.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef, useState } from "react"; 2 | import { MdOutlineArrowOutward } from "react-icons/md"; 3 | import gsap from "gsap"; 4 | import { motion, AnimatePresence } from "framer-motion"; 5 | 6 | const SocialMediaLinks = () => { 7 | const [hoveredLink, setHoveredLink] = useState(null); 8 | 9 | const textRefs = useRef([]); 10 | textRefs.current = []; 11 | 12 | let xPercent = 0; 13 | let direction = -1; 14 | 15 | const addToRefs = (el) => { 16 | if (el && !textRefs.current.includes(el)) { 17 | textRefs.current.push(el); 18 | } 19 | }; 20 | 21 | useEffect(() => { 22 | const animation = () => { 23 | if (xPercent <= -100) { 24 | xPercent = 0; 25 | } 26 | gsap.set(textRefs.current, { xPercent }); 27 | xPercent += 0.6 * direction; 28 | requestAnimationFrame(animation); 29 | }; 30 | 31 | requestAnimationFrame(animation); 32 | }, []); 33 | 34 | const socialLinks = [ 35 | { 36 | name: "Twitter", 37 | url: "https://x.com/vikas_ipar?t=xdfw_bSJLdFN8dykcCSWZw&s=08", 38 | }, 39 | { 40 | name: "LinkedIn", 41 | url: "https://www.linkedin.com/in/vikas-ipar/", 42 | }, 43 | { 44 | name: "GitHub", 45 | url: "https://github.com/vikasipar", 46 | }, 47 | { 48 | name: "Portfolio", 49 | url: "https://vikasipar.me", 50 | }, 51 | ]; 52 | 53 | return ( 54 |
55 |

56 | SOCIAL MEDIA AND CONTACTS 57 |

58 | {socialLinks.map((link, index) => ( 59 | 60 |
setHoveredLink(index)} 68 | onMouseLeave={() => setHoveredLink(null)} 69 | > 70 | {hoveredLink !== index ? ( 71 | 76 | {link.name} 77 | 78 | 79 | ) : ( 80 | 86 | {[...Array(8)].map((_, i) => ( 87 |
92 | {link.name} 93 | 94 |
95 | ))} 96 |
97 | )} 98 |
99 |
100 | ))} 101 |
102 | ); 103 | }; 104 | 105 | export default SocialMediaLinks; 106 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------