Merge branch 'main' into main
This commit is contained in:
commit
5f827e23d7
11 changed files with 280 additions and 10 deletions
|
@ -3,6 +3,8 @@ import Hero from '@/components/shared/Hero';
|
||||||
import HowItWorks from '@/components/shared/HowItWorks';
|
import HowItWorks from '@/components/shared/HowItWorks';
|
||||||
import Newsletter from '@/components/shared/Newsletter';
|
import Newsletter from '@/components/shared/Newsletter';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const RootPage = () => {
|
const RootPage = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -10,6 +12,7 @@ const RootPage = () => {
|
||||||
<HowItWorks />
|
<HowItWorks />
|
||||||
<About />
|
<About />
|
||||||
<Newsletter />
|
<Newsletter />
|
||||||
|
<Faq />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,39 @@
|
||||||
|
import { questions } from "@/constants";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "../ui/accordion";
|
||||||
|
|
||||||
const Faq = () => {
|
const Faq = () => {
|
||||||
return <div>Faq</div>;
|
return (
|
||||||
|
<section id="faq" className="wrapper container py-24 md:py-28">
|
||||||
|
<h2 className="text-3xl md:text-5xl font-bold mb-4 text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
|
||||||
|
Frequently Asked Question
|
||||||
|
</h2>
|
||||||
|
<p className="textlg text-muted-foreground text-start mt-4 mb-8">
|
||||||
|
Find answers to common questions about SVRJS
|
||||||
|
</p>
|
||||||
|
<Accordion
|
||||||
|
type="single"
|
||||||
|
collapsible={true}
|
||||||
|
className="w-full AccordionRoot"
|
||||||
|
>
|
||||||
|
{questions.map(({ question, answer, key }) => (
|
||||||
|
<AccordionItem key={key} value={key} className="border-b">
|
||||||
|
<AccordionTrigger className="text-left text-lg">
|
||||||
|
{question}
|
||||||
|
</AccordionTrigger>
|
||||||
|
<AccordionContent className="text-[1rem] text-muted-foreground">
|
||||||
|
{answer}
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
))}
|
||||||
|
</Accordion>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Faq;
|
export default Faq;
|
||||||
|
|
7
components/shared/Footer.tsx
Normal file
7
components/shared/Footer.tsx
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const Footer = () => {
|
||||||
|
return <div>Footer</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
|
@ -45,7 +45,7 @@ const Hero = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="relative container grid lg:grid-cols-2 place-items-center py-20 md:py-24 gap-10">
|
<section className="relative container grid lg:grid-cols-2 place-items-center py-20 md:py-24 gap-10">
|
||||||
{/* <GridPattern
|
<GridPattern
|
||||||
squares={[
|
squares={[
|
||||||
[4, 4],
|
[4, 4],
|
||||||
[5, 1],
|
[5, 1],
|
||||||
|
@ -56,9 +56,9 @@ const Hero = () => {
|
||||||
]}
|
]}
|
||||||
className={cn(
|
className={cn(
|
||||||
"[mask-image:radial-gradient(300px_circle_at_center,white,transparent)]",
|
"[mask-image:radial-gradient(300px_circle_at_center,white,transparent)]",
|
||||||
"inset-x-0 inset-y-[-50%] h-[200%] opacity-20"
|
"inset-x-0 inset-y-[-50%] h-[200%] opacity-30"
|
||||||
)}
|
)}
|
||||||
/> */}
|
/>
|
||||||
<div className="text-center lg:text-start space-y-6">
|
<div className="text-center lg:text-start space-y-6">
|
||||||
<AnimatedGradientText className="mx-auto lg:mx-0">
|
<AnimatedGradientText className="mx-auto lg:mx-0">
|
||||||
🎉{" "}
|
🎉{" "}
|
||||||
|
|
|
@ -66,7 +66,9 @@ const Navbar = () => {
|
||||||
key={label}
|
key={label}
|
||||||
href={href}
|
href={href}
|
||||||
target={target}
|
target={target}
|
||||||
className={`border ${buttonVariants({ variant: 'ghost' })}`}
|
className={`border ${buttonVariants({
|
||||||
|
variant: "ghost",
|
||||||
|
})} px-0 w-11`}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src="/next.svg"
|
src="/next.svg"
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Input } from "../ui/input";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { Happy_Monkey } from "next/font/google";
|
||||||
|
|
||||||
|
const happyMonkey = Happy_Monkey({
|
||||||
|
preload: true,
|
||||||
|
weight: "400",
|
||||||
|
subsets: ["latin"],
|
||||||
|
});
|
||||||
|
|
||||||
const Newsletter = () => {
|
const Newsletter = () => {
|
||||||
const [submission, setSubmission] = useState<
|
const [submission, setSubmission] = useState<
|
||||||
|
@ -15,21 +25,50 @@ const Newsletter = () => {
|
||||||
<section id="newsletter">
|
<section id="newsletter">
|
||||||
<hr className="w-11/12 mx-auto" />
|
<hr className="w-11/12 mx-auto" />
|
||||||
<div className="container py-24 md:py-32">
|
<div className="container py-24 md:py-32">
|
||||||
<h3 className="text-center text-4xl md:text-5xl font-bold bg-clip-text text-transparent bg-gradient-to-b from-neutral-200 to-neutral-600">
|
<h3 className="text-center text-4xl md:text-5xl text-black font-bold dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
|
||||||
Join The Newsletter!
|
Join The Newsletter!
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-lg text-muted-foreground text-center mt-4 mb-8">
|
<p className="text-lg text-muted-foreground text-center mt-4 mb-8">
|
||||||
Choosing the right website deployment option is important when
|
Choosing the right website deployment option is important when
|
||||||
creating a website, because it directly impacts the user experience
|
creating a website, because it directly impacts the user experience
|
||||||
and the resources required to run your website. Website deployment is
|
and the resources required to run your website.
|
||||||
a process of publishing a website into a production hosting
|
|
||||||
environment
|
|
||||||
</p>
|
</p>
|
||||||
<form
|
<form
|
||||||
className="relative flex flex-col w-full md:flex-row md:w-6/12 lg:w-4/12 mx-auto gap-4 md:gap-2"
|
className="relative flex flex-col w-full md:flex-row md:w-6/12 lg:w-4/12 mx-auto gap-4 md:gap-2"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
></form>
|
>
|
||||||
|
<Input placeholder="example@subscribe.com"></Input>
|
||||||
|
|
||||||
|
<Button disabled={submission === "loading"}>Subscribe</Button>
|
||||||
|
<div className="pointer-events-none dark:invert -scale-x-100 absolute -bottom-14 right-1/2 md:right-14 inline-flex justify-center items-center gap-1">
|
||||||
|
<Image
|
||||||
|
src="/curly-arrow.png"
|
||||||
|
alt="see here"
|
||||||
|
width={35}
|
||||||
|
height={35}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={`mt-10 font-bold text-black -scale-x-100 text-[15px] ${happyMonkey.className}`}
|
||||||
|
>
|
||||||
|
{submission === "idle" && "Subscribe Now"}
|
||||||
|
{submission === "loading" && (
|
||||||
|
<p className="text-sm text-center">Subscribing...</p>
|
||||||
|
)}
|
||||||
|
{submission === "success" && (
|
||||||
|
<p className="dark:invert text-sm text-center text-green-500">
|
||||||
|
🎉 Subscribed successfully...
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{submission === "error" && (
|
||||||
|
<p className="dark:invert text-sm text-center text-red-500">
|
||||||
|
😥 Something went wrong...
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<hr className="w-11/12 mx-auto" />
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
58
components/ui/accordion.tsx
Normal file
58
components/ui/accordion.tsx
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
||||||
|
import { ChevronDown } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Accordion = AccordionPrimitive.Root
|
||||||
|
|
||||||
|
const AccordionItem = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Item>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Item
|
||||||
|
ref={ref}
|
||||||
|
className={cn("border-b", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
AccordionItem.displayName = "AccordionItem"
|
||||||
|
|
||||||
|
const AccordionTrigger = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Header className="flex">
|
||||||
|
<AccordionPrimitive.Trigger
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
||||||
|
</AccordionPrimitive.Trigger>
|
||||||
|
</AccordionPrimitive.Header>
|
||||||
|
))
|
||||||
|
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
|
||||||
|
|
||||||
|
const AccordionContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
||||||
|
</AccordionPrimitive.Content>
|
||||||
|
))
|
||||||
|
|
||||||
|
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
||||||
|
|
||||||
|
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
25
components/ui/input.tsx
Normal file
25
components/ui/input.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
export interface InputProps
|
||||||
|
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||||
|
|
||||||
|
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||||
|
({ className, type, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
className={cn(
|
||||||
|
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Input.displayName = "Input"
|
||||||
|
|
||||||
|
export { Input }
|
|
@ -77,3 +77,42 @@ export const Features = [
|
||||||
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
|
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const questions = [
|
||||||
|
{
|
||||||
|
key: "item-1",
|
||||||
|
question: "What is a web server?",
|
||||||
|
answer:
|
||||||
|
"A web server is computer software that accepts HTTP requests and serves websites. Web servers can also be underlying hardware running web server software.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "item-2",
|
||||||
|
question: "What is SVR.JS?",
|
||||||
|
answer:
|
||||||
|
"SVR.JS is web server software running on Node.JS that can host both static and dynamic content. With additional mods, SVR.JS can be used for different types of dynamic content and can even be used as a forward or reverse proxy. SVR.JS is licensed under a permissive MIT/X11 license",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "item-3",
|
||||||
|
question: "How was SVR.JS created?",
|
||||||
|
answer:
|
||||||
|
"Someone in 2018 wanted to create a website, but he didn't know about setting up popular web server software like Apache httpd, NGINX, or IIS... So he created his own web server in Node.JS to serve his website! And he saved it in a file called svr.js. Since then, this web server has been gradually turned from a web server intended for one website into a general-purpose web server, which is what SVR.JS is today!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "item-4",
|
||||||
|
question: "How did SVR.JS get its name?",
|
||||||
|
answer:
|
||||||
|
"SVR.JS got its name from the original name of the server script: svr.js, one of many generic file names for a server written in JavaScript.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "item-5",
|
||||||
|
question: "What is Node.JS?",
|
||||||
|
answer:
|
||||||
|
"Node.JS is an asynchronous event-driven JavaScript runtime built on Chromium's V8 engine. Node.JS is designed to build scalable network applications.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "item-6",
|
||||||
|
question: "How can I use SVR.JS?",
|
||||||
|
answer:
|
||||||
|
"You can <a href='/docs' className='text-white'>read its documentation</a> to learn how to use the SVR.JS web server.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
64
package-lock.json
generated
64
package-lock.json
generated
|
@ -11,6 +11,7 @@
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||||
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
"@radix-ui/react-navigation-menu": "^1.1.4",
|
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||||
|
@ -550,6 +551,38 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-accordion": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-collapsible": "1.0.3",
|
||||||
|
"@radix-ui/react-collection": "1.0.3",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.1",
|
||||||
|
"@radix-ui/react-context": "1.0.1",
|
||||||
|
"@radix-ui/react-direction": "1.0.1",
|
||||||
|
"@radix-ui/react-id": "1.0.1",
|
||||||
|
"@radix-ui/react-primitive": "1.0.3",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-alert-dialog": {
|
"node_modules/@radix-ui/react-alert-dialog": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.5.tgz",
|
||||||
|
@ -680,6 +713,37 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-collapsible": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.1",
|
||||||
|
"@radix-ui/react-context": "1.0.1",
|
||||||
|
"@radix-ui/react-id": "1.0.1",
|
||||||
|
"@radix-ui/react-presence": "1.0.1",
|
||||||
|
"@radix-ui/react-primitive": "1.0.3",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.1",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-collection": {
|
"node_modules/@radix-ui/react-collection": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz",
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||||
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
"@radix-ui/react-navigation-menu": "^1.1.4",
|
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||||
|
|
Loading…
Reference in a new issue