diff --git a/Cargo.lock b/Cargo.lock index 1318a3d..320aa0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -369,6 +369,8 @@ dependencies = [ "futures-util", "include_dir", "rapid-web", + "serde", + "serde_json", ] [[package]] @@ -1856,18 +1858,18 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.177" +version = "1.0.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63ba2516aa6bf82e0b19ca8b50019d52df58455d3cf9bdaf6315225fdd0c560a" +checksum = "60363bdd39a7be0266a520dab25fdc9241d2f987b08a01e01f0ec6d06a981348" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.177" +version = "1.0.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "401797fe7833d72109fedec6bfcbe67c0eed9b99772f26eb8afd261f0abc6fd3" +checksum = "f28482318d6641454cb273da158647922d1be6b5a2fcc6165cd89ebdd7ed576b" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 5d6178a..1fd6396 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" futures-util = "0.3.28" include_dir = "0.7.3" rapid-web = "0.4.7" +serde = { version = "1.0.178", features = ["serde_derive", "derive"] } +serde_json = "1.0.104" # Rapid binary [[bin]] diff --git a/app/header.tsx b/app/header.tsx new file mode 100644 index 0000000..64737ba --- /dev/null +++ b/app/header.tsx @@ -0,0 +1,149 @@ +"use client"; +import { Fragment } from "react"; +import { Popover, Transition } from "@headlessui/react"; +import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline"; +import Image from "next/image"; + +export type HeaderProps = { + navigation: { name: string; href: string }[]; +}; + +export function Header({ navigation }: HeaderProps) { + return ( + +
+ +
+ + + +
+
+
+ +
+
+ + + Close menu + +
+
+
+
+ {navigation.map((item) => ( + + {item.name} + + ))} +
+ +
+

+ Existing customer?{" "} + + Login + +

