From 1b983e8c7e0dd2b4325161785664f38799de7e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Fri, 21 Oct 2022 17:44:48 +0200 Subject: [PATCH] Feat(www): shuttle beta signup (#421) * feat(www): add beta signup form * feat: add formspree endpoint * feat: remove socials footer from beta page * feat: add dummy text above sign up form * feat: placeholder gif * feat: align dummy text left * feat: remove gif, add text * feat: update beta page text * feat: update the rest of the site --- www/components/BetaHero.tsx | 29 ++++ www/components/Examples.tsx | 2 +- www/components/Features.tsx | 23 ++- www/components/Footer.tsx | 31 +--- www/components/Header.tsx | 1 + www/components/SignupForm.tsx | 85 ++++++++++ www/components/Socials.tsx | 52 +++++++ www/lib/constants.ts | 10 +- www/package.json | 1 + www/pages/beta.tsx | 11 ++ www/pages/blog.tsx | 2 + www/pages/index.tsx | 2 + www/pages/pricing.tsx | 286 +++++++++++++++++----------------- 13 files changed, 348 insertions(+), 187 deletions(-) create mode 100644 www/components/BetaHero.tsx create mode 100644 www/components/SignupForm.tsx create mode 100644 www/components/Socials.tsx create mode 100644 www/pages/beta.tsx diff --git a/www/components/BetaHero.tsx b/www/components/BetaHero.tsx new file mode 100644 index 000000000..35284b336 --- /dev/null +++ b/www/components/BetaHero.tsx @@ -0,0 +1,29 @@ +import { useRouter } from "next/router"; +import SignupForm from "./SignupForm"; + +const BetaHero = () => { + const { basePath } = useRouter(); + return ( +
+
+
+
+
+ Shuttle + + BETA + +
+ +
+
+
+
+ ); +}; + +export default BetaHero; diff --git a/www/components/Examples.tsx b/www/components/Examples.tsx index 575ec570f..3792cee87 100644 --- a/www/components/Examples.tsx +++ b/www/components/Examples.tsx @@ -40,7 +40,7 @@ export default function Examples() {

- From code to cloud in a minute + The Fastest Development Experience, ever.

Take your code to full-featured cloud infrastructure in under a diff --git a/www/components/Features.tsx b/www/components/Features.tsx index 7a8b24d67..ae14d7e82 100644 --- a/www/components/Features.tsx +++ b/www/components/Features.tsx @@ -2,29 +2,27 @@ import { CheckIcon } from "@heroicons/react/outline"; const features = [ { - name: "Infrastructure from Rust", + name: "Skip the AWS console", description: - "Traits and annotations define all your infrastructure from your service code", + "Configure your infrastructure directly from your Rust code. Avoid unnecessary context-switching and complicated UIs.", }, { - name: "Serverless", + name: "Compile-time insurance", description: - "All the infrastructure and wiring you need is handled by the deployer runtime. No VMs or containers", + "Know that you are getting what you need at compile-time. Cut down on debugging time.", }, { name: "Databases", description: - "Wiring up a service to a persistent database is as easy as deriving a trait", + "Wiring up a service to a persistent database is as easy as adding one line of code. And we support multiple providers.", }, { name: "Entirely open-source", - description: - "A completely free and open-source project, with no vendor lock-in or hidden code", + description: "A completely free and open-source project.", }, { - name: "Self-hosting friendly", - description: - "Deploy the entire platform under your own AWS account for extra security and isolation", + name: "Generous free tier", + description: "Start deploying your apps with no strings attached.", }, { name: "Fast deploy times", @@ -42,11 +40,10 @@ export default function Features() {

- Serverless for Rust + Deploy Apps with a Single Command

- The only serverless platform that lets you control your - infrastructure from Rust code as easily as deriving a trait. + Control your infrastructure by adding annotations to your code.

diff --git a/www/components/Footer.tsx b/www/components/Footer.tsx index aed55c9fb..01dededb8 100644 --- a/www/components/Footer.tsx +++ b/www/components/Footer.tsx @@ -100,14 +100,11 @@ export default function Footer() { ))}
- + {/*

Let's make Rust the next language of cloud-native

-

- We love you Go, but Rust is just better. -

{communities.map((community, index) => ( ))}
-
- - {/*
-

- Ready to dive in? - - Start your free trial today. - -

-
- - Get Started - - - - Join Discord - -
*/} + {/* */} +
{navigation.map((col, index) => ( diff --git a/www/components/Header.tsx b/www/components/Header.tsx index 8f9ff7ac4..69ac34392 100644 --- a/www/components/Header.tsx +++ b/www/components/Header.tsx @@ -12,6 +12,7 @@ const navigation = [ { name: "Docs", href: SHUTTLE_DOCS_URL, internal: false }, { name: "Blog", href: "/blog", internal: true }, { name: "Pricing", href: "/pricing", internal: true }, + { name: "Beta", href: "/beta", internal: true }, ]; export default function Header() { diff --git a/www/components/SignupForm.tsx b/www/components/SignupForm.tsx new file mode 100644 index 000000000..24ce6ff82 --- /dev/null +++ b/www/components/SignupForm.tsx @@ -0,0 +1,85 @@ +import { useForm, ValidationError } from "@formspree/react"; +import { + CONTRIBUTING_URL, + DISCORD_URL, + FORMSPREE_ENDPOINT, + GITHUB_URL, + TWITTER_URL, +} from "../lib/constants"; +import ExternalLink from "./ExternalLink"; +import Image from "next/image"; +const links = [ + { name: "💻 contributing to shuttle", href: CONTRIBUTING_URL }, + { name: "⭐️ starring the repository", href: GITHUB_URL }, + { name: "👾 joining our discord community", href: DISCORD_URL }, + { name: "🐦 following us on twitter", href: TWITTER_URL }, +]; +export default function SignupForm() { + const [state, handleSubmit] = useForm(FORMSPREE_ENDPOINT); + + if (state.succeeded) { + return ( +
+

+ Thank you for registering your interest in the next iteration of + shuttle. +

+

+ If you are looking for a way to support shuttle in the meantime, you + can do so by: +

+
+ {links.map((link) => ( + + {link.name} + + ))} +
+
+ ); + } + return ( + <> +
+
+ Build Backends. Fast. +
+
+ Sign up to our closed beta and get updated on the{" "} + { + + next iteration of shuttle + + } + , a serverless backend framework with the fastest build, test and + deploy times ever. +
+
+
+ + + + + + ); +} diff --git a/www/components/Socials.tsx b/www/components/Socials.tsx new file mode 100644 index 000000000..a415d7252 --- /dev/null +++ b/www/components/Socials.tsx @@ -0,0 +1,52 @@ +import { + faDiscord, + faGithub, + faTwitter, +} from "@fortawesome/free-brands-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { DISCORD_URL, GITHUB_URL, TWITTER_URL } from "../lib/constants"; +import ExternalLink from "./ExternalLink"; + +const communities = [ + { + name: "Github", + href: GITHUB_URL, + icon: faGithub, + }, + { + name: "Discord", + href: DISCORD_URL, + icon: faDiscord, + }, + { + name: "Twitter", + href: TWITTER_URL, + icon: faTwitter, + }, +]; + +export default function Socials() { + return ( +
+

+ Let's Build the Future of Backend Development Together +

+ +
+ {communities.map((community, index) => ( + + + {community.name} + + ))} +
+
+ ); +} diff --git a/www/lib/constants.ts b/www/lib/constants.ts index a8e071ac7..d606963f1 100644 --- a/www/lib/constants.ts +++ b/www/lib/constants.ts @@ -1,18 +1,20 @@ export const APP_NAME = "shuttle"; -export const SITE_TITLE = "Stateful Serverless for Rust"; +export const SITE_TITLE = "Build Backends. Fast."; export const SITE_DESCRIPTION = - "Shuttle is a web application platform that uses traits and annotations to configure your backend deployment - including databases."; + "Stop worrying about the infrastructure. Focus on writing code, shuttle will do the rest."; export const SITE_URL = "https://shuttle.rs/"; export const TWITTER_HANDLE = "@shuttle_dev"; export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID; +export const FORMSPREE_ENDPOINT = process.env.NEXT_PUBLIC_FORMSPREE_ENDPOINT; export const GITHUB_URL = "https://github.com/shuttle-hq/shuttle"; export const DISCORD_URL = "https://discord.gg/shuttle"; export const TWITTER_URL = "https://twitter.com/shuttle_dev"; -export const SHUTTLE_DOCS_URL = - "https://docs.shuttle.rs/"; +export const SHUTTLE_DOCS_URL = "https://docs.shuttle.rs/"; +export const CONTRIBUTING_URL = + "https://github.com/shuttle-hq/shuttle/blob/main/CONTRIBUTING.md"; diff --git a/www/package.json b/www/package.json index 07a5d3433..92e7c340f 100644 --- a/www/package.json +++ b/www/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@auth0/nextjs-auth0": "^1.7.0", + "@formspree/react": "^2.4.0", "@fortawesome/fontawesome-svg-core": "^6.1.0", "@fortawesome/free-brands-svg-icons": "^6.1.0", "@fortawesome/free-regular-svg-icons": "^6.1.0", diff --git a/www/pages/beta.tsx b/www/pages/beta.tsx new file mode 100644 index 000000000..2aac0db04 --- /dev/null +++ b/www/pages/beta.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +import BetaHero from "../components/BetaHero"; + +export default function ShuttleNext() { + return ( + <> + + + ); +} diff --git a/www/pages/blog.tsx b/www/pages/blog.tsx index 750fb1a0f..5f506cb58 100644 --- a/www/pages/blog.tsx +++ b/www/pages/blog.tsx @@ -9,6 +9,7 @@ import { SITE_URL } from "../lib/constants"; import { GetStaticPropsResult } from "next"; import InternalLink from "../components/InternalLink"; import classnames from "classnames"; +import Socials from "../components/Socials"; export async function getStaticProps(): Promise> { const allPostsData = getSortedPosts(); @@ -142,6 +143,7 @@ export default function Blog(props: Props): JSX.Element {
+ ); } diff --git a/www/pages/index.tsx b/www/pages/index.tsx index 3635a3e48..03bc4d294 100644 --- a/www/pages/index.tsx +++ b/www/pages/index.tsx @@ -3,6 +3,7 @@ import Examples from "../components/Examples"; import CodeSnippets from "../components/CodeSnippets"; import Features from "../components/Features"; import Hero from "../components/Hero"; +import Socials from "../components/Socials"; export default function Home() { return ( @@ -11,6 +12,7 @@ export default function Home() { + ); } diff --git a/www/pages/pricing.tsx b/www/pages/pricing.tsx index 69a343f6e..a97212c4a 100644 --- a/www/pages/pricing.tsx +++ b/www/pages/pricing.tsx @@ -4,6 +4,7 @@ import classnames from "classnames"; import { DISCORD_URL } from "../lib/constants"; import ExternalLink from "../components/ExternalLink"; import LoginButton from "../components/LoginButton"; +import Socials from "../components/Socials"; const tiers = [ { @@ -114,167 +115,170 @@ const sections = [ export default function Pricing() { return ( -
-
- {/* xs to lg */} -
- {tiers.map((tier, tierIdx) => ( -
-
-

- {tier.name} -

-

{tier.price}

-

- {tier.description} -

- -
+ <> +
+
+ {/* xs to lg */} +
+ {tiers.map((tier, tierIdx) => ( +
+
+

+ {tier.name} +

+

{tier.price}

+

+ {tier.description} +

+ +
- {sections.map((section) => ( - - - - - - - - - - {section.features.map((feature) => ( - - + {section.features.map((feature) => ( + + + + + ))} + +
- {section.name} -
- Feature - - Included -
- {feature.name} + {sections.map((section) => ( + + + + + + - - ))} - -
+ {section.name} +
+ Feature + + Included - - {feature.tiers[tier.name]} - -
- ))} - -
- -
- - ))} - + +
+ {feature.name} + + + {feature.tiers[tier.name]} + +
+ ))} - {/* lg+ */} -
- - - - - - {tiers.map((tier) => ( + + + + ))} + + + {/* lg+ */} +
+
Pricing plan comparison
- Feature by - Plans -
+ + + - ))} - - - - - - {tiers.map((tier) => ( - - ))} - - {sections.map((section) => ( - - + {tiers.map((tier) => ( - - {section.features.map((feature) => ( - + ))} + + + + + + {tiers.map((tier) => ( + + ))} + + {sections.map((section) => ( + + - {tiers.map((tier) => ( - - ))} - ))} - - ))} - - - - - {tiers.map((tier) => ( - + {section.features.map((feature) => ( + + + {tiers.map((tier) => ( + + ))} + + ))} + ))} - - -
Pricing plan comparison
- {tier.name} + Feature by + Plans
- Pricing - -
-

{tier.price}

-

- {tier.description} -

- -
-
- {section.name} + {tier.name}
+ Pricing + +
+

{tier.price}

+

+ {tier.description} +

+ +
+
- {feature.name} + {section.name} - - {feature.tiers[tier.name]} - -
- Choose your plan - - -
+ {feature.name} + + + {feature.tiers[tier.name]} + +
+ + + + + Choose your plan + + {tiers.map((tier) => ( + + + + ))} + + + +
-
+ + ); }