├── public
├── favicon.ico
├── videos
│ └── video.mp4
└── images
│ ├── hero-image-01.jpg
│ ├── testimonial-01.jpg
│ ├── testimonial-02.jpg
│ ├── testimonial-03.jpg
│ ├── features-03-image-01.png
│ ├── features-03-image-02.png
│ └── features-03-image-03.png
├── app
├── api
│ └── hello
│ │ └── route.ts
├── (auth)
│ ├── layout.tsx
│ ├── reset-password
│ │ └── page.tsx
│ ├── signin
│ │ └── page.tsx
│ └── signup
│ │ └── page.tsx
├── (default)
│ ├── page.tsx
│ └── layout.tsx
├── css
│ ├── style.css
│ └── additional-styles
│ │ ├── toggle-switch.css
│ │ ├── utility-patterns.css
│ │ ├── range-slider.css
│ │ └── theme.css
└── layout.tsx
├── .vscode
└── settings.json
├── postcss.config.js
├── next.config.js
├── CHANGELOG.md
├── .gitignore
├── tsconfig.json
├── package.json
├── components
├── banner.tsx
├── ui
│ ├── header.tsx
│ ├── mobile-menu.tsx
│ └── footer.tsx
├── modal-video.tsx
├── testimonials.tsx
├── features.tsx
├── blocks.tsx
├── zigzag.tsx
├── hero.tsx
├── newsletter.tsx
└── page-illustration.tsx
├── tailwind.config.js
└── README.md
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/favicon.ico
--------------------------------------------------------------------------------
/public/videos/video.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/videos/video.mp4
--------------------------------------------------------------------------------
/app/api/hello/route.ts:
--------------------------------------------------------------------------------
1 | export async function GET(request: Request) {
2 | return new Response('Hello, Next.js!')
3 | }
4 |
--------------------------------------------------------------------------------
/public/images/hero-image-01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/images/hero-image-01.jpg
--------------------------------------------------------------------------------
/public/images/testimonial-01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/images/testimonial-01.jpg
--------------------------------------------------------------------------------
/public/images/testimonial-02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/images/testimonial-02.jpg
--------------------------------------------------------------------------------
/public/images/testimonial-03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/images/testimonial-03.jpg
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib",
3 | "typescript.enablePromptUseWorkspaceTsdk": true
4 | }
--------------------------------------------------------------------------------
/public/images/features-03-image-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/images/features-03-image-01.png
--------------------------------------------------------------------------------
/public/images/features-03-image-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/images/features-03-image-02.png
--------------------------------------------------------------------------------
/public/images/features-03-image-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frozen-dev71/open-react-template/main/public/images/features-03-image-03.png
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'postcss-import': {},
4 | tailwindcss: {},
5 | autoprefixer: {},
6 | },
7 | }
8 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | experimental: {
4 | appDir: true,
5 | },
6 | }
7 |
8 | module.exports = nextConfig
9 |
--------------------------------------------------------------------------------
/app/(auth)/layout.tsx:
--------------------------------------------------------------------------------
1 | import PageIllustration from '@/components/page-illustration'
2 |
3 | export default function AuthLayout({
4 | children,
5 | }: {
6 | children: React.ReactNode
7 | }) {
8 | return (
9 |
10 |
11 |
12 |
13 | {children}
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG.md
2 |
3 | ## [3.1.0] - 2023-05-07
4 |
5 | Modal video improvements
6 |
7 | ## [3.0.0] - 2023-04-12
8 |
9 | Conversion to Next.js
10 |
11 | ## [2.0.3] - 2023-03-28
12 |
13 | Fix video
14 |
15 | ## [2.0.2] - 2023-03-28
16 |
17 | Add self-hosted video
18 |
19 | ## [2.0.1] - 2023-02-16
20 |
21 | Remove header links
22 |
23 | ## [2.0.0] - 2023-02-16
24 |
25 | Replace Cruip CSS with Tailwind CSS
26 |
27 | ## [1.0.0] - 2020-04-07
28 |
29 | First release
--------------------------------------------------------------------------------
/app/(default)/page.tsx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Home - Open PRO',
3 | description: 'Page description',
4 | }
5 |
6 | import Hero from '@/components/hero'
7 | import Features from '@/components/features'
8 | import Newsletter from '@/components/newsletter'
9 | import Zigzag from '@/components/zigzag'
10 | import Testimonials from '@/components/testimonials'
11 |
12 | export default function Home() {
13 | return (
14 | <>
15 |
16 |
17 |
18 |
19 |
20 | >
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/.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
36 | next-env.d.ts
37 |
38 | # contentlayer
39 | .contentlayer
40 |
--------------------------------------------------------------------------------
/app/css/style.css:
--------------------------------------------------------------------------------
1 | @import 'tailwindcss/base';
2 | @import 'tailwindcss/components';
3 |
4 | /* Additional styles */
5 | @import 'additional-styles/utility-patterns.css';
6 | @import 'additional-styles/range-slider.css';
7 | @import 'additional-styles/toggle-switch.css';
8 | @import 'additional-styles/theme.css';
9 |
10 | @import 'tailwindcss/utilities';
11 |
12 | /* Additional Tailwind directives: https://tailwindcss.com/docs/functions-and-directives/#responsive */
13 | @layer utilities {
14 | .rtl {
15 | direction: rtl;
16 | }
17 | }
18 |
19 | /* See Alpine.js: https://github.com/alpinejs/alpine#x-cloak */
20 | [x-cloak=""] {
21 | display: none;
22 | }
23 |
--------------------------------------------------------------------------------
/app/css/additional-styles/toggle-switch.css:
--------------------------------------------------------------------------------
1 | /* Switch element */
2 | .form-switch {
3 | @apply relative select-none;
4 | width: 60px;
5 | }
6 |
7 | .form-switch label {
8 | @apply block overflow-hidden cursor-pointer h-8 rounded-full;
9 | }
10 |
11 | .form-switch label>span:first-child {
12 | @apply absolute block rounded-full;
13 | width: 28px;
14 | height: 28px;
15 | top: 2px;
16 | left: 2px;
17 | right: 50%;
18 | transition: all .15s ease-out;
19 | }
20 |
21 | .form-switch input[type="checkbox"]:checked+label {
22 | @apply bg-purple-600;
23 | }
24 |
25 | .form-switch input[type="checkbox"]:checked+label>span:first-child {
26 | left: 30px;
27 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "paths": {
23 | "@/*": ["./*"]
24 | }
25 | },
26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27 | "exclude": ["node_modules"]
28 | }
29 |
--------------------------------------------------------------------------------
/app/(default)/layout.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useEffect } from 'react'
4 |
5 | import AOS from 'aos'
6 | import 'aos/dist/aos.css'
7 |
8 | import PageIllustration from '@/components/page-illustration'
9 | import Footer from '@/components/ui/footer'
10 |
11 | export default function DefaultLayout({
12 | children,
13 | }: {
14 | children: React.ReactNode
15 | }) {
16 |
17 | useEffect(() => {
18 | AOS.init({
19 | once: true,
20 | disable: 'phone',
21 | duration: 600,
22 | easing: 'ease-out-sine',
23 | })
24 | })
25 |
26 | return (
27 | <>
28 |
29 |
30 |
31 |
32 | {children}
33 |
34 |
35 |
36 |
37 | >
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "open-pro-next",
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 | },
11 | "dependencies": {
12 | "@headlessui/react": "^1.7.13",
13 | "@types/node": "^18.15.11",
14 | "@types/react": "^18.0.34",
15 | "@types/react-dom": "18.0.11",
16 | "aos": "^3.0.0-beta.6",
17 | "next": "^13.3.0",
18 | "react": "18.2.0",
19 | "react-dom": "18.2.0",
20 | "typescript": "^5.0.4"
21 | },
22 | "devDependencies": {
23 | "@tailwindcss/forms": "^0.5.3",
24 | "@types/aos": "^3.0.4",
25 | "autoprefixer": "^10.4.14",
26 | "postcss": "^8.4.21",
27 | "tailwindcss": "^3.3.1"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import './css/style.css'
2 |
3 | import { Inter, Architects_Daughter } from 'next/font/google'
4 |
5 | import Header from '@/components/ui/header'
6 | import Banner from '@/components/banner'
7 |
8 | const inter = Inter({
9 | subsets: ['latin'],
10 | variable: '--font-inter',
11 | display: 'swap'
12 | })
13 |
14 | const architects_daughter = Architects_Daughter({
15 | subsets: ['latin'],
16 | variable: '--font-architects-daughter',
17 | weight: '400',
18 | display: 'swap'
19 | })
20 |
21 | export const metadata = {
22 | title: 'Create Next App',
23 | description: 'Generated by create next app',
24 | }
25 |
26 | export default function RootLayout({
27 | children,
28 | }: {
29 | children: React.ReactNode
30 | }) {
31 | return (
32 |
33 |
34 |
35 |
36 | {children}
37 |
38 |
39 |
40 |
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/app/css/additional-styles/utility-patterns.css:
--------------------------------------------------------------------------------
1 | /* Typography */
2 | .h1 {
3 | @apply text-4xl font-extrabold leading-tight tracking-tighter;
4 | }
5 |
6 | .h2 {
7 | @apply text-3xl font-extrabold leading-tight tracking-tighter;
8 | }
9 |
10 | .h3 {
11 | @apply text-3xl font-bold leading-tight;
12 | }
13 |
14 | .h4 {
15 | @apply text-2xl font-bold leading-snug tracking-tight;
16 | }
17 |
18 | @screen md {
19 | .h1 {
20 | @apply text-5xl;
21 | }
22 |
23 | .h2 {
24 | @apply text-4xl;
25 | }
26 | }
27 |
28 | /* Buttons */
29 | .btn,
30 | .btn-sm {
31 | @apply font-medium inline-flex items-center justify-center border border-transparent rounded-sm leading-snug transition duration-150 ease-in-out;
32 | }
33 |
34 | .btn {
35 | @apply px-8 py-3;
36 | }
37 |
38 | .btn-sm {
39 | @apply px-4 py-2;
40 | }
41 |
42 | /* Forms */
43 | .form-input,
44 | .form-textarea,
45 | .form-multiselect,
46 | .form-select,
47 | .form-checkbox,
48 | .form-radio {
49 | @apply bg-transparent border border-gray-700 focus:border-gray-500;
50 | }
51 |
52 | .form-input,
53 | .form-textarea,
54 | .form-multiselect,
55 | .form-select,
56 | .form-checkbox {
57 | @apply rounded-sm;
58 | }
59 |
60 | .form-input,
61 | .form-textarea,
62 | .form-multiselect,
63 | .form-select {
64 | @apply py-3 px-4;
65 | }
66 |
67 | .form-input,
68 | .form-textarea {
69 | @apply placeholder-gray-500;
70 | }
71 |
72 | .form-select {
73 | @apply pr-10;
74 | }
75 |
76 | .form-checkbox,
77 | .form-radio {
78 | @apply text-purple-600;
79 | }
--------------------------------------------------------------------------------
/components/banner.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useState } from 'react'
4 |
5 | export default function Banner() {
6 | const [bannerOpen, setBannerOpen] = useState(true)
7 |
8 | return (
9 | <>
10 | {bannerOpen && (
11 |
12 |
13 |
27 |
setBannerOpen(false)}>
28 | Close
29 |
30 |
31 |
32 |
33 |
34 |
35 | )}
36 | >
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/app/(auth)/reset-password/page.tsx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Reset Password - Open PRO',
3 | description: 'Page description',
4 | }
5 |
6 | import Link from 'next/link'
7 |
8 | export default function ResetPassword() {
9 | return (
10 |
11 |
12 |
13 |
14 | {/* Page header */}
15 |
16 |
Forgot your password?
17 |
We'll email you instructions on how to reset it.
18 |
19 |
20 | {/* Form */}
21 |
22 |
35 |
36 | Cancel
37 |
38 |
39 |
40 |
41 |
42 |
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | './app/**/*.{js,ts,jsx,tsx}',
5 | './pages/**/*.{js,ts,jsx,tsx}',
6 | './components/**/*.{js,ts,jsx,tsx}',
7 | ],
8 | theme: {
9 | extend: {
10 | colors: {
11 | gray: {
12 | 100: '#EBF1F5',
13 | 200: '#D9E3EA',
14 | 300: '#C5D2DC',
15 | 400: '#9BA9B4',
16 | 500: '#707D86',
17 | 600: '#55595F',
18 | 700: '#33363A',
19 | 800: '#25282C',
20 | 900: '#151719',
21 | },
22 | purple: {
23 | 100: '#F4F4FF',
24 | 200: '#E2E1FF',
25 | 300: '#CBCCFF',
26 | 400: '#ABABFF',
27 | 500: '#8D8DFF',
28 | 600: '#5D5DFF',
29 | 700: '#4B4ACF',
30 | 800: '#38379C',
31 | 900: '#262668',
32 | },
33 | },
34 | spacing: {
35 | '9/16': '56.25%',
36 | '3/4': '75%',
37 | '1/1': '100%',
38 | },
39 | fontFamily: {
40 | inter: ['var(--font-inter)', 'sans-serif'],
41 | 'architects-daughter': ['var(--font-architects-daughter)', 'sans-serif']
42 | },
43 | fontSize: {
44 | xs: '0.75rem',
45 | sm: '0.875rem',
46 | base: '1rem',
47 | lg: '1.125rem',
48 | xl: '1.25rem',
49 | '2xl': '1.5rem',
50 | '3xl': '2rem',
51 | '4xl': '2.5rem',
52 | '5xl': '3.25rem',
53 | '6xl': '4rem',
54 | },
55 | inset: {
56 | 'full': '100%',
57 | },
58 | letterSpacing: {
59 | tighter: '-0.02em',
60 | tight: '-0.01em',
61 | normal: '0',
62 | wide: '0.01em',
63 | wider: '0.02em',
64 | widest: '0.4em',
65 | },
66 | minWidth: {
67 | '10': '2.5rem',
68 | },
69 | scale: {
70 | '98': '.98'
71 | },
72 | },
73 | },
74 | plugins: [
75 | require('@tailwindcss/forms'),
76 | ],
77 | }
78 |
--------------------------------------------------------------------------------
/app/css/additional-styles/range-slider.css:
--------------------------------------------------------------------------------
1 | /* Range slider */
2 | :root {
3 | --range-thumb-size: 36px;
4 | }
5 |
6 | input[type=range] {
7 | appearance: none;
8 | background: #ccc;
9 | border-radius: 3px;
10 | height: 6px;
11 | margin-top: (--range-thumb-size - 6px) * 0.5;
12 | margin-bottom: (--range-thumb-size - 6px) * 0.5;
13 | --thumb-size: #{--range-thumb-size};
14 | }
15 |
16 | input[type=range]::-webkit-slider-thumb {
17 | appearance: none;
18 | -webkit-appearance: none;
19 | background-color: #000;
20 | background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fill-rule='nonzero'/%3E%3C/svg%3E");
21 | background-position: center;
22 | background-repeat: no-repeat;
23 | border: 0;
24 | border-radius: 50%;
25 | cursor: pointer;
26 | height: --range-thumb-size;
27 | width: --range-thumb-size;
28 | }
29 |
30 | input[type=range]::-moz-range-thumb {
31 | background-color: #000;
32 | background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fill-rule='nonzero'/%3E%3C/svg%3E");
33 | background-position: center;
34 | background-repeat: no-repeat;
35 | border: 0;
36 | border: none;
37 | border-radius: 50%;
38 | cursor: pointer;
39 | height: --range-thumb-size;
40 | width: --range-thumb-size;
41 | }
42 |
43 | input[type=range]::-ms-thumb {
44 | background-color: #000;
45 | background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fill-rule='nonzero'/%3E%3C/svg%3E");
46 | background-position: center;
47 | background-repeat: no-repeat;
48 | border: 0;
49 | border-radius: 50%;
50 | cursor: pointer;
51 | height: --range-thumb-size;
52 | width: --range-thumb-size;
53 | }
54 |
55 | input[type=range]::-moz-focus-outer {
56 | border: 0;
57 | }
--------------------------------------------------------------------------------
/components/ui/header.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import MobileMenu from './mobile-menu'
3 |
4 | export default function Header() {
5 | return (
6 |
7 |
8 |
9 | {/* Site branding */}
10 |
11 | {/* Logo */}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | {/* Desktop navigation */}
20 |
21 | {/* Desktop sign in links */}
22 |
23 |
24 |
28 | Sign in
29 |
30 |
31 |
32 |
33 | Sign up
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | )
45 | }
46 |
--------------------------------------------------------------------------------
/components/ui/mobile-menu.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useState, useRef, useEffect } from 'react'
4 | import Link from 'next/link'
5 |
6 | export default function MobileMenu() {
7 | const [mobileNavOpen, setMobileNavOpen] = useState(false)
8 |
9 | const trigger = useRef(null)
10 | const mobileNav = useRef(null)
11 |
12 | // close the mobile menu on click outside
13 | useEffect(() => {
14 | const clickHandler = ({ target }: { target: EventTarget | null }): void => {
15 | if (!mobileNav.current || !trigger.current) return;
16 | if (!mobileNavOpen || mobileNav.current.contains(target as Node) || trigger.current.contains(target as Node)) return;
17 | setMobileNavOpen(false)
18 | };
19 | document.addEventListener('click', clickHandler)
20 | return () => document.removeEventListener('click', clickHandler)
21 | })
22 |
23 | // close the mobile menu if the esc key is pressed
24 | useEffect(() => {
25 | const keyHandler = ({ keyCode }: { keyCode: number }): void => {
26 | if (!mobileNavOpen || keyCode !== 27) return;
27 | setMobileNavOpen(false)
28 | };
29 | document.addEventListener('keydown', keyHandler)
30 | return () => document.removeEventListener('keydown', keyHandler)
31 | })
32 |
33 | return (
34 |
35 | {/* Hamburger button */}
36 |
setMobileNavOpen(!mobileNavOpen)}
42 | >
43 | Menu
44 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | {/*Mobile navigation */}
56 |
62 |
63 |
64 | setMobileNavOpen(false)}>
65 | Sign in
66 |
67 |
68 |
69 | setMobileNavOpen(false)}
72 | >
73 | Sign up
74 |
75 |
76 |
77 |
78 |
79 | )
80 | }
81 |
--------------------------------------------------------------------------------
/components/modal-video.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useState, useRef, Fragment } from 'react'
4 | import type { StaticImageData } from 'next/image'
5 | import { Dialog, Transition } from '@headlessui/react'
6 | import Image from 'next/image'
7 |
8 | interface ModalVideoProps {
9 | thumb: StaticImageData
10 | thumbWidth: number
11 | thumbHeight: number
12 | thumbAlt: string
13 | video: string
14 | videoWidth: number
15 | videoHeight: number
16 | }
17 |
18 | export default function ModalVideo({
19 | thumb,
20 | thumbWidth,
21 | thumbHeight,
22 | thumbAlt,
23 | video,
24 | videoWidth,
25 | videoHeight,
26 | }: ModalVideoProps) {
27 | const [modalOpen, setModalOpen] = useState(false)
28 | const videoRef = useRef(null)
29 |
30 | return (
31 |
32 |
33 | {/* Video thumbnail */}
34 |
35 |
36 |
37 |
{ setModalOpen(true) }} aria-label="Watch the video">
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | {/* End: Video thumbnail */}
52 |
53 |
videoRef.current?.play()}>
54 | setModalOpen(false)}>
55 |
56 | {/* Modal backdrop */}
57 |
67 | {/* End: Modal backdrop */}
68 |
69 | {/* Modal dialog */}
70 |
79 |
80 |
81 |
82 |
83 | Your browser does not support the video tag.
84 |
85 |
86 |
87 |
88 | {/* End: Modal dialog */}
89 |
90 |
91 |
92 |
93 |
94 | )
95 | }
--------------------------------------------------------------------------------
/app/(auth)/signin/page.tsx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Sign In - Open PRO',
3 | description: 'Page description',
4 | }
5 |
6 | import Link from 'next/link'
7 |
8 | export default function SignIn() {
9 | return (
10 |
11 |
12 |
13 |
14 | {/* Page header */}
15 |
16 |
Welcome back. We exist to make entrepreneurship easier.
17 |
18 |
19 | {/* Form */}
20 |
21 |
34 |
35 |
36 |
Or, sign in with your email
37 |
38 |
39 |
69 |
70 | Don’t you have an account? Sign up
71 |
72 |
73 |
74 |
75 |
76 |
77 | )
78 | }
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Free React / Next.js landing page template
2 |
3 | 
4 |
5 | **Open** is a **free React / Next.js landing page template built with Tailwind CSS** for developers/makers who want to create a quick and professional landing page for their open source projects, SaaS products, online services, and more.
6 |
7 | Use it for whatever you want, and be sure to reach us out on [Twitter](https://twitter.com/Cruip_com) if you build anything cool/useful with it.
8 |
9 | Created and maintained with ❤️ by [Cruip.com](https://cruip.com).
10 |
11 | *Version 1.0.0 built with the Cruip CSS is available [here](https://github.com/cruip/open-react-template/releases/tag/1.0.0).*
12 | *Version 2.0.3 built with Tailwind CSS and React + Vite is available [here](https://github.com/cruip/open-react-template/releases/tag/2.0.3).*
13 |
14 | ## Live demo
15 |
16 | Check the live demo here 👉️ [https://open.cruip.com/](https://open.cruip.com/)
17 |
18 | ## Open PRO
19 |
20 | [](https://cruip.com/)
21 |
22 | ## Design files
23 |
24 | If you need the design files, you can download them from Figma's Community 👉 https://bit.ly/401KSUS
25 |
26 | ## Usage
27 |
28 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
29 |
30 | ### Getting Started
31 |
32 | First, run the development server:
33 |
34 | ```bash
35 | npm run dev
36 | # or
37 | yarn dev
38 | # or
39 | pnpm dev
40 | ```
41 |
42 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
43 |
44 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
45 |
46 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
47 |
48 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
49 |
50 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
51 |
52 | ### Learn More
53 |
54 | To learn more about Next.js, take a look at the following resources:
55 |
56 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
57 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
58 |
59 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
60 |
61 | ### Deploy on Vercel
62 |
63 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
64 |
65 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
66 |
67 |
68 | ### Support notes
69 | This template has been developed with the App Router (`app`) and React Server Components. If you’re unfamiliar with these beta features, you can find more information about them on the Next.js beta documentation page. So, please note that any request dealing with React (e.g. extra features, customisations, et cetera) is to be considered out of the support scope.
70 |
71 | For more information about what support covers, please see our (FAQs)[https://cruip.com/faq/].
72 |
73 | ## Credits
74 |
75 | - [Nucleo](https://nucleoapp.com/)
76 |
77 | ## Terms and License
78 |
79 | - Released under the [GPL](https://www.gnu.org/licenses/gpl-3.0.html).
80 | - Copyright 2023 [Cruip](https://cruip.com/).
81 | - Use it for personal and commercial projects, but please don’t republish, redistribute, or resell the template.
82 | - Attribution is not required, although it is really appreciated.
83 |
84 | ## About Us
85 |
86 | We're an Italian developer/designer duo creating high-quality design/code resources for developers, makers, and startups.
87 |
88 | ## Stay in the loop
89 |
90 | If you would like to know when we release new resources, you can follow us on [Twitter](https://twitter.com/Cruip_com), or you can subscribe to our monthly [newsletter](https://cruip.com/#subscribe).
91 |
--------------------------------------------------------------------------------
/app/(auth)/signup/page.tsx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Sign Up - Open PRO',
3 | description: 'Page description',
4 | }
5 |
6 | import Link from 'next/link'
7 |
8 | export default function SignUp() {
9 | return (
10 |
11 |
12 |
13 |
14 | {/* Page header */}
15 |
16 |
Welcome. We exist to make entrepreneurship easier.
17 |
18 |
19 | {/* Form */}
20 |
21 |
34 |
35 |
36 |
Or, register with your email
37 |
38 |
39 |
73 |
74 | Already using Open PRO? Sign in
75 |
76 |
77 |
78 |
79 |
80 |
81 | )
82 | }
83 |
--------------------------------------------------------------------------------
/app/css/additional-styles/theme.css:
--------------------------------------------------------------------------------
1 | .form-input:focus,
2 | .form-textarea:focus,
3 | .form-multiselect:focus,
4 | .form-select:focus,
5 | .form-checkbox:focus,
6 | .form-radio:focus {
7 | @apply ring-0;
8 | }
9 |
10 | /* Hamburger button */
11 | .hamburger svg > *:nth-child(1),
12 | .hamburger svg > *:nth-child(2),
13 | .hamburger svg > *:nth-child(3) {
14 | transform-origin: center;
15 | transform: rotate(0deg);
16 | }
17 |
18 | .hamburger svg > *:nth-child(1) {
19 | transition: y 0.1s 0.25s ease-in, transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19), opacity 0.1s ease-in;
20 | }
21 |
22 | .hamburger svg > *:nth-child(2) {
23 | transition: transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19);
24 | }
25 |
26 | .hamburger svg > *:nth-child(3) {
27 | transition: y 0.1s 0.25s ease-in, transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19), width 0.1s 0.25s ease-in;
28 | }
29 |
30 | .hamburger.active svg > *:nth-child(1) {
31 | opacity: 0;
32 | y: 11;
33 | transform: rotate(225deg);
34 | transition: y 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1), opacity 0.1s 0.12s ease-out;
35 | }
36 |
37 | .hamburger.active svg > *:nth-child(2) {
38 | transform: rotate(225deg);
39 | transition: transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
40 | }
41 |
42 | .hamburger.active svg > *:nth-child(3) {
43 | y: 11;
44 | transform: rotate(135deg);
45 | transition: y 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1), width 0.1s ease-out;
46 | }
47 |
48 | /* Pulsing animation */
49 | @keyframes pulseLoop {
50 | 0% { opacity: 0; transform: scale(0.1) translateZ(0); }
51 | 40% { opacity: 1; }
52 | 60% { opacity: 1; }
53 | 100% { opacity: 0; transform: scale(2) translateZ(0); }
54 | }
55 | .pulse {
56 | transform: scale(0.1);
57 | opacity: 0;
58 | transform-origin: center;
59 | animation: pulseLoop 8000ms linear infinite;
60 | }
61 | .pulse-1 {
62 | animation-delay: -2000ms;
63 | }
64 | .pulse-2 {
65 | animation-delay: -4000ms;
66 | }
67 | .pulse-3 {
68 | animation-delay: -6000ms;
69 | }
70 |
71 | /* Custom AOS distance */
72 | @media screen {
73 | html:not(.no-js) body [data-aos=fade-up] {
74 | -webkit-transform: translate3d(0, 10px, 0);
75 | transform: translate3d(0, 10px, 0);
76 | }
77 |
78 | html:not(.no-js) body [data-aos=fade-down] {
79 | -webkit-transform: translate3d(0, -10px, 0);
80 | transform: translate3d(0, -10px, 0);
81 | }
82 |
83 | html:not(.no-js) body [data-aos=fade-right] {
84 | -webkit-transform: translate3d(-10px, 0, 0);
85 | transform: translate3d(-10px, 0, 0);
86 | }
87 |
88 | html:not(.no-js) body [data-aos=fade-left] {
89 | -webkit-transform: translate3d(10px, 0, 0);
90 | transform: translate3d(10px, 0, 0);
91 | }
92 |
93 | html:not(.no-js) body [data-aos=fade-up-right] {
94 | -webkit-transform: translate3d(-10px, 10px, 0);
95 | transform: translate3d(-10px, 10px, 0);
96 | }
97 |
98 | html:not(.no-js) body [data-aos=fade-up-left] {
99 | -webkit-transform: translate3d(10px, 10px, 0);
100 | transform: translate3d(10px, 10px, 0);
101 | }
102 |
103 | html:not(.no-js) body [data-aos=fade-down-right] {
104 | -webkit-transform: translate3d(-10px, -10px, 0);
105 | transform: translate3d(-10px, -10px, 0);
106 | }
107 |
108 | html:not(.no-js) body [data-aos=fade-down-left] {
109 | -webkit-transform: translate3d(10px, -10px, 0);
110 | transform: translate3d(10px, -10px, 0);
111 | }
112 |
113 | html:not(.no-js) body [data-aos=zoom-in-up] {
114 | -webkit-transform: translate3d(0, 10px, 0) scale(.6);
115 | transform: translate3d(0, 10px, 0) scale(.6);
116 | }
117 |
118 | html:not(.no-js) body [data-aos=zoom-in-down] {
119 | -webkit-transform: translate3d(0, -10px, 0) scale(.6);
120 | transform: translate3d(0, -10px, 0) scale(.6);
121 | }
122 |
123 | html:not(.no-js) body [data-aos=zoom-in-right] {
124 | -webkit-transform: translate3d(-10px, 0, 0) scale(.6);
125 | transform: translate3d(-10px, 0, 0) scale(.6);
126 | }
127 |
128 | html:not(.no-js) body [data-aos=zoom-in-left] {
129 | -webkit-transform: translate3d(10px, 0, 0) scale(.6);
130 | transform: translate3d(10px, 0, 0) scale(.6);
131 | }
132 |
133 | html:not(.no-js) body [data-aos=zoom-out-up] {
134 | -webkit-transform: translate3d(0, 10px, 0) scale(1.2);
135 | transform: translate3d(0, 10px, 0) scale(1.2);
136 | }
137 |
138 | html:not(.no-js) body [data-aos=zoom-out-down] {
139 | -webkit-transform: translate3d(0, -10px, 0) scale(1.2);
140 | transform: translate3d(0, -10px, 0) scale(1.2);
141 | }
142 |
143 | html:not(.no-js) body [data-aos=zoom-out-right] {
144 | -webkit-transform: translate3d(-10px, 0, 0) scale(1.2);
145 | transform: translate3d(-10px, 0, 0) scale(1.2);
146 | }
147 |
148 | html:not(.no-js) body [data-aos=zoom-out-left] {
149 | -webkit-transform: translate3d(10px, 0, 0) scale(1.2);
150 | transform: translate3d(10px, 0, 0) scale(1.2);
151 | }
152 | }
--------------------------------------------------------------------------------
/components/testimonials.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image'
2 |
3 | import TestimonialImage01 from '@/public/images/testimonial-01.jpg'
4 | import TestimonialImage02 from '@/public/images/testimonial-02.jpg'
5 | import TestimonialImage03 from '@/public/images/testimonial-03.jpg'
6 |
7 | export default function Testimonials() {
8 | return (
9 |
10 |
11 |
12 |
13 | {/* Section header */}
14 |
15 |
Don't take our word for it
16 |
Vitae aliquet nec ullamcorper sit amet risus nullam eget felis semper quis lectus nulla at volutpat diam ut venenatis tellus—in ornare.
17 |
18 |
19 | {/* Testimonials */}
20 |
21 |
22 | {/* 1st testimonial */}
23 |
24 |
32 |
— Open PRO lets me quickly get the insights I care about so that I can focus on my productive work. I've had Open PRO for about 24 hours now and I honestly don't know how I functioned without it before.
33 |
36 |
37 |
38 | {/* 2nd testimonial */}
39 |
40 |
48 |
— Open PRO lets me quickly get the insights I care about so that I can focus on my productive work. I've had Open PRO for about 24 hours now and I honestly don't know how I functioned without it before.
49 |
52 |
53 |
54 | {/* 3rd testimonial */}
55 |
56 |
64 |
— Open PRO lets me quickly get the insights I care about so that I can focus on my productive work. I've had Open PRO for about 24 hours now and I honestly don't know how I functioned without it before.
65 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | )
76 | }
77 |
--------------------------------------------------------------------------------
/components/features.tsx:
--------------------------------------------------------------------------------
1 | export default function Features() {
2 | return (
3 |
4 |
5 |
6 |
7 | {/* Section header */}
8 |
9 |
The majority our customers do not understand their workflows.
10 |
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
11 |
12 |
13 | {/* Items */}
14 |
15 |
16 | {/* 1st item */}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
Instant Features
24 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
25 |
26 |
27 | {/* 2nd item */}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Instant Features
35 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
36 |
37 |
38 | {/* 3rd item */}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Instant Features
49 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
50 |
51 |
52 | {/* 4th item */}
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
Instant Features
62 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
63 |
64 |
65 | {/* 5th item */}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
Instant Features
75 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
76 |
77 |
78 | {/* 6th item */}
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
Instant Features
89 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | )
98 | }
99 |
--------------------------------------------------------------------------------
/components/blocks.tsx:
--------------------------------------------------------------------------------
1 | export default function Blocks() {
2 | return (
3 |
4 |
5 |
6 |
7 | {/* Section header */}
8 |
9 |
The majority our customers do not understand their workflows.
10 |
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
11 |
12 |
13 | {/* Items */}
14 |
15 |
16 | {/* 1st item */}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
Instant Features
24 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
25 |
26 |
27 | {/* 2nd item */}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Instant Features
35 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
36 |
37 |
38 | {/* 3rd item */}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Instant Features
49 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
50 |
51 |
52 | {/* 4th item */}
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
Instant Features
62 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
63 |
64 |
65 | {/* 5th item */}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
Instant Features
75 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
76 |
77 |
78 | {/* 6th item */}
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
Instant Features
89 |
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | )
98 | }
99 |
--------------------------------------------------------------------------------
/components/zigzag.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image'
2 |
3 | import FeatImage01 from '@/public/images/features-03-image-01.png'
4 | import FeatImage02 from '@/public/images/features-03-image-02.png'
5 | import FeatImage03 from '@/public/images/features-03-image-03.png'
6 |
7 | export default function Zigzag() {
8 | return (
9 |
10 |
11 |
12 |
13 | {/* Section header */}
14 |
15 |
Reach goals that matter
16 |
One product, unlimited solutions
17 |
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit laborum — semper quis lectus nulla.
18 |
19 |
20 | {/* Items */}
21 |
22 |
23 | {/* 1st item */}
24 |
25 | {/* Image */}
26 |
27 |
28 |
29 | {/* Content */}
30 |
31 |
32 |
More speed. Less spend
33 |
Keep projects on schedule
34 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
35 |
36 |
37 |
38 |
39 |
40 | Duis aute irure dolor in reprehenderit
41 |
42 |
43 |
44 |
45 |
46 | Excepteur sint occaecat
47 |
48 |
49 |
50 |
51 |
52 | Amet consectetur adipiscing elit
53 |
54 |
55 |
56 |
57 |
58 |
59 | {/* 2nd item */}
60 |
61 | {/* Image */}
62 |
63 |
64 |
65 | {/* Content */}
66 |
67 |
68 |
More speed. Less spend
69 |
Keep projects on schedule
70 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
71 |
72 |
73 |
74 |
75 |
76 | Duis aute irure dolor in reprehenderit
77 |
78 |
79 |
80 |
81 |
82 | Excepteur sint occaecat
83 |
84 |
85 |
86 |
87 |
88 | Amet consectetur adipiscing elit
89 |
90 |
91 |
92 |
93 |
94 |
95 | {/* 3rd item */}
96 |
97 | {/* Image */}
98 |
99 |
100 |
101 | {/* Content */}
102 |
103 |
104 |
More speed. Less spend
105 |
Keep projects on schedule
106 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
107 |
108 |
109 |
110 |
111 |
112 | Duis aute irure dolor in reprehenderit
113 |
114 |
115 |
116 |
117 |
118 | Excepteur sint occaecat
119 |
120 |
121 |
122 |
123 |
124 | Amet consectetur adipiscing elit
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | )
137 | }
138 |
--------------------------------------------------------------------------------
/components/hero.tsx:
--------------------------------------------------------------------------------
1 | import VideoThumb from '@/public/images/hero-image-01.jpg'
2 | import ModalVideo from '@/components/modal-video'
3 |
4 | export default function Hero() {
5 | return (
6 |
7 |
8 |
9 | {/* Illustration behind hero content */}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {/* Hero content */}
23 |
24 |
25 | {/* Section header */}
26 |
27 |
Landing template for startups
28 |
Our landing page template works on all devices, so you only have to set it up once, and get beautiful results forever.
29 |
37 |
38 |
39 |
47 |
48 |
49 |
50 |
51 |
52 | )
53 | }
54 |
--------------------------------------------------------------------------------
/components/ui/footer.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Link from 'next/link'
3 |
4 | export default function Footer() {
5 | return (
6 |
7 |
8 |
9 |
10 | {/* Top area: Blocks */}
11 |
12 |
13 | {/* 1st block */}
14 |
15 |
16 | {/* Logo */}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups.
24 |
25 |
26 | {/* 2nd, 3rd and 4th blocks */}
27 |
28 |
29 | {/* 2nd block */}
30 |
31 |
Products
32 |
33 |
34 | Web Studio
35 |
36 |
37 | DynamicBox Flex
38 |
39 |
40 | Programming Forms
41 |
42 |
43 |
44 |
45 | {/* 3rd block */}
46 |
47 |
Resources
48 |
49 |
50 | Nostrud exercitation
51 |
52 |
53 | Visual mockups
54 |
55 |
56 | Nostrud exercitation
57 |
58 |
59 | Visual mockups
60 |
61 |
62 | Nostrud exercitation
63 |
64 |
65 |
66 |
67 | {/* 4th block */}
68 |
69 |
Company
70 |
71 |
72 | Consectetur adipiscing
73 |
74 |
75 | Labore et dolore
76 |
77 |
78 | Consectetur adipiscing
79 |
80 |
81 | Labore et dolore
82 |
83 |
84 | Consectetur adipiscing
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | {/* Bottom area */}
94 |
95 |
96 | {/* Social links */}
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | {/* Copyrights note */}
138 |
© Cruip.com. All rights reserved.
139 |
140 |
141 |
142 |
143 |
144 |
145 | )
146 | }
147 |
--------------------------------------------------------------------------------
/components/newsletter.tsx:
--------------------------------------------------------------------------------
1 | export default function Newsletter() {
2 | return (
3 |
4 |
5 |
6 | {/* CTA box */}
7 |
8 |
9 | {/* Background illustration */}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | {/* CTA content */}
25 |
26 |
Stay in the loop
27 |
Join our newsletter to get top news before anyone else.
28 |
29 |
30 | {/* CTA form */}
31 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | )
47 | }
48 |
--------------------------------------------------------------------------------
/components/page-illustration.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function PageIllustration() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------