├── .dockerignore ├── .github └── FUNDING.yml ├── .gitignore ├── .husky └── pre-commit ├── .lintstagedrc.json ├── .prettierrc ├── .vscode ├── extensions.json └── launch.json ├── Dockerfile ├── LICENSE ├── README.md ├── astro.config.mjs ├── bin └── build-docker.sh ├── package.json ├── public └── favicon.svg ├── src ├── components │ ├── BlogPostCard.tsx │ ├── CTA.tsx │ ├── Card.astro │ ├── Data.tsx │ ├── Feature.tsx │ ├── Newsletter.tsx │ ├── Price.tsx │ ├── Signin.tsx │ └── Stats.tsx ├── env.d.ts ├── layouts │ ├── Footer.tsx │ ├── Header.tsx │ └── Layout.astro └── pages │ ├── 404.astro │ ├── blog │ ├── [id].astro │ └── index.astro │ ├── contact.astro │ ├── index.astro │ ├── price.astro │ └── signin.astro ├── tailwind.config.cjs ├── tsconfig.json └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | bin 4 | Dockerfile 5 | .git 6 | dist 7 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: jungley # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: jungley # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | 4 | # generated types 5 | .astro/ 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # logs 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | 23 | # vercel build 24 | .vercel 25 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}": ["prettier --write"] 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "quoteProps": "as-needed", 8 | "jsxSingleQuote": false, 9 | "trailingComma": "all", 10 | "bracketSpacing": true, 11 | "arrowParens": "always", 12 | "requirePragma": false, 13 | "insertPragma": false, 14 | "proseWrap": "preserve", 15 | "plugins": [ 16 | "prettier-plugin-astro" 17 | ], 18 | "overrides": [ 19 | { 20 | "files": "*.astro", 21 | "options": { 22 | "parser": "astro" 23 | } 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine AS build 2 | WORKDIR /app 3 | 4 | COPY package.json . 5 | RUN yarn 6 | 7 | COPY --chown=node:node . . 8 | RUN yarn build 9 | 10 | USER node 11 | ENV NODE_ENV=production 12 | ENV HOST=0.0.0.0 13 | ENV PORT=3000 14 | EXPOSE 3000 15 | 16 | CMD node ./dist/server/entry.mjs 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Jungley 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 | # Astro landing-page 2 | 3 | ``` 4 | yarn create astro --template jungley8/astro-landing-page 5 | ``` 6 | 7 | ## 🚀 Project Structure 8 | 9 | Inside of your Astro project, you'll see the following folders and files: 10 | 11 | ``` 12 | / 13 | ├── public 14 | │ └── favicon.svg 15 | ├── src 16 | │ ├── components 17 | │ │ ├── BlogPostCard.tsx 18 | │ │ ├── CTA.tsx 19 | │ │ ├── Card.astro 20 | │ │ ├── Data.tsx 21 | │ │ ├── Feature.tsx 22 | │ │ ├── Newsletter.tsx 23 | │ │ ├── Price.tsx 24 | │ │ ├── Signin.tsx 25 | │ │ └── Stats.tsx 26 | │ ├── env.d.ts 27 | │ ├── layouts 28 | │ │ ├── Footer.tsx 29 | │ │ ├── Header.tsx 30 | │ │ └── Layout.astro 31 | │ └── pages 32 | │ ├── 404.astro 33 | │ ├── blog 34 | │ │ ├── [id].astro 35 | │ │ └── index.astro 36 | │ ├── contact.astro 37 | │ ├── index.astro 38 | │ ├── price.astro 39 | │ └── signin.astro 40 | ├── tailwind.config.cjs 41 | └── package.json 42 | ``` 43 | 44 | Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. 45 | 46 | There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. 47 | 48 | Any static assets, like images, can be placed in the `public/` directory. 49 | 50 | ## 🧞 Commands 51 | 52 | All commands are run from the root of the project, from a terminal: 53 | 54 | | Command | Action | 55 | | :------------------ | :----------------------------------------------- | 56 | | `yarn` | Installs dependencies | 57 | | `yarn dev` | Starts local dev server at `localhost:3000` | 58 | | `yarn build` | Build your production site to `./dist/` | 59 | | `yarn preview` | Preview your build locally, before deploying | 60 | | `yarn astro ...` | Run CLI commands like `astro add`, `astro check` | 61 | | `yarn astro --help` | Get help using the Astro CLI | 62 | | `yarn prettier` | Formate and beautify your code | 63 | 64 | ## 👀 Want to learn more? 65 | 66 | Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). 67 | 68 | ## Demo 69 | 70 | [astro-landing-page demo](https://astro-landing-page-jet.vercel.app) 71 | 72 | ## Deploy 73 | 74 | Host your own live version of Astro-landing-page with Vercel. 75 | 76 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FJungley8%2Fastro-landing-page) 77 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | // import node from '@astrojs/node'; 3 | import react from "@astrojs/react"; 4 | import tailwind from "@astrojs/tailwind"; 5 | 6 | import vercel from "@astrojs/vercel/serverless"; 7 | 8 | // https://astro.build/config 9 | export default defineConfig({ 10 | output: 'server', 11 | // if 使用 docker, 请将 adapter 切换到 node 12 | // adapter: node({ 13 | // mode: 'standalone' 14 | // }), 15 | adapter: vercel({ 16 | analytics: true 17 | }), 18 | integrations: [react(), tailwind()], 19 | markdown: { 20 | // Example: Switch to use prism for syntax highlighting in Markdown 21 | syntaxHighlight: 'prism' 22 | } 23 | }); -------------------------------------------------------------------------------- /bin/build-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # set -x 4 | set -e 5 | 6 | if [[ ! -z "$1" ]]; then 7 | version=$1 8 | else 9 | read -p "请输入镜像版本号:" version 10 | fi 11 | 12 | version=v${version} 13 | echo $version 14 | 15 | # build your container 16 | SOURCE_IMAGE='jungley-net' 17 | push_tag=registry.cn-hangzhou.aliyuncs.com/jungleyyeh/$SOURCE_IMAGE:$version 18 | 19 | docker build -t $SOURCE_IMAGE . 20 | 21 | docker tag $SOURCE_IMAGE $push_tag 22 | 23 | # Push your image to a registry 24 | docker push $push_tag 25 | 26 | docker image rm $push_tag -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jungley-net", 3 | "type": "module", 4 | "version": "0.0.2", 5 | "scripts": { 6 | "dev": "astro dev --host", 7 | "start": "astro dev --host", 8 | "build": "astro check && astro build", 9 | "preview": "astro preview", 10 | "prettier": "prettier --write ./src", 11 | "astro": "astro", 12 | "prepare": "husky install" 13 | }, 14 | "dependencies": { 15 | "@astrojs/check": "^0.5.6", 16 | "@astrojs/node": "^8.2.3", 17 | "@astrojs/prism": "^3.0.0", 18 | "@astrojs/react": "^3.0.10", 19 | "@astrojs/tailwind": "^5.1.0", 20 | "@astrojs/ts-plugin": "^1.5.3", 21 | "@astrojs/vercel": "^7.3.4", 22 | "@headlessui/react": "^1.7.18", 23 | "@heroicons/react": "^2.1.1", 24 | "@tailwindcss/aspect-ratio": "^0.4.2", 25 | "@tailwindcss/forms": "^0.5.7", 26 | "@tailwindcss/typography": "^0.5.10", 27 | "@types/react": "^18.2.61", 28 | "@types/react-dom": "^18.2.19", 29 | "astro": "^4.4.10", 30 | "classnames": "^2.5.1", 31 | "react": "^18.2.0", 32 | "react-dom": "^18.2.0", 33 | "tailwindcss": "^3.4.1", 34 | "typescript": "^5.3.3" 35 | }, 36 | "devDependencies": { 37 | "husky": "^9.0.11", 38 | "lint-staged": "^15.2.2", 39 | "prettier": "^3.2.5", 40 | "prettier-plugin-astro": "^0.13.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/BlogPostCard.tsx: -------------------------------------------------------------------------------- 1 | type Post = { 2 | id: number; 3 | datetime: string | undefined; 4 | date: string; 5 | category: any; 6 | href: string | undefined; 7 | title: string; 8 | description: string; 9 | author: any; 10 | }; 11 | export default function BlogPostCard({ post }: { post: Post }) { 12 | return ( 13 |
17 |
18 | 21 | 25 | {post.category.title} 26 | 27 |
28 |
29 |