+
+
+
+
+
+
+ ); +} diff --git a/app/layout.tsx b/app/layout.tsx index 0941a55..7be3b2b 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,5 @@ import { Metadata } from "next"; +import "../styles/globals.css"; export const metadata: Metadata = { title: "Rapid App with NextJS App-Router", diff --git a/app/page.tsx b/app/page.tsx index 612fb99..7b26648 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,23 +1,668 @@ -import { Welcome, createBoltClient } from "@rapid-web/react"; +import { createBoltClient } from "@rapid-web/react"; import { routes, Handlers } from "../pages/api/bindings"; const bolt = createBoltClient(routes, { transport: "http://localhost:8080", }); +import { + ArrowPathIcon, + CloudArrowUpIcon, + CogIcon, + LockClosedIcon, + ServerIcon, + ShieldCheckIcon, +} from "@heroicons/react/24/outline"; +import { + ArrowTopRightOnSquareIcon, + ChevronRightIcon, +} from "@heroicons/react/20/solid"; +import { Header } from "./header"; +import Image from "next/image"; + +const navigation = [ + { name: "Product", href: "#" }, + { name: "Features", href: "#" }, + { name: "Marketplace", href: "#" }, + { name: "Company", href: "#" }, +]; +const features = [ + { + name: "Push to Deploy", + description: + "Ac tincidunt sapien vehicula erat auctor pellentesque rhoncus. Et magna sit morbi vitae lobortis.", + icon: CloudArrowUpIcon, + }, + { + name: "SSL Certificates", + description: + "Qui aut temporibus nesciunt vitae dicta repellat sit dolores pariatur. Temporibus qui illum aut.", + icon: LockClosedIcon, + }, + { + name: "Simple Queues", + description: + "Rerum quas incidunt deleniti quaerat suscipit mollitia. Amet repellendus ut odit dolores qui.", + icon: ArrowPathIcon, + }, + { + name: "Advanced Security", + description: + "Ullam laboriosam est voluptatem maxime ut mollitia commodi. Et dignissimos suscipit perspiciatis.", + icon: ShieldCheckIcon, + }, + { + name: "Powerful API", + description: + "Ab a facere voluptatem in quia corrupti veritatis aliquam. Veritatis labore quaerat ipsum quaerat id.", + icon: CogIcon, + }, + { + name: "Database Backups", + description: + "Quia qui et est officia cupiditate qui consectetur. Ratione similique et impedit ea ipsum et.", + icon: ServerIcon, + }, +]; +const blogPosts = [ + { + id: 1, + title: "Boost your conversion rate", + href: "#", + date: "Mar 16, 2020", + datetime: "2020-03-16", + category: { name: "Article", href: "#" }, + imageUrl: + "https://images.unsplash.com/photo-1496128858413-b36217c2ce36?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1679&q=80", + preview: + "Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto accusantium praesentium eius, ut atque fuga culpa, similique sequi cum eos quis dolorum.", + author: { + name: "Roel Aufderehar", + imageUrl: + "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + href: "#", + }, + readingLength: "6 min", + }, + { + id: 2, + title: "How to use search engine optimization to drive sales", + href: "#", + date: "Mar 10, 2020", + datetime: "2020-03-10", + category: { name: "Video", href: "#" }, + imageUrl: + "https://images.unsplash.com/photo-1547586696-ea22b4d4235d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1679&q=80", + preview: + "Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit facilis asperiores porro quaerat doloribus, eveniet dolore. Adipisci tempora aut inventore optio animi., tempore temporibus quo laudantium.", + author: { + name: "Brenna Goyette", + imageUrl: + "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + href: "#", + }, + readingLength: "4 min", + }, + { + id: 3, + title: "Improve your customer experience", + href: "#", + date: "Feb 12, 2020", + datetime: "2020-02-12", + category: { name: "Case Study", href: "#" }, + imageUrl: + "https://images.unsplash.com/photo-1492724441997-5dc865305da7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1679&q=80", + preview: + "Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint harum rerum voluptatem quo recusandae magni placeat saepe molestiae, sed excepturi cumque corporis perferendis hic.", + author: { + name: "Daniela Metz", + imageUrl: + "https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + href: "#", + }, + readingLength: "11 min", + }, +]; +const footerNavigation = { + solutions: [ + { name: "Marketing", href: "#" }, + { name: "Analytics", href: "#" }, + { name: "Commerce", href: "#" }, + { name: "Insights", href: "#" }, + ], + support: [ + { name: "Pricing", href: "#" }, + { name: "Documentation", href: "#" }, + { name: "Guides", href: "#" }, + { name: "API Status", href: "#" }, + ], + company: [ + { name: "About", href: "#" }, + { name: "Blog", href: "#" }, + { name: "Jobs", href: "#" }, + { name: "Press", href: "#" }, + { name: "Partners", href: "#" }, + ], + legal: [ + { name: "Claim", href: "#" }, + { name: "Privacy", href: "#" }, + { name: "Terms", href: "#" }, + ], + social: [ + { + name: "Facebook", + href: "#", + icon: (props: Omit, "ref">) => ( + + + + ), + }, + { + name: "Instagram", + href: "#", + icon: (props: Omit, "ref">) => ( + + + + ), + }, + { + name: "Twitter", + href: "#", + icon: (props: Omit, "ref">) => ( + + + + ), + }, + { + name: "GitHub", + href: "#", + icon: (props: Omit, "ref">) => ( + + + + ), + }, + { + name: "Dribbble", + href: "#", + icon: (props: Omit, "ref">) => ( + + + + ), + }, + ], +}; + export default async function Home() { - const { data: title } = await bolt("hello").get(routes.hello); + const { + data: { plain, colored }, + } = await bolt("hello").get(routes.hello); const { data: message } = await bolt("echo").post( routes.echo, - "Hello from the client!" + "Anim aute id magna aliqua ad ad non deserunt sunt. Quiirure qui Lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat." ); return ( -
- -

{title}

- The server replied: {message} -
-
+
+
+
+
+
+
+
+
+
+ + + We're hiring + + + Visit our careers page + + +

+ {plain} + + {colored} + +

+

+ {message} +

+
+
+
+
+ + +
+
+ +
+
+

+ Start your free 14-day trial, no credit card + necessary. By providing your email, you agree to our{" "} + + terms of service + + . +

+
+
+
+
+
+
+ {/* Illustration taken from Lucid Illustrations: https://lucid.pixsellz.io/ */} + +
+
+
+
+
+ + {/* Feature section with screenshot */} +
+
+
+

+ Serverless +

+

+ No server? No problem. +

+

+ Phasellus lorem quam molestie id quisque diam aenean nulla in. + Accumsan in quis quis nunc, ullamcorper malesuada. Eleifend + condimentum id viverra nulla. +

+
+
+ +
+
+
+ + {/* Feature section with grid */} +
+
+

+ Deploy faster +

+

+ Everything you need to deploy your app +

+

+ Phasellus lorem quam molestie id quisque diam aenean nulla in. + Accumsan in quis quis nunc, ullamcorper malesuada. Eleifend + condimentum id viverra nulla. +

+
+
+ {features.map((feature) => ( +
+
+
+
+ + +
+

+ {feature.name} +

+

+ {feature.description} +

+
+
+
+ ))} +
+
+
+
+ + {/* Testimonial section */} +
+
+
+ +
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Sed urna nulla vitae laoreet augue. Amet feugiat est + integer dolor auctor adipiscing nunc urna, sit. +

+
+
+

+ Judith Black +

+

+ CEO at PureInsights +

+
+
+
+
+
+
+ + {/* Blog section */} +
+
+
+

Learn

+

+ Helpful Resources +

+

+ Phasellus lorem quam molestie id quisque diam aenean nulla in. + Accumsan in quis quis nunc, ullamcorper malesuada. Eleifend + condimentum id viverra nulla. +

+
+
+ {blogPosts.map((post) => ( +
+
+ +
+
+ +
+
+ + {post.author.name} + +
+
+

+ + {post.author.name} + +

+
+ + + {post.readingLength} read +
+
+
+
+
+ ))} +
+
+
+ + {/* CTA Section */} +
+
+ + +
+
+

+ Award winning support +

+

+ We’re here to help +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Et, + egestas tempus tellus etiam sed. Quam a scelerisque amet + ullamcorper eu enim et fermentum, augue. Aliquet amet volutpat + quisque ut interdum tincidunt duis. +

+ +
+
+
+
+ +
+
); } diff --git a/package-lock.json b/package-lock.json index 76f5737..013b0ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "name": "rapid-nextjs-testing", "version": "0.1.0", "dependencies": { + "@heroicons/react": "^2.0.18", + "@icons-pack/react-simple-icons": "^8.0.1", "@rapid-web/react": "^0.2.4", "@types/node": "20.4.2", "@types/react": "18.2.15", @@ -24,10 +26,13 @@ }, "devDependencies": { "@rapid-web/ui": "^0.2.2", + "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/forms": "^0.5.4", "concurrently": "^8.2.0", "eslint-config-prettier": "^8.9.0", "prettier": "^2.8.8", "prettier-plugin-rust": "^0.1.9", + "prettier-plugin-tailwindcss": "^0.4.1", "prettier-plugin-toml": "^0.3.1", "rimraf": "^5.0.1" } @@ -175,6 +180,14 @@ "react-dom": "^16 || ^17 || ^18" } }, + "node_modules/@heroicons/react": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz", + "integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==", + "peerDependencies": { + "react": ">= 16" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", @@ -205,6 +218,14 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, + "node_modules/@icons-pack/react-simple-icons": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@icons-pack/react-simple-icons/-/react-simple-icons-8.0.1.tgz", + "integrity": "sha512-lCdPSp+EFJKDabwQ16pQsTJKViwGa8naoYAnL0IpxQvl7E1CeQ7Z84BbJWhIustrrdNIZwcyuKg+ClPi7BXFWw==", + "peerDependencies": { + "react": "^16.13 || ^17 || ^18" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -591,6 +612,27 @@ "tslib": "^2.4.0" } }, + "node_modules/@tailwindcss/aspect-ratio": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz", + "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==", + "dev": true, + "peerDependencies": { + "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + } + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.4.tgz", + "integrity": "sha512-YAm12D3R7/9Mh4jFbYSMnsd6jG++8KxogWgqs7hbdo/86aWjjlIEvL7+QYdVELmAI0InXTpZqFIg5e7aDVWI2Q==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" + } + }, "node_modules/@toml-tools/lexer": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@toml-tools/lexer/-/lexer-0.3.1.tgz", @@ -3244,6 +3286,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3890,6 +3941,80 @@ "prettier": "^2.7.1" } }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz", + "integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==", + "dev": true, + "engines": { + "node": ">=12.17.0" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@shufo/prettier-plugin-blade": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "prettier": "^2.2 || ^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*", + "prettier-plugin-twig-melody": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@shufo/prettier-plugin-blade": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "prettier-plugin-twig-melody": { + "optional": true + } + } + }, "node_modules/prettier-plugin-toml": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/prettier-plugin-toml/-/prettier-plugin-toml-0.3.1.tgz", diff --git a/package.json b/package.json index dd7338a..517b8b0 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "clean@rust": "cargo clean" }, "dependencies": { + "@heroicons/react": "^2.0.18", + "@icons-pack/react-simple-icons": "^8.0.1", "@rapid-web/react": "^0.2.4", "@types/node": "20.4.2", "@types/react": "18.2.15", @@ -32,10 +34,13 @@ }, "devDependencies": { "@rapid-web/ui": "^0.2.2", + "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/forms": "^0.5.4", "concurrently": "^8.2.0", "eslint-config-prettier": "^8.9.0", "prettier": "^2.8.8", "prettier-plugin-rust": "^0.1.9", + "prettier-plugin-tailwindcss": "^0.4.1", "prettier-plugin-toml": "^0.3.1", "rimraf": "^5.0.1" } diff --git a/pages/api/bindings.ts b/pages/api/bindings.ts index d2dc866..72215bd 100644 --- a/pages/api/bindings.ts +++ b/pages/api/bindings.ts @@ -9,7 +9,7 @@ export interface Handlers { }, "hello": { - output: string + output: HelloResponse type: 'query' isDynamic: false }, @@ -36,4 +36,9 @@ export const routes = { url: '/echo', type: 'post', }, -} as const \ No newline at end of file +} as const + +export interface HelloResponse { + plain: string; + colored: string; +} \ No newline at end of file diff --git a/pages/api/routes/hello.rs b/pages/api/routes/hello.rs index 4110842..e58fd57 100644 --- a/pages/api/routes/hello.rs +++ b/pages/api/routes/hello.rs @@ -1,10 +1,20 @@ use rapid_web::actix::HttpResponse; use rapid_web::rapid_web_codegen::rapid_handler; +use serde::{ Serialize, Deserialize }; pub const ROUTE_KEY: &str = "hello"; -pub type RapidOutput = String; +pub type RapidOutput = HelloResponse; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct HelloResponse { + plain: String, + colored: String, +} #[rapid_handler] pub async fn query() -> HttpResponse { - HttpResponse::Ok().body("Hello from a RAPID rust endpoint!") + HttpResponse::Ok().json(HelloResponse { + plain: "Rapid, Rust powered NextJS for".to_string(), + colored: "a faster web!".to_string(), + }) } diff --git a/tailwind.config.ts b/tailwind.config.ts index 13e0a83..450ca8c 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -4,11 +4,14 @@ import { rapidTailwindTheme, rapidPlugin, } from "@rapid-web/ui"; +import tailwindForms from "@tailwindcss/forms" +import tailwindAspect from "@tailwindcss/aspect-ratio" // Use this as your template paths directory if using nextjs app dir: "./app/**/*.{js,ts,jsx,tsx,mdx}", export default { content: [ + "./app/**/*.{js,ts,jsx,tsx}", "./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", rapidStylesPath, @@ -19,6 +22,8 @@ export default { }), }, plugins: [ + tailwindForms({}), + tailwindAspect, rapidPlugin({ // Configure global styles variants here (documentation coming soon) global: {},