├── public └── favicon.ico ├── postcss.config.js ├── .gitignore ├── .eslintrc.js ├── app ├── utils.js ├── components │ ├── Sections │ │ ├── Photo │ │ │ ├── PhotoPreview.jsx │ │ │ ├── Border.jsx │ │ │ └── UploadPhoto.jsx │ │ ├── ColorPicker.jsx │ │ ├── UserDetails.jsx │ │ ├── Skills.jsx │ │ ├── Customization.jsx │ │ ├── Socials.jsx │ │ ├── Education.jsx │ │ └── Projects.jsx │ ├── ui │ │ ├── label.jsx │ │ ├── separator.jsx │ │ ├── textarea.jsx │ │ ├── input.jsx │ │ ├── toaster.jsx │ │ ├── slider.jsx │ │ ├── tooltip.jsx │ │ ├── popover.jsx │ │ ├── accordion.jsx │ │ ├── button.jsx │ │ ├── calendar.jsx │ │ ├── use-toast.ts │ │ └── toast.jsx │ ├── CustomInput │ │ └── CustomInput.jsx │ ├── TemplatePicker │ │ └── TemplatePicker.jsx │ ├── TemplateRender │ │ └── TemplateRender.jsx │ ├── DatePicker │ │ └── DatePicker.jsx │ └── Templates │ │ ├── ModernTemplate.jsx │ │ ├── CalmTemplate.jsx │ │ └── InitialTemplate.jsx ├── entry.client.jsx ├── tailwind.css ├── hooks │ └── useZoom.js ├── lib │ └── helpers.js ├── root.jsx ├── constants │ └── general.js ├── entry.server.jsx └── routes │ └── _index.jsx ├── components.json ├── remix.config.js ├── tsconfig.json ├── README.md ├── LICENSE ├── package.json ├── tailwind.config.js └── api └── metafile.server.json /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RawandDev/simple-resume-builder/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | .cache 4 | .env 5 | .vercel 6 | .output 7 | 8 | /build/ 9 | /public/build 10 | /api/index.js 11 | /api/index.js.map 12 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import('eslint').Linter.Config} */ 2 | module.exports = { 3 | extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], 4 | }; 5 | -------------------------------------------------------------------------------- /app/utils.js: -------------------------------------------------------------------------------- 1 | import { clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": false, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "app/tailwind.css", 9 | "baseColor": "slate", 10 | "cssVariables": false 11 | }, 12 | "aliases": { 13 | "components": "~/components", 14 | "utils": "~/utils" 15 | } 16 | } -------------------------------------------------------------------------------- /app/components/Sections/Photo/PhotoPreview.jsx: -------------------------------------------------------------------------------- 1 | function PhotoPreview({ selectedImage, border }) { 2 | return ( 3 | selectedImage && ( 4 | not found 12 | ) 13 | ); 14 | } 15 | 16 | export default PhotoPreview; 17 | -------------------------------------------------------------------------------- /remix.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@remix-run/dev').AppConfig} */ 2 | module.exports = { 3 | ignoredRouteFiles: ["**/.*"], 4 | // appDirectory: "app", 5 | // assetsBuildDirectory: "public/build", 6 | // publicPath: "/build/", 7 | serverModuleFormat: "cjs", 8 | future: { 9 | v2_dev: true, 10 | v2_errorBoundary: true, 11 | v2_headers: true, 12 | v2_meta: true, 13 | v2_normalizeFormMethod: true, 14 | v2_routeConvention: true, 15 | }, 16 | tailwind: true, 17 | postcss: true, 18 | }; 19 | -------------------------------------------------------------------------------- /app/components/ui/label.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as LabelPrimitive from "@radix-ui/react-label" 3 | import { cva } from "class-variance-authority"; 4 | 5 | import { cn } from "~/utils" 6 | 7 | const labelVariants = cva( 8 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 9 | ) 10 | 11 | const Label = React.forwardRef(({ className, ...props }, ref) => ( 12 | 13 | )) 14 | Label.displayName = LabelPrimitive.Root.displayName 15 | 16 | export { Label } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "lib": ["DOM", "DOM.Iterable", "ES2019"], 5 | "isolatedModules": true, 6 | "esModuleInterop": true, 7 | "jsx": "react-jsx", 8 | "moduleResolution": "node", 9 | "resolveJsonModule": true, 10 | "target": "ES2019", 11 | "strict": true, 12 | "allowJs": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "baseUrl": ".", 15 | "paths": { 16 | "~/*": ["./app/*"] 17 | }, 18 | 19 | // Remix takes care of building everything in `remix build`. 20 | "noEmit": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/entry.client.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * By default, Remix will handle hydrating your app on the client for you. 3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ 4 | * For more information, see https://remix.run/file-conventions/entry.client 5 | */ 6 | 7 | import { RemixBrowser } from "@remix-run/react"; 8 | import { startTransition, StrictMode } from "react"; 9 | import { hydrateRoot } from "react-dom/client"; 10 | 11 | startTransition(() => { 12 | hydrateRoot( 13 | document, 14 | 15 | 16 | 17 | ); 18 | }); 19 | -------------------------------------------------------------------------------- /app/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @media print { 6 | #container { 7 | size: a4; 8 | } 9 | } 10 | 11 | @media screen { 12 | #container { 13 | size: unset; 14 | max-width: 210mm; 15 | } 16 | } 17 | 18 | ::-webkit-scrollbar { 19 | width: 12px; 20 | } 21 | 22 | ::-webkit-scrollbar-track { 23 | background-color: rgb(220, 220, 220, 0.5); 24 | } 25 | 26 | ::-webkit-scrollbar-thumb { 27 | background-color: rgba(214, 214, 214); 28 | border-radius: 5px; 29 | } 30 | 31 | ::-webkit-scrollbar-thumb:hover { 32 | background-color: rgb(210, 210, 210); 33 | border-radius: 5px; 34 | } 35 | -------------------------------------------------------------------------------- /app/components/ui/separator.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as SeparatorPrimitive from "@radix-ui/react-separator" 3 | 4 | import { cn } from "~/utils" 5 | 6 | const Separator = React.forwardRef(( 7 | { className, orientation = "horizontal", decorative = true, ...props }, 8 | ref 9 | ) => ( 10 | 20 | )) 21 | Separator.displayName = SeparatorPrimitive.Root.displayName 22 | 23 | export { Separator } 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to the resume builder 2 | 3 | Simple yet elegant CV/Resume builder. Built with Remix + Shadcn/ui + Tailwindcss. 4 | 5 | Check the website here: https://simple-resume-builder.vercel.app 6 | 7 | 8 | ## Demo 9 | 10 | Here is a quick demo about the application. 11 | 12 | 13 | https://github.com/RawandDev/simple-resume-builder/assets/82733587/61f41ae6-eef9-4dec-9719-47a6534bef18 14 | 15 | 16 | 17 | 18 | 19 | ## Development 20 | 21 | To run your Remix app locally, make sure your project's local dependencies are installed: 22 | 23 | ```sh 24 | yarn 25 | ``` 26 | 27 | Afterwards, start the Remix development server like so: 28 | 29 | ```sh 30 | yarn dev 31 | ``` 32 | 33 | Open up [http://localhost:3000](http://localhost:3000) and you should be ready to go! 34 | -------------------------------------------------------------------------------- /app/components/ui/textarea.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "~/utils" 4 | 5 | const Textarea = React.forwardRef(({ className, ...props }, ref) => { 6 | return ( 7 | (