├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── app ├── api │ └── hello │ │ └── route.ts ├── error.tsx ├── favicon.ico ├── globals.css ├── layout.tsx ├── not-found.tsx ├── page.tsx └── providers.tsx ├── lib └── className.ts ├── next-env.d.ts ├── next.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public ├── fonts │ └── inter-var-latin.woff2 ├── robots.txt └── static │ └── favicons │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-270x270.png │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── styles └── globals.css ├── tailwind.config.js ├── tsconfig.json └── ui ├── AnimateEnter.tsx ├── ExternalLink.tsx ├── Flashcard.tsx ├── Footer.tsx └── Icons.tsx /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [*.json] 16 | indent_size = 2 -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | dist/ 3 | pnpm-lock.yaml 4 | .contentlayer/ 5 | data/ 6 | node_modules/ 7 | .next/ 8 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | node: true, 6 | }, 7 | extends: [ 8 | 'eslint:recommended', 9 | 'plugin:@typescript-eslint/recommended', 10 | 'plugin:import/errors', 11 | 'plugin:import/typescript', 12 | 'plugin:react-hooks/recommended', 13 | 'plugin:react/recommended', 14 | 'next/core-web-vitals', 15 | ], 16 | overrides: [ 17 | { 18 | files: ['**/*.ts'], 19 | rules: { 20 | 'react/display-name': 0, 21 | }, 22 | }, 23 | ], 24 | parser: '@typescript-eslint/parser', 25 | parserOptions: { 26 | ecmaFeatures: { 27 | jsx: true, 28 | }, 29 | }, 30 | plugins: [ 31 | '@typescript-eslint', 32 | 'import', 33 | 'react-hooks', 34 | 'react', 35 | 'sort-keys-fix', 36 | 'typescript-sort-keys', 37 | 'unicorn', 38 | ], 39 | rules: { 40 | '@typescript-eslint/ban-ts-comment': 0, 41 | '@typescript-eslint/no-empty-function': 0, 42 | '@typescript-eslint/no-namespace': 0, 43 | '@typescript-eslint/no-non-null-assertion': 0, 44 | '@typescript-eslint/no-unused-vars': ['error'], 45 | '@typescript-eslint/no-var-requires': 0, 46 | 'array-bracket-spacing': [2, 'never'], 47 | 'arrow-parens': [2, 'always'], 48 | 'arrow-spacing': 2, 49 | 'brace-style': [ 50 | 2, 51 | '1tbs', 52 | { 53 | allowSingleLine: true, 54 | }, 55 | ], 56 | 'eol-last': 2, 57 | // `import/default` and `import/namespace` are slow. 58 | 'import/default': 0, 59 | 'import/namespace': 0, 60 | 'import/no-duplicates': 2, 61 | 'import/no-extraneous-dependencies': [2], 62 | 'import/no-namespace': 2, 63 | 'import/order': 0, 64 | 'no-console': 0, 65 | 'no-const-assign': 2, 66 | 'no-extra-parens': [2, 'functions'], 67 | 'no-irregular-whitespace': 2, 68 | 'no-this-before-super': 2, 69 | 'no-unused-expressions': 2, 70 | 'no-unused-labels': 1, 71 | 'no-unused-vars': 0, 72 | 'no-var': 2, 73 | 'object-curly-spacing': 0, 74 | 'object-shorthand': 2, 75 | 'prefer-arrow-callback': 2, 76 | 'prefer-const': 2, 77 | 'react-hooks/exhaustive-deps': 2, 78 | 'react/jsx-sort-props': 2, 79 | 'react/prop-types': 0, 80 | 'react/react-in-jsx-scope': 0, 81 | semi: [2, 'always'], 82 | 'sort-keys-fix/sort-keys-fix': 2, 83 | 'space-before-blocks': 2, 84 | 'space-before-function-paren': [ 85 | 2, 86 | { anonymous: 'never', asyncArrow: 'always', named: 'never' }, 87 | ], 88 | 'typescript-sort-keys/interface': 2, 89 | 'typescript-sort-keys/string-enum': 2, 90 | 'unicorn/better-regex': 2, 91 | 'unicorn/catch-error-name': 2, 92 | 'unicorn/consistent-function-scoping': 2, 93 | 'unicorn/no-abusive-eslint-disable': 2, 94 | 'unicorn/no-hex-escape': 2, 95 | 'unicorn/no-useless-promise-resolve-reject': 2, 96 | 'unicorn/no-useless-spread': 2, 97 | 'unicorn/numeric-separators-style': 2, 98 | 'unicorn/prefer-array-flat-map': 2, 99 | 'unicorn/prefer-array-index-of': 2, 100 | 'unicorn/prefer-array-some': 2, 101 | 'unicorn/prefer-at': 2, 102 | 'unicorn/prefer-dom-node-append': 2, 103 | 'unicorn/prefer-native-coercion-functions': 2, 104 | 'unicorn/prefer-node-protocol': 2, 105 | 'unicorn/prefer-number-properties': 2, 106 | 'unicorn/prefer-optional-catch-binding': 2, 107 | 'unicorn/prefer-string-replace-all': 2, 108 | 'unicorn/prefer-string-slice': 2, 109 | 'unicorn/prefer-ternary': 2, 110 | 'unicorn/prefer-top-level-await': 2, 111 | 'unicorn/text-encoding-identifier-case': 2, 112 | }, 113 | settings: { 114 | 'import/parsers': { 115 | '@typescript-eslint/parser': ['.ts', '.tsx'], 116 | }, 117 | react: { 118 | version: '18.0.0', 119 | }, 120 | }, 121 | } 122 | -------------------------------------------------------------------------------- /.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 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 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 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | .cache 36 | package.json 37 | package-lock.json 38 | public 39 | node_modules 40 | out_functions 41 | out_publish 42 | .next 43 | yarn.lock 44 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "jsxSingleQuote": true, 4 | "tabWidth": 2, 5 | "printWidth": 80, 6 | "useTabs": false, 7 | "semi": false, 8 | "trailingComma": "es5", 9 | "bracketSpacing": true, 10 | "arrowParens": "avoid" 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "bradlc.vscode-tailwindcss", 4 | "dbaeumer.vscode-eslint", 5 | "EditorConfig.EditorConfig", 6 | "esbenp.prettier-vscode" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnPaste": false, 4 | "editor.formatOnSave": true, 5 | "prettier.requireConfig": true, 6 | "editor.quickSuggestions": { 7 | "strings": true 8 | }, 9 | "editor.codeActionsOnSave": { 10 | "source.fixAll.eslint": true 11 | }, 12 | "eslint.workingDirectories": [{ "mode": "auto" }], 13 | 14 | // https://github.com/antfu/vscode-file-nesting-config 15 | "explorer.experimental.fileNesting.enabled": true, 16 | "explorer.experimental.fileNesting.expand": false, 17 | "explorer.experimental.fileNesting.patterns": { 18 | ".gitignore": ".gitattributes, .gitmodules, .gitmessage, .mailmap, .git-blame*", 19 | "*.js": "$(capture).js.map, $(capture).min.js, $(capture).d.ts", 20 | "*.jsx": "$(capture).js", 21 | "*.ts": "$(capture).js, $(capture).*.ts", 22 | "*.tsx": "$(capture).ts", 23 | "index.d.ts": "*.d.ts", 24 | "shims.d.ts": "*.d.ts", 25 | "go.mod": ".air*, go.sum", 26 | "default.nix": "shell.nix", 27 | "flake.nix": "flake.lock", 28 | ".env": "*.env, .env*, env.d.ts", 29 | "dockerfile": ".dockerignore, dockerfile*", 30 | "package.json": ".browserslist*, .circleci*, .codecov, .commitlint*, .editorconfig, .eslint*, .flowconfig, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .markdownlint*, .mocha*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .stackblitz*, .stylelint*, .tazerc*, .textlint*, .travis*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, api-extractor.json, appveyor*, ava.config.*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, cypress.json, dangerfile*, dprint.json, grunt*, gulp*, jasmine.*, jenkins*, jest.config.*, jsconfig.*, karma*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, nx.*, package-lock.json, playwright.config.*, pm2.*, pnpm*, prettier*, pullapprove*, puppeteer.config.*, renovate*, rollup.config.*, stylelint*, tsconfig.*, tsdoc.*, tslint*, tsup.config.*, turbo*, typedoc*, vercel*, vetur.config.*, vitest.config.*, webpack.config.*, workspace.json, xo.config.*, yarn*", 31 | "rush.json": ".browserslist*, .circleci*, .codecov, .commitlint*, .editorconfig, .eslint*, .flowconfig, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .markdownlint*, .mocha*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .stackblitz*, .stylelint*, .tazerc*, .textlint*, .travis*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, api-extractor.json, appveyor*, ava.config.*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, cypress.json, dangerfile*, dprint.json, grunt*, gulp*, jasmine.*, jenkins*, jest.config.*, jsconfig.*, karma*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, nx.*, package-lock.json, playwright.config.*, pm2.*, pnpm*, prettier*, pullapprove*, puppeteer.config.*, renovate*, rollup.config.*, stylelint*, tsconfig.*, tsdoc.*, tslint*, tsup.config.*, turbo*, typedoc*, vercel*, vetur.config.*, vitest.config.*, webpack.config.*, workspace.json, xo.config.*, yarn*", 32 | "readme.*": "authors, backers.md, changelog*, citation*, code_of_conduct.md, codeowners, contributing.md, contributors, copying, credits, governance.md, history.md, license*, maintainers, readme*, security.md, sponsors.md", 33 | "cargo.toml": "cargo.lock, rust-toolchain.toml, rustfmt.toml", 34 | "gemfile": ".ruby-version, gemfile.lock", 35 | "vite.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env*, .htmlnanorc*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, cssnano.config.*, cypress.json, env.d.ts, htmlnanorc.*, index.html, jasmine.*, jest.config.*, jsconfig.*, karma*, playwright.config.*, postcss.config.*, puppeteer.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 36 | "vue.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env*, .htmlnanorc*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, cssnano.config.*, cypress.json, env.d.ts, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, playwright.config.*, postcss.config.*, puppeteer.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 37 | "nuxt.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env*, .htmlnanorc*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, cssnano.config.*, cypress.json, env.d.ts, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, playwright.config.*, postcss.config.*, puppeteer.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 38 | "next.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env*, .htmlnanorc*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, cssnano.config.*, cypress.json, env.d.ts, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, next-env.d.ts, playwright.config.*, postcss.config.*, puppeteer.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 39 | "svelte.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env*, .htmlnanorc*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, cssnano.config.*, cypress.json, env.d.ts, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, playwright.config.*, postcss.config.*, puppeteer.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 40 | "remix.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env*, .htmlnanorc*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, cssnano.config.*, cypress.json, env.d.ts, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, playwright.config.*, postcss.config.*, puppeteer.config.*, remix.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Cristi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ultimate Front-end Template 2 | 3 | ![preview](https://cdn.discordapp.com/attachments/797485737272541250/952208625806495815/image_5.png) 4 | 5 | > Most elements are taken from [my website](https://cretu.dev). 6 | 7 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fcristicretu%2Fts-next-tailwind-template) 8 | 9 | [Use as a CodeSandbox template](https://codesandbox.io/s/ts-next-tailwind-template-vbjvcr) 10 | 11 | ## Ingredients ✨: 12 | 13 | - NextJS 13 🚀 14 | - TailwindCSS 🦄 15 | - Typescript 🦺 16 | - Dark Mode Support 🌓 17 | - ESLint + Prettier Config 📂 18 | - Husky 🐶 19 | - Self-Hosted Inter Font ␊ 20 | 21 | ## Getting started 22 | 23 | 1. With 'use as template' repository 24 | ![preview](https://cdn.discordapp.com/attachments/797485737272541250/952208604386189332/Group_11.png) 25 | 26 | 2. Clone the project 27 | 28 | ```bash 29 | # http 30 | git clone https://github.com/cristicretu/ts-next-tailwind-template.git 31 | ``` 32 | 33 | ```bash 34 | # ssh 35 | git clone git@github.com:cristicretu/ts-next-tailwind-template.git 36 | ``` 37 | 38 | 3. With `create-next-app` 39 | 40 | ```bash 41 | npx create-next-app -e https://github.com/cristicretu/ts-next-tailwind-template project-name 42 | ``` 43 | 44 | * Tip: if you want to use the version prior to Next.js 13 with the app directory, use: 45 | ```bash 46 | npx create-next-app -e https://github.com/cristicretu/ts-next-tailwind-template/tree/1ac5d6dd4157ea3c7cc89f14fbfbf01ab0b495fc project-name 47 | ``` 48 | 49 | Install the required packages and run the template 50 | 51 | ```bash 52 | cd project-name 53 | npm install 54 | # yarn install 55 | # pnpm install 56 | ``` 57 | 58 | ## Included 59 | 60 | ### Custom classNames function 61 | > Under `/lib/classNames` 62 | 63 | ### Packages 64 | 65 | 1. Next-themes: An abstraction for themes in your Next.js app 66 | 2. react-use: react-hooks 67 | 3. Framer Motion: animation library 68 | 69 | ### Custom globals.css 70 | 71 | 1. custom underline 72 | 2. vercel navbar 73 | 3. removes firefox, edge and ie. bugs with overflows 74 | 75 | ### Absolute Imports 76 | 77 | ```tsx 78 | import TextField from '../../../ui/TextField.tsx' 79 | ``` 80 | 81 | changes to 82 | 83 | ```tsx 84 | import TextField from 'uis/TextField.tsx' 85 | ``` 86 | 87 | ### SEO optimization found in `Container.tsx` 88 | 89 | ### Folder structuring & organization 90 | 91 | > Under `/ui/` & `/public/` 92 | 93 | ### Self Hosted Inter Font 94 | 95 | > Under `/public/fonts/` 96 | 97 | ### 404 Page 98 | 99 | ### Favicons and more configs 100 | 101 | > Under `/public/static/favicons/` 102 | 103 | ![preview](https://cdn.discordapp.com/attachments/797485737272541250/952211815046197278/Frame_7.png) 104 | -------------------------------------------------------------------------------- /app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | export async function GET() { 2 | return new Response('Hello, Next.js!'); 3 | } 4 | -------------------------------------------------------------------------------- /app/error.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useEffect } from 'react'; 4 | 5 | export default function Error({ error }: { error: Error; reset: () => void }) { 6 | useEffect(() => { 7 | // Log the error to an error reporting service 8 | console.error(error); 9 | }, [error]); 10 | 11 | return ( 12 |
13 |

Oh no, something went wrong... maybe refresh?

14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zeus-Aphrodite/typeScript/4d47a61d2135ca0629647c98113fe807c4a542bd/app/favicon.ico -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | html { 7 | @apply max-h-screen antialiased; 8 | } 9 | 10 | * { 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | @apply m-0 p-0 font-sans; 16 | } 17 | 18 | pre::-webkit-scrollbar { 19 | display: none; 20 | } 21 | 22 | pre { 23 | -ms-overflow-style: none; /* IE and Edge */ 24 | scrollbar-width: none; /* Firefox */ 25 | } 26 | 27 | .capsize::before { 28 | content: ''; 29 | margin-bottom: -0.098em; 30 | display: table; 31 | } 32 | 33 | .capsize::after { 34 | content: ''; 35 | margin-top: -0.219em; 36 | display: table; 37 | } 38 | } 39 | 40 | @layer components { 41 | button { 42 | user-select: none; 43 | } 44 | 45 | button { 46 | -webkit-touch-callout: none; 47 | -webkit-user-select: none; 48 | -khtml-user-select: none; 49 | -moz-user-select: none; 50 | -ms-user-select: none; 51 | user-select: none; 52 | -webkit-tap-highlight-color: transparent; 53 | } 54 | } 55 | 56 | @layer utilities { 57 | .text-primary { 58 | @apply text-black dark:text-white; 59 | } 60 | 61 | .text-secondary { 62 | @apply text-black/80 dark:text-white/80; 63 | } 64 | 65 | .text-tertiary { 66 | @apply text-black/60 dark:text-white/60; 67 | } 68 | 69 | .text-quaternary { 70 | @apply text-black/40 dark:text-white/40; 71 | } 72 | 73 | .flip-card { 74 | background-color: transparent; 75 | perspective: 1000px; /* Remove this if you don't want the 3D effect */ 76 | } 77 | 78 | /* This container is needed to position the front and back side */ 79 | .flip-card-inner { 80 | position: relative; 81 | transition: transform 0.8s; 82 | transform-style: preserve-3d; 83 | } 84 | 85 | .rotate-y-180 { 86 | transform: rotateY(180deg); 87 | } 88 | 89 | /* .flip-card:hover .flip-card-inner { 90 | transform: rotateY(180deg); 91 | } */ 92 | 93 | .flip-card-front, 94 | .flip-card-back { 95 | position: absolute; 96 | width: 100%; 97 | height: 100%; 98 | -webkit-backface-visibility: hidden; /* Safari */ 99 | backface-visibility: hidden; 100 | } 101 | 102 | .flip-card-back { 103 | transform: rotateY(180deg); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import Footer from '../ui/Footer'; 2 | import './globals.css'; 3 | import Providers from './providers'; 4 | import { cn } from '@/lib/className'; 5 | import AnimateEnter from '@/ui/AnimateEnter'; 6 | import { Metadata } from 'next'; 7 | import { Inter } from 'next/font/google'; 8 | 9 | const inter = Inter({ subsets: ['latin'] }); 10 | 11 | export const metadata: Metadata = { 12 | authors: [{ name: 'Cristian Crețu', url: 'https://cretu.dev' }], 13 | category: 'design', 14 | creator: 'Cristian Crețu', 15 | description: 'Design Engineer.', 16 | icons: { 17 | apple: '/static/favicons/apple-touch-icon-180x180.png', 18 | icon: '/static/favicons/favicon-196x196.png', 19 | shortcut: '/favicon.ico', 20 | }, 21 | keywords: [ 22 | 'Next.js', 23 | 'React', 24 | 'JavaScript', 25 | 'TypeScript', 26 | 'TailwindCSS', 27 | 'Design', 28 | 'Engineering', 29 | 'Frontend', 30 | 'Developer', 31 | ], 32 | manifest: '/static/favicons/site.webmanifest', 33 | openGraph: { 34 | description: 'Design Engineer.', 35 | images: [ 36 | { 37 | alt: 'Cristian Crețu', 38 | height: 1080, 39 | url: 'https://cretu.dev/static/images/og.png', 40 | width: 1920, 41 | }, 42 | ], 43 | locale: 'en-US', 44 | siteName: 'Cristian Crețu', 45 | title: 'Cristian Crețu', 46 | type: 'website', 47 | url: 'https://cretu.dev', 48 | }, 49 | publisher: 'Cristian Crețu', 50 | robots: { 51 | follow: true, 52 | googleBot: { 53 | follow: true, 54 | index: true, 55 | 'max-image-preview': 'large', 56 | 'max-snippet': -1, 57 | 'max-video-preview': -1, 58 | }, 59 | index: true, 60 | }, 61 | themeColor: [ 62 | { color: 'white', media: '(prefers-color-scheme: light)' }, 63 | { color: '#171717', media: '(prefers-color-scheme: dark)' }, 64 | ], 65 | title: { 66 | default: 'Cristian Crețu', 67 | template: '%s | Cristian Crețu', 68 | }, 69 | twitter: { 70 | card: 'summary_large_image', 71 | site: '@cristicrtu', 72 | title: 'Cristian Crețu', 73 | }, 74 | verification: { 75 | google: 'fK4YqLAHjoaynXLF1e5gaPzDNOircgiYSgAwSXqr61o', 76 | }, 77 | }; 78 | 79 | export default function RootLayout({ 80 | children, 81 | }: { 82 | children: React.ReactNode 83 | }) { 84 | return ( 85 | 86 | 94 | 95 | 96 | 97 | <> 98 | {children} 99 |