30 | 31 | 32 | {post.title} 33 | 34 |

35 |

36 | {post.description} 37 |

38 |
39 |
40 | 45 |
46 |

47 | 48 | 49 | {post.author.name} 50 | 51 |

52 |

{post.author.role}

53 |
54 |
55 |
56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /src/components/CTA.tsx: -------------------------------------------------------------------------------- 1 | export default function CTA() { 2 | return ( 3 |
4 |
5 |
6 | 25 |
26 |

27 | Boost your productivity. 28 |
29 | Start using our app today. 30 |

31 |

32 | Ac euismod vel sit maecenas id pellentesque eu sed consectetur. 33 | Malesuada adipiscing sagittis vel nulla. 34 |

35 |
36 | 40 | Get started 41 | 42 | 46 | Learn more 47 | 48 |
49 |
50 |
51 | App screenshot 58 |
59 |
60 |
61 |
62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /src/components/Card.astro: -------------------------------------------------------------------------------- 1 | --- 2 | export interface Props { 3 | title: string; 4 | body: string; 5 | href: string; 6 | } 7 | 8 | const { href, title, body } = Astro.props; 9 | --- 10 | 11 | 22 | 61 | -------------------------------------------------------------------------------- /src/components/Data.tsx: -------------------------------------------------------------------------------- 1 | import { PaperClipIcon } from '@heroicons/react/20/solid'; 2 | 3 | export default function Data() { 4 | return ( 5 |
6 |
7 |
8 |
9 |

10 | Applicant Information 11 |

12 |

13 | Personal details and application. 14 |

15 |
16 |
17 |
18 |
19 |
Full name
20 |
21 | Margot Foster 22 |
23 |
24 |
25 |
26 | Application for 27 |
28 |
29 | Backend Developer 30 |
31 |
32 |
33 |
34 | Email address 35 |
36 |
37 | margotfoster@example.com 38 |
39 |
40 |
41 |
42 | Salary expectation 43 |
44 |
45 | $120,000 46 |
47 |
48 |
49 |
About
50 |
51 | Fugiat ipsum ipsum deserunt culpa aute sint do nostrud anim 52 | incididunt cillum culpa consequat. Excepteur qui ipsum aliquip 53 | consequat sint. Sit id mollit nulla mollit nostrud in ea 54 | officia proident. Irure nostrud pariatur mollit ad adipisicing 55 | reprehenderit deserunt qui eu. 56 |
57 |
58 |
59 |
60 | Attachments 61 |
62 |
63 |
    67 |
  • 68 |
    69 |
    77 | 85 |
  • 86 |
  • 87 |
    88 |
    96 | 104 |
  • 105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | ); 114 | } 115 | -------------------------------------------------------------------------------- /src/components/Feature.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | CloudArrowUpIcon, 3 | LockClosedIcon, 4 | ServerIcon, 5 | } from '@heroicons/react/20/solid'; 6 | 7 | const features = [ 8 | { 9 | name: 'Push to deploy.', 10 | description: 11 | 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.', 12 | icon: CloudArrowUpIcon, 13 | }, 14 | { 15 | name: 'SSL certificates.', 16 | description: 17 | 'Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui lorem cupidatat commodo.', 18 | icon: LockClosedIcon, 19 | }, 20 | { 21 | name: 'Database backups.', 22 | description: 23 | 'Ac tincidunt sapien vehicula erat auctor pellentesque rhoncus. Et magna sit morbi lobortis.', 24 | icon: ServerIcon, 25 | }, 26 | ]; 27 | 28 | export default function Feature() { 29 | return ( 30 |
31 |
32 |
33 |
34 |
35 |

36 | Deploy faster 37 |

38 |

39 | A better workflow 40 |

41 |

42 | Lorem ipsum, dolor sit amet consectetur adipisicing elit. 43 | Maiores impedit perferendis suscipit eaque, iste dolor 44 | cupiditate blanditiis ratione. 45 |

46 |
47 | {features.map((feature) => ( 48 |
49 |
50 |
{' '} 56 |
{feature.description}
57 |
58 | ))} 59 |
60 |
61 |
62 | Product screenshot 69 |
70 |
71 |
72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /src/components/Newsletter.tsx: -------------------------------------------------------------------------------- 1 | import { CalendarDaysIcon, HandRaisedIcon } from '@heroicons/react/24/outline'; 2 | 3 | export default function Newsletter() { 4 | return ( 5 |
9 |
10 |
11 |
12 |

13 | Subscribe to our newsletter. 14 |

15 |

16 | Nostrud amet eu ullamco nisi aute in ad minim nostrud adipisicing 17 | velit quis. Duis tempor incididunt dolore. 18 |

19 |
20 | 23 | 32 | 38 |
39 |
40 |
41 |
42 |
43 |
48 |
Weekly articles
49 |
50 | Non laboris consequat cupidatat laborum magna. Eiusmod non irure 51 | cupidatat duis commodo amet. 52 |
53 |
54 |
55 |
56 |
61 |
No spam
62 |
63 | Officia excepteur ullamco ut sint duis proident non adipisicing. 64 | Voluptate incididunt anim. 65 |
66 |
67 |
68 |
69 |
70 | 75 | 80 | 81 | 89 | 90 | 91 | 92 | 93 | 94 |
95 | ); 96 | } 97 | -------------------------------------------------------------------------------- /src/components/Price.tsx: -------------------------------------------------------------------------------- 1 | import { CheckIcon } from '@heroicons/react/20/solid'; 2 | 3 | const includedFeatures = [ 4 | 'Private forum access', 5 | 'Member resources', 6 | 'Entry to annual conference', 7 | 'Official member t-shirt', 8 | ]; 9 | 10 | export default function Price() { 11 | return ( 12 |
13 |
14 |
15 |

16 | Simple no-tricks pricing 17 |

18 |

19 | Distinctio et nulla eum soluta et neque labore quibusdam. Saepe et 20 | quasi iusto modi velit ut non voluptas in. Explicabo id ut laborum. 21 |

22 |
23 |
24 |
25 |

26 | Lifetime membership 27 |

28 |

29 | Lorem ipsum dolor sit amet consect etur adipisicing elit. Itaque 30 | amet indis perferendis blanditiis repellendus etur quidem 31 | assumenda. 32 |

33 |
34 |

35 | What’s included 36 |

37 |
38 |
39 |
    43 | {includedFeatures.map((feature) => ( 44 |
  • 45 |
  • 51 | ))} 52 |
53 |
54 |
55 |
56 |
57 |

58 | Pay once, own it forever 59 |

60 |

61 | 62 | $349 63 | 64 | 65 | USD 66 | 67 |

68 | 72 | Get access 73 | 74 |

75 | Invoices and receipts available for easy company reimbursement 76 |

77 |
78 |
79 |
80 |
81 |
82 |
83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /src/components/Signin.tsx: -------------------------------------------------------------------------------- 1 | import { LockClosedIcon } from '@heroicons/react/20/solid'; 2 | 3 | export default function Signin() { 4 | return ( 5 | <> 6 |
7 |
8 |
9 | Your Company 14 |

15 | Sign in to your account 16 |

17 |

18 | Or{' '} 19 | 23 | start your 14-day free trial 24 | 25 |

26 |
27 |
28 | 29 |
30 |
31 | 34 | 43 |
44 |
45 | 48 | 57 |
58 |
59 | 60 |
61 |
62 | 68 | 74 |
75 | 76 | 84 |
85 | 86 |
87 | 99 |
100 |
101 |
102 |
103 | 104 | ); 105 | } 106 | -------------------------------------------------------------------------------- /src/components/Stats.tsx: -------------------------------------------------------------------------------- 1 | const stats = [ 2 | { id: 1, name: 'Transactions every 24 hours', value: '44 million' }, 3 | { id: 2, name: 'Assets under holding', value: '$119 trillion' }, 4 | { id: 3, name: 'New users annually', value: '46,000' }, 5 | ]; 6 | 7 | export default function Stats() { 8 | return ( 9 |
10 |
11 |
12 | {stats.map((stat) => ( 13 |
17 |
{stat.name}
18 |
19 | {stat.value} 20 |
21 |
22 | ))} 23 |
24 |
25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | // readonly DB_PASSWORD: string; 5 | // readonly PUBLIC_POKEAPI: string; 6 | // more env variables... 7 | } 8 | 9 | interface ImportMeta { 10 | readonly env: ImportMetaEnv; 11 | } 12 | -------------------------------------------------------------------------------- /src/layouts/Footer.tsx: -------------------------------------------------------------------------------- 1 | export default function Footer() { 2 | return ( 3 | 265 | ); 266 | } 267 | -------------------------------------------------------------------------------- /src/layouts/Header.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment, useState } from 'react'; 2 | import { Dialog, Disclosure, Popover, Transition } from '@headlessui/react'; 3 | import { 4 | ArrowPathIcon, 5 | Bars3Icon, 6 | ChartPieIcon, 7 | CursorArrowRaysIcon, 8 | FingerPrintIcon, 9 | SquaresPlusIcon, 10 | XMarkIcon, 11 | } from '@heroicons/react/24/outline'; 12 | import { 13 | ChevronDownIcon, 14 | PhoneIcon, 15 | PlayCircleIcon, 16 | } from '@heroicons/react/20/solid'; 17 | import classNames from 'classnames'; 18 | 19 | const products = [ 20 | { 21 | name: 'Analytics', 22 | description: 'Get a better understanding of your traffic', 23 | href: '#', 24 | icon: ChartPieIcon, 25 | }, 26 | { 27 | name: 'Engagement', 28 | description: 'Speak directly to your customers', 29 | href: '#', 30 | icon: CursorArrowRaysIcon, 31 | }, 32 | { 33 | name: 'Security', 34 | description: 'Your customers’ data will be safe and secure', 35 | href: '#', 36 | icon: FingerPrintIcon, 37 | }, 38 | { 39 | name: 'Integrations', 40 | description: 'Connect with third-party tools', 41 | href: '#', 42 | icon: SquaresPlusIcon, 43 | }, 44 | { 45 | name: 'Automations', 46 | description: 'Build strategic funnels that will convert', 47 | href: '#', 48 | icon: ArrowPathIcon, 49 | }, 50 | ]; 51 | const callsToAction = [ 52 | { name: 'Watch demo', href: '#', icon: PlayCircleIcon }, 53 | { name: 'Contact sales', href: '#', icon: PhoneIcon }, 54 | ]; 55 | 56 | export default function Header() { 57 | const [mobileMenuOpen, setMobileMenuOpen] = useState(false); 58 | 59 | return ( 60 |
61 | 183 | 189 |
190 | 191 |
192 | 193 | Your Company 194 | 199 | 200 | 208 |
209 |
210 |
211 |
212 | 213 | {({ open }) => ( 214 | <> 215 | 216 | Product 217 | 225 | 226 | {[...products, ...callsToAction].map((item) => ( 227 | 233 | {item.name} 234 | 235 | ))} 236 | 237 | 238 | )} 239 | 240 | 244 | Newsletter 245 | 246 | 250 | Price 251 | 252 | 256 | Contact 257 | 258 | 262 | Blog 263 | 264 |
265 | 273 |
274 |
275 |
276 |
277 |
278 | ); 279 | } 280 | -------------------------------------------------------------------------------- /src/layouts/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Footer from './Footer'; 3 | import Header from './Header'; 4 | 5 | export interface Props { 6 | title: string; 7 | } 8 | 9 | const { title } = Astro.props; 10 | --- 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {title} 20 | 21 | 22 |
23 | 24 |