├── src ├── styles │ ├── Footer.module.css │ ├── globals.css │ ├── VideoCard.module.css │ ├── Header.module.css │ ├── TestimonialCard.module.css │ ├── Icon.module.css │ ├── ProductCard.module.css │ ├── BlogCard.module.css │ └── Home.module.css ├── pages │ ├── _app.js │ ├── api │ │ └── hello.js │ ├── index.js │ └── [...page].js └── components │ ├── footer.js │ ├── icons.js │ ├── icon-blob.js │ ├── with-tooltip.js │ ├── code-block.js │ ├── cards │ ├── video-card.js │ ├── testimonial-card.js │ ├── blog-card.js │ └── product-card.js │ ├── icon-component.js │ └── header.js ├── .eslintrc.json ├── public ├── favicon.ico ├── images │ └── drag-and-drop.png ├── svgs │ ├── orange-rhomboid.svg │ ├── yellow-oblong.svg │ ├── long-yellow-arrow.svg │ ├── v-face.svg │ ├── pink-play.svg │ ├── orange-palette-blob.svg │ ├── yellow-smile.svg │ ├── purple-circle.svg │ ├── angular.svg │ ├── yellow-dots.svg │ ├── pink-triangle.svg │ ├── purple-straight-face.svg │ ├── purple-rhomboid.svg │ ├── pointer.svg │ ├── s-block.svg │ ├── circle-arrow.svg │ ├── yellow-right-arrow.svg │ ├── blue-atom.svg │ ├── multi-color-f.svg │ ├── pink-arrow.svg │ ├── yellow-smiley-blob.svg │ └── blue-cloud.svg └── vercel.svg ├── next.config.js ├── .gitignore ├── package.json └── README.md /src/styles/Footer.module.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BuilderIO/demo-editor/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/images/drag-and-drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BuilderIO/demo-editor/HEAD/public/images/drag-and-drop.png -------------------------------------------------------------------------------- /src/pages/_app.js: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | 3 | function MyApp({ Component, pageProps }) { 4 | return 5 | } 6 | 7 | export default MyApp 8 | -------------------------------------------------------------------------------- /src/components/footer.js: -------------------------------------------------------------------------------- 1 | import styles from "../styles/Footer.module.css"; 2 | 3 | export function MyFooter() { 4 | return ( 5 |
6 | // TOOD: add a custom footer 7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /src/pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default function handler(req, res) { 4 | res.status(200).json({ name: 'John Doe' }) 5 | } 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | swcMinify: true, 5 | images: { 6 | domains: ["cdn.builder.io"], 7 | }, 8 | }; 9 | 10 | module.exports = nextConfig; 11 | -------------------------------------------------------------------------------- /public/svgs/orange-rhomboid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/svgs/yellow-oblong.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | background: black; 6 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 7 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 8 | } 9 | 10 | a { 11 | color: inherit; 12 | text-decoration: none; 13 | } 14 | 15 | * { 16 | box-sizing: border-box; 17 | } 18 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /src/styles/VideoCard.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | max-width: 354px; 5 | background: #1a73e8; 6 | margin: auto; 7 | } 8 | 9 | .title { 10 | margin: 50px 20px 10px; 11 | font-family: "Poppins"; 12 | font-weight: 600; 13 | font-size: 30px; 14 | line-height: 38px; 15 | text-align: center; 16 | color: #ffffff; 17 | } 18 | 19 | .video { 20 | /* opacity: 0.9; */ 21 | /* mix-blend-mode: multiply; */ 22 | max-width: 100%; 23 | } 24 | -------------------------------------------------------------------------------- /public/svgs/long-yellow-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/components/icons.js: -------------------------------------------------------------------------------- 1 | export const iconUrls = [ 2 | "/svgs/blue-atom.svg", 3 | "/svgs/long-yellow-arrow.svg", 4 | "/svgs/multi-color-f.svg", 5 | "/svgs/pink-triangle.svg", 6 | "/svgs/pointer.svg", 7 | "/svgs/purple-circle.svg", 8 | "/svgs/purple-rhomboid.svg", 9 | "/svgs/s-block.svg", 10 | "/svgs/yellow-dots.svg", 11 | "/svgs/yellow-oblong.svg", 12 | "/svgs/yellow-smile.svg", 13 | "/svgs/circle-arrow.svg", 14 | "/svgs/blue-cloud.svg", 15 | "/svgs/purple-straight-face.svg", 16 | "/svgs/pink-arrow.svg", 17 | "/svgs/angular.svg", 18 | "/svgs/v-face.svg", 19 | "/svgs/orange-rhomboid.svg", 20 | "/svgs/pink-play.svg", 21 | ].sort(() => Math.random() - 0.5); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-editor", 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 | "@builder.io/react": "^2.0.1", 13 | "@builder.io/widgets": "^1.2.23", 14 | "@emotion/react": "^11.10.4", 15 | "@emotion/styled": "^11.10.4", 16 | "@mui/material": "^5.10.3", 17 | "next": "12.2.2", 18 | "react": "18.2.0", 19 | "react-dom": "18.2.0", 20 | "react-syntax-highlighter": "^15.5.0" 21 | }, 22 | "devDependencies": { 23 | "eslint": "8.20.0", 24 | "eslint-config-next": "12.2.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/styles/Header.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | backdrop-filter: saturate(180%) blur(5px); 3 | box-shadow: inset 0 -1px 0 0 hsla(0, 0%, 100%, 0.1); 4 | position: sticky; 5 | top: 0; 6 | background: rgba(0, 0, 0, 0.5); 7 | display: flex; 8 | justify-content: center; 9 | color: white; 10 | height: 64px; 11 | z-index: 2; 12 | } 13 | 14 | .innerContainer { 15 | width: 1200px; 16 | max-width: 100%; 17 | padding: 0 15px; 18 | display: flex; 19 | align-items: center; 20 | justify-content: space-between; 21 | flex-direction: row; 22 | } 23 | 24 | .titleContainer { 25 | display: flex; 26 | align-items: center; 27 | flex-direction: row; 28 | flex-wrap: wrap; 29 | } 30 | 31 | .title { 32 | margin: 0px 15px; 33 | } 34 | 35 | .repoLink { 36 | cursor: pointer; 37 | } 38 | 39 | .repoLink:hover { 40 | text-decoration: underline; 41 | } 42 | -------------------------------------------------------------------------------- /src/components/icon-blob.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Image from "next/image"; 3 | 4 | export const IconBlob = (props) => ( 5 | { 12 | const randomDirectionNumber = Math.random(); 13 | const randomAxisNumber = Math.random(); 14 | const direction = randomDirectionNumber > 0.5 ? 1 : -1; 15 | const axis = 16 | randomAxisNumber > 0.7 17 | ? `0,0,${direction}` 18 | : randomAxisNumber > 0.3 19 | ? `0,${direction},0` 20 | : `${direction},0,0`; 21 | event.target.style.transform = `rotate3d(${axis},360deg)`; 22 | }} 23 | onMouseOut={(event) => { 24 | event.target.style.transform = "rotate3d(0,0,1,0)"; 25 | }} 26 | src={props.icon} 27 | height="75" 28 | width="75" 29 | /> 30 | ); 31 | -------------------------------------------------------------------------------- /src/components/with-tooltip.js: -------------------------------------------------------------------------------- 1 | import Tooltip from "@mui/material/Tooltip"; 2 | 3 | // HOC to add a tooltip to a component's source on hover, for demo purposes 4 | export function withTooltip(url, Component) { 5 | return function SourceCodeTooltipWrappedComponent(props) { 6 | return ( 7 | { 16 | // Open with JS so will open in visual editor 17 | // (by default links are intentionally disabled in the visual editor) 18 | open(url, "_blank"); 19 | }} 20 | > 21 | Click here to view my source code 22 | 23 | } 24 | > 25 |
26 | 27 |
28 |
29 | ); 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/code-block.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Builder } from "@builder.io/react"; 3 | import { gruvboxDark } from "react-syntax-highlighter/dist/cjs/styles/hljs"; 4 | import SyntaxHighlighter from "react-syntax-highlighter"; 5 | import { withTooltip } from "./with-tooltip"; 6 | 7 | const CodeBlock = (props) => ( 8 | 9 | {props.code} 10 | 11 | ); 12 | 13 | // Wrap our component with a tooltip pointing to it's source code 14 | const DemoCodeBlock = withTooltip( 15 | "https://github.com/BuilderIO/demo-editor/blob/main/src/components/code-block.js", 16 | CodeBlock 17 | ); 18 | 19 | // Learn about registering custom components: https://www.builder.io/c/docs/custom-components-intro 20 | Builder.registerComponent(DemoCodeBlock, { 21 | name: "CodeBlock", 22 | image: 'https://tabler-icons.io/static/tabler-icons/icons-png/code-plus.png', 23 | inputs: [ 24 | { 25 | name: "code", 26 | type: "longText", 27 | defaultValue: "const incr = num => num + 1", 28 | }, 29 | { 30 | name: "language", 31 | type: "string", 32 | defaultValue: "javascript", 33 | }, 34 | ], 35 | }); 36 | -------------------------------------------------------------------------------- /src/styles/TestimonialCard.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | padding: 32px 24px; 6 | gap: 16px; 7 | background: #1a1b23; 8 | box-shadow: -4px 4px 8px rgba(0, 0, 0, 0.11); 9 | border-radius: 18px; 10 | max-width: 354px; 11 | margin: auto; 12 | } 13 | 14 | .divider { 15 | display: flex; 16 | width: 100%; 17 | height: 0.5px; 18 | margin: 16px 0; 19 | background: rgba(255, 255, 255, 0.2); 20 | } 21 | 22 | .quote { 23 | display: flex; 24 | align-items: center; 25 | font-family: "PT Mono"; 26 | font-style: normal; 27 | font-weight: 700; 28 | font-size: 100px; 29 | text-align: center; 30 | color: #18b6f6; 31 | } 32 | 33 | .testimonialDetails { 34 | text-align: center; 35 | font-style: normal; 36 | font-weight: 400; 37 | font-size: 16px; 38 | line-height: 150%; 39 | color: #ffffff; 40 | } 41 | 42 | .testimonialDetails p { 43 | margin-bottom: 47px; 44 | } 45 | 46 | .customer { 47 | font-weight: 600; 48 | font-size: 12px; 49 | text-align: center; 50 | text-transform: uppercase; 51 | color: #ffffff; 52 | } 53 | 54 | .customerDetails { 55 | font-weight: 400; 56 | font-size: 12px; 57 | text-align: center; 58 | color: rgba(255, 255, 255, 0.8); 59 | } 60 | -------------------------------------------------------------------------------- /public/svgs/v-face.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/svgs/pink-play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/components/cards/video-card.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Builder } from "@builder.io/react"; 3 | import styles from "../../styles/VideoCard.module.css"; 4 | import { withTooltip } from "../with-tooltip"; 5 | 6 | export default function VideoCard(props) { 7 | return ( 8 |
9 |
{props.title}
10 | 11 |
12 | ); 13 | } 14 | 15 | // Wrap our component with a tooltip pointing to it's source code 16 | const DemoVideoCard = withTooltip( 17 | "https://github.com/BuilderIO/demo-editor/blob/main/src/components/cards/video-card.js", 18 | VideoCard 19 | ); 20 | 21 | // Learn about registering custom components: https://www.builder.io/c/docs/custom-components-intro 22 | Builder.registerComponent(DemoVideoCard, { 23 | name: "VideoCard", 24 | image: 'https://tabler-icons.io/static/tabler-icons/icons-png/brand-youtube.png', 25 | inputs: [ 26 | { 27 | name: "title", 28 | type: "string", 29 | defaultValue: "Make Your Product the Star of the Show", 30 | }, 31 | { 32 | name: "video", 33 | type: "file", 34 | allowedFileTypes: ["mp4"], 35 | defaultValue: 36 | "https://cdn.builder.io/o/assets%2F21cf4c80eb1941fab464c19faa3a1c42%2F0ad5500130f34806984c24f2003d1437%2Fcompressed?apiKey=21cf4c80eb1941fab464c19faa3a1c42&token=0ad5500130f34806984c24f2003d1437&alt=media&optimized=true", 37 | }, 38 | ], 39 | }); 40 | -------------------------------------------------------------------------------- /src/styles/Icon.module.css: -------------------------------------------------------------------------------- 1 | .iconContainer { 2 | display: flex; 3 | width: 100%; 4 | padding: 30px 55px; 5 | } 6 | 7 | @media (max-width: 991px) { 8 | .iconContainer { 9 | flex-direction: column; 10 | align-items: center; 11 | padding: 30px 10px; 12 | } 13 | } 14 | 15 | .blobContainer { 16 | width: 50%; 17 | display: flex; 18 | flex-wrap: wrap; 19 | justify-content: center; 20 | } 21 | 22 | @media (max-width: 991px) { 23 | .blobContainer { 24 | margin: 0; 25 | width: 75%; 26 | } 27 | } 28 | 29 | @media (max-width: 345px) { 30 | .blobContainer { 31 | margin: 0; 32 | width: 100%; 33 | } 34 | } 35 | 36 | .heroContainer { 37 | width: 50%; 38 | margin-left: 45px; 39 | } 40 | 41 | @media (max-width: 991px) { 42 | .heroContainer { 43 | margin: 0; 44 | width: 75%; 45 | text-align: center; 46 | } 47 | } 48 | 49 | .heroLeadText { 50 | color: #ac7ef4; 51 | text-transform: uppercase; 52 | font-family: monospace; 53 | font-weight: 700; 54 | font-size: 16px; 55 | margin-top: 20px; 56 | } 57 | 58 | .heroTitleText { 59 | color: white; 60 | font-weight: 600; 61 | font-size: 36px; 62 | margin: 16px 0; 63 | } 64 | 65 | .heroDescription { 66 | color: white; 67 | font-size: 16px; 68 | line-height: 1.5rem; 69 | } 70 | 71 | .heroCallout { 72 | display: flex; 73 | align-items: center; 74 | padding: 0 15px; 75 | color: white; 76 | border: 4px solid #f7c92e; 77 | border-radius: 99px; 78 | margin-top: 57px; 79 | } 80 | 81 | .heroCalloutText { 82 | margin-left: 10px; 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Builder.io Demo App 2 | 3 | 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), with Builder.io integrated for our [editor demo](https://builder.io/demo) 4 | 5 | ## To run locally: 6 | 7 | First, run the development server: 8 | 9 | ```bash 10 | npm run dev 11 | # or 12 | yarn dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 18 | 19 | [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.js`. 20 | 21 | 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. 22 | 23 | ## Learn More 24 | 25 | To learn more about [Builder.io](https://www.builder.io), take a look at the following resources: 26 | 27 | - [Builder.io developer docs](https://www.builder.io/c/docs/developers) 28 | 29 | To learn more about Next.js, take a look at the following resources: 30 | 31 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 32 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 33 | 34 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 35 | -------------------------------------------------------------------------------- /src/styles/ProductCard.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | max-width: 354px; 5 | margin: auto; 6 | color: #121212; 7 | } 8 | 9 | .imageContainer { 10 | display: flex; 11 | justify-content: center; 12 | padding: 52px 0; 13 | width: 100%; 14 | background: #f6af3a; 15 | } 16 | 17 | .productInfo { 18 | background: white; 19 | padding: 24px; 20 | } 21 | 22 | .productTitle { 23 | font-weight: 600; 24 | font-size: 22px; 25 | margin-bottom: 8px; 26 | } 27 | 28 | .productPrice { 29 | font-weight: 600; 30 | font-size: 22px; 31 | color: rgba(0, 0, 0, 0.6); 32 | } 33 | 34 | .divider { 35 | display: flex; 36 | width: 100%; 37 | height: 0.5px; 38 | margin: 22px 0; 39 | background: rgba(0, 0, 0, 0.2); 40 | } 41 | 42 | .productDetails { 43 | display: flex; 44 | justify-content: space-between; 45 | cursor: pointer; 46 | align-items: center; 47 | } 48 | 49 | .dropdown { 50 | display: inline-block; 51 | width: 8px; 52 | height: 8px; 53 | margin-right: 3px; 54 | border: 2px solid #485350; 55 | border-bottom: none; 56 | border-left: none; 57 | transform: rotate(-45deg); 58 | transition: rotate 250ms ease-in-out; 59 | } 60 | 61 | .productDescription { 62 | font-size: 16px; 63 | line-height: 19px; 64 | color: #485350; 65 | max-height: 0; 66 | overflow: hidden; 67 | transition: max-height 250ms ease-in-out; 68 | } 69 | 70 | .productDescription p { 71 | margin: 22px 0 0; 72 | } 73 | 74 | .productButton { 75 | width: 100%; 76 | height: 36px; 77 | color: white; 78 | background: #1a73e8; 79 | border-radius: 5px; 80 | border: none; 81 | cursor: pointer; 82 | } 83 | -------------------------------------------------------------------------------- /src/styles/BlogCard.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | max-width: 354px; 5 | margin: auto; 6 | } 7 | 8 | .imageContainer { 9 | display: flex; 10 | justify-content: center; 11 | padding: 52px 0; 12 | width: 100%; 13 | background: #efb2cb; 14 | } 15 | 16 | .blogDetails { 17 | background: white; 18 | padding: 24px; 19 | } 20 | 21 | .blogHeading { 22 | display: flex; 23 | justify-content: space-between; 24 | } 25 | 26 | .headingText { 27 | font-weight: 500; 28 | font-size: 13px; 29 | color: #f06d41; 30 | text-transform: uppercase; 31 | } 32 | 33 | .blogLength { 34 | font-size: 13px; 35 | color: #121212; 36 | opacity: 0.3; 37 | } 38 | 39 | .blogTitle { 40 | font-weight: 500; 41 | font-size: 20px; 42 | line-height: 30px; 43 | color: #121212; 44 | margin: 20px 0 12px; 45 | } 46 | 47 | .productPrice { 48 | font-weight: 600; 49 | font-size: 22px; 50 | color: rgba(0, 0, 0, 0.6); 51 | } 52 | 53 | .divider { 54 | display: flex; 55 | width: 100%; 56 | height: 0.5px; 57 | margin: 22px 0; 58 | background: rgba(0, 0, 0, 0.2); 59 | } 60 | 61 | .blogDescription { 62 | font-weight: 400; 63 | font-size: 14px; 64 | line-height: 26px; 65 | color: #121212; 66 | } 67 | 68 | .byLineContainer { 69 | display: flex; 70 | justify-content: space-between; 71 | flex-wrap: wrap; 72 | align-items: center; 73 | } 74 | 75 | .byLine { 76 | display: flex; 77 | align-items: center; 78 | font-size: 13px; 79 | color: #273240; 80 | } 81 | 82 | .byLine img { 83 | height: 28px; 84 | width: 28px; 85 | margin-right: 8px; 86 | } 87 | 88 | .publishDate { 89 | font-size: 12px; 90 | color: #2c3a4b; 91 | opacity: 0.5; 92 | } 93 | -------------------------------------------------------------------------------- /src/components/cards/testimonial-card.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Builder } from "@builder.io/react"; 3 | import styles from "../../styles/TestimonialCard.module.css"; 4 | import { withTooltip } from "../with-tooltip"; 5 | 6 | export default function TestimonialCard(props) { 7 | return ( 8 |
9 |
10 | 11 |
12 |
13 |

{props.testimonial}

14 |
15 |
{props.customer}
16 |
{props.customerDetails}
17 |
18 |
19 | ); 20 | } 21 | 22 | // Wrap our component with a tooltip pointing to it's source code 23 | const DemoTestimonialCard = withTooltip( 24 | "https://github.com/BuilderIO/demo-editor/blob/main/src/components/cards/testimonial-card.js", 25 | TestimonialCard 26 | ); 27 | 28 | // Learn about registering custom components: https://www.builder.io/c/docs/custom-components-intro 29 | Builder.registerComponent(DemoTestimonialCard, { 30 | name: "TestimonialCard", 31 | image: 'https://tabler-icons.io/static/tabler-icons/icons-png/quote.png', 32 | inputs: [ 33 | { 34 | name: "testimonial", 35 | type: "longText", 36 | defaultValue: 37 | "With Builder, we’re able to see the same quality results that were only previously possible through reliance on our engineering team, who now have capacity to tackle higher-value projects.", 38 | }, 39 | { 40 | name: "customer", 41 | type: "string", 42 | defaultValue: "Everlane", 43 | enum: [ 44 | "Everlane", 45 | "Alo Yoga", 46 | "Afterpay", 47 | "Zapier", 48 | "Vista", 49 | "Harry's", 50 | "Chubbies", 51 | "Atoms", 52 | ], 53 | }, 54 | 55 | { 56 | name: "customerDetails", 57 | type: "string", 58 | defaultValue: "DAVE KING, CTO", 59 | }, 60 | ], 61 | }); 62 | -------------------------------------------------------------------------------- /src/components/icon-component.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Image from "next/image"; 3 | import { Builder } from "@builder.io/react"; 4 | import { IconBlob } from "./icon-blob"; 5 | import { iconUrls } from "./icons"; 6 | import styles from "../styles/Icon.module.css"; 7 | import { withTooltip } from "./with-tooltip"; 8 | 9 | const DEFAULT_FLEX_GAP = 10; 10 | 11 | const IconComponent = (props) => { 12 | return ( 13 |
14 |
18 | {iconUrls.slice(0, props.numberOfIcons).map((icon) => ( 19 | 20 | ))} 21 |
22 |
23 |

The power of no code

24 |

You’re in total control

25 |

26 | This is a react component. 27 | It’s connected to Builder for visual editing. Changes will update live 28 | in the visual editor as you edit. 29 |

30 |
31 | 32 |

33 | To edit the parameters, select the block, then choose Edit. 34 |

35 |
36 |
37 |
38 | ); 39 | }; 40 | 41 | // Wrap our component with a tooltip pointing to it's source code 42 | const DemoIconComponent = withTooltip( 43 | "https://github.com/BuilderIO/demo-editor/blob/main/src/components/icon-component.js", 44 | IconComponent 45 | ); 46 | 47 | // Learn about registering custom components: https://www.builder.io/c/docs/custom-components-intro 48 | Builder.registerComponent(DemoIconComponent, { 49 | name: "IconComponent", 50 | image: "https://tabler-icons.io/static/tabler-icons/icons-png/grid-dots.png", 51 | inputs: [ 52 | { name: "numberOfIcons", type: "number", defaultValue: 20 }, 53 | { name: "flexGap", type: "number", defaultValue: DEFAULT_FLEX_GAP }, 54 | ], 55 | }); 56 | -------------------------------------------------------------------------------- /src/styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | padding: 0 2rem; 3 | } 4 | 5 | .main { 6 | min-height: 100vh; 7 | padding: 4rem 0; 8 | flex: 1; 9 | display: flex; 10 | flex-direction: column; 11 | justify-content: center; 12 | align-items: center; 13 | } 14 | 15 | .footer { 16 | display: flex; 17 | flex: 1; 18 | padding: 2rem 0; 19 | border-top: 1px solid #eaeaea; 20 | justify-content: center; 21 | align-items: center; 22 | } 23 | 24 | .footer a { 25 | display: flex; 26 | justify-content: center; 27 | align-items: center; 28 | flex-grow: 1; 29 | } 30 | 31 | .title a { 32 | color: #0070f3; 33 | text-decoration: none; 34 | } 35 | 36 | .title a:hover, 37 | .title a:focus, 38 | .title a:active { 39 | text-decoration: underline; 40 | } 41 | 42 | .title { 43 | margin: 0; 44 | line-height: 1.15; 45 | font-size: 4rem; 46 | } 47 | 48 | .title, 49 | .description { 50 | text-align: center; 51 | } 52 | 53 | .description { 54 | margin: 4rem 0; 55 | line-height: 1.5; 56 | font-size: 1.5rem; 57 | } 58 | 59 | .code { 60 | background: #fafafa; 61 | border-radius: 5px; 62 | padding: 0.75rem; 63 | font-size: 1.1rem; 64 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 65 | Bitstream Vera Sans Mono, Courier New, monospace; 66 | } 67 | 68 | .grid { 69 | display: flex; 70 | align-items: center; 71 | justify-content: center; 72 | flex-wrap: wrap; 73 | max-width: 800px; 74 | } 75 | 76 | .card { 77 | margin: 1rem; 78 | padding: 1.5rem; 79 | text-align: left; 80 | color: inherit; 81 | text-decoration: none; 82 | border: 1px solid #eaeaea; 83 | border-radius: 10px; 84 | transition: color 0.15s ease, border-color 0.15s ease; 85 | max-width: 300px; 86 | } 87 | 88 | .card:hover, 89 | .card:focus, 90 | .card:active { 91 | color: #0070f3; 92 | border-color: #0070f3; 93 | } 94 | 95 | .card h2 { 96 | margin: 0 0 1rem 0; 97 | font-size: 1.5rem; 98 | } 99 | 100 | .card p { 101 | margin: 0; 102 | font-size: 1.25rem; 103 | line-height: 1.5; 104 | } 105 | 106 | .logo { 107 | height: 1em; 108 | margin-left: 0.5rem; 109 | } 110 | 111 | @media (max-width: 600px) { 112 | .grid { 113 | width: 100%; 114 | flex-direction: column; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import Image from 'next/image' 3 | import styles from '../styles/Home.module.css' 4 | 5 | export default function Home() { 6 | return ( 7 |
8 | 9 | Create Next App 10 | 11 | 12 | 13 | 14 |
15 |

16 | Welcome to Next.js! 17 |

18 | 19 |

20 | Get started by editing{' '} 21 | pages/index.js 22 |

23 | 24 |
25 | 26 |

Documentation →

27 |

Find in-depth information about Next.js features and API.

28 |
29 | 30 | 31 |

Learn →

32 |

Learn about Next.js in an interactive course with quizzes!

33 |
34 | 35 | 39 |

Examples →

40 |

Discover and deploy boilerplate example Next.js projects.

41 |
42 | 43 | 47 |

Deploy →

48 |

49 | Instantly deploy your Next.js site to a public URL with Vercel. 50 |

51 |
52 |
53 |
54 | 55 | 67 |
68 | ) 69 | } 70 | -------------------------------------------------------------------------------- /src/components/header.js: -------------------------------------------------------------------------------- 1 | import styles from "../styles/Header.module.css"; 2 | 3 | export function MyHeader() { 4 | return ( 5 |
6 |
7 |
8 | 15 | 19 | 23 | 27 | 28 | 29 |
30 | Builder Demo 31 |
32 |
33 | { 36 | // Open with JS so will open in visual editor 37 | // (by default links are intentionally disabled in the visual editor) 38 | open("https://github.com/Builderio/demo-editor", "_blank"); 39 | }} 40 | > 41 | View my source 42 | 43 |
44 |
45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /public/svgs/orange-palette-blob.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/svgs/yellow-smile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/svgs/purple-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/svgs/angular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /public/svgs/yellow-dots.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/components/cards/blog-card.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Builder } from "@builder.io/react"; 3 | import Image from "next/image"; 4 | import styles from "../../styles/BlogCard.module.css"; 5 | import { withTooltip } from "../with-tooltip"; 6 | 7 | export default function BlogCard(props) { 8 | return ( 9 |
10 |
11 | 12 |
13 |
14 |
15 | {props.tag} 16 | 17 | {props.estimatedTime} minute read 18 | 19 |
20 |
{props.title}
21 | 22 |
26 | 27 |
28 | 29 |
30 | 31 | 32 | {props.author} 33 | 34 | 35 | {props.publishDate} 36 |
37 |
38 |
39 | ); 40 | } 41 | 42 | // Wrap our component with a tooltip pointing to it's source code 43 | const DemoBlogCard = withTooltip( 44 | "https://github.com/BuilderIO/demo-editor/blob/main/src/components/cards/blog-card.js", 45 | BlogCard 46 | ); 47 | 48 | // Learn about registering custom components: https://www.builder.io/c/docs/custom-components-intro 49 | Builder.registerComponent(DemoBlogCard, { 50 | name: "BlogCard", 51 | image: 'https://tabler-icons.io/static/tabler-icons/icons-png/article.png', 52 | inputs: [ 53 | { 54 | name: "thumbnail", 55 | type: "file", 56 | defaultValue: 57 | "https://cdn.builder.io/api/v1/image/assets%2F1f3bf1d766354f32ba70dde440fcef97%2F75e3e53ecc4a44b795592a4fbe57f702", 58 | allowedFileTypes: ["png", "jpg", "svg"], 59 | }, 60 | 61 | { 62 | name: "title", 63 | type: "string", 64 | defaultValue: "Guide Your Customers with Best Practices", 65 | }, 66 | { name: "tag", type: "string", defaultValue: "Best Practices" }, 67 | { name: "estimatedTime", type: "number", defaultValue: 5 }, 68 | 69 | { 70 | name: "body", 71 | type: "richText", 72 | defaultValue: 73 | "Empower your teams to leverage your code components as building blocks to unlock their creativity. Create content for any experience, channel, and screen. A drag and drop experience makes building content easy and fast for your teams.", 74 | }, 75 | { name: "author", type: "string", defaultValue: "Jane Builder" }, 76 | { 77 | name: "authorImage", 78 | type: "file", 79 | defaultValue: 80 | "https://cdn.builder.io/api/v1/image/assets%2Fccda6c7abf4c4b8195aa67d47de420dd%2F91d681a0a2304c42b07bbb2f54af399d", 81 | allowedFileTypes: ["png", "jpg", "svg"], 82 | }, 83 | { name: "publishDate", type: "string", defaultValue: "Yesterday" }, 84 | ], 85 | }); 86 | -------------------------------------------------------------------------------- /public/svgs/pink-triangle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/cards/product-card.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Builder } from "@builder.io/react"; 3 | import Image from "next/image"; 4 | import styles from "../../styles/ProductCard.module.css"; 5 | import { withTooltip } from "../with-tooltip"; 6 | 7 | export default function ProductCard(props) { 8 | const [productDetailsOpen, setProductDetailsOpen] = useState(false); 9 | return ( 10 |
11 |
12 | 17 |
18 |
19 |
{props.productTitle}
20 |
{props.productPrice}
21 | 22 |
23 | 24 |
setProductDetailsOpen(!productDetailsOpen)} 27 | > 28 | Details 29 |
33 |
34 | 35 |
39 |

{props.productDescription}

40 |
41 | 42 |
43 | 44 | 50 |
51 |
52 | ); 53 | } 54 | 55 | // Wrap our component with a tooltip pointing to it's source code 56 | const DemoProductCard = withTooltip( 57 | "https://github.com/BuilderIO/demo-editor/blob/main/src/components/cards/product-card.js", 58 | ProductCard 59 | ); 60 | 61 | // Learn about registering custom components: https://www.builder.io/c/docs/custom-components-intro 62 | Builder.registerComponent(DemoProductCard, { 63 | name: "ProductCard", 64 | image: 'https://tabler-icons.io/static/tabler-icons/icons-png/shopping-cart.png', 65 | inputs: [ 66 | { 67 | name: "productTitle", 68 | type: "string", 69 | defaultValue: "Your Product Details Here", 70 | }, 71 | { 72 | name: "productDescription", 73 | type: "longText", 74 | defaultValue: 75 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", 76 | }, 77 | { 78 | name: "productPrice", 79 | type: "string", 80 | defaultValue: "$20 / month", 81 | helperText: 82 | "You can add validation to inputs, so if you enter a string without a number this will show a warning.", 83 | regex: { 84 | pattern: /\d/, 85 | options: "g", 86 | message: "Price must contain a number (e.g. $20)", 87 | }, 88 | }, 89 | { name: "buttonColor", type: "color", defaultValue: "#1a73e8" }, 90 | { 91 | name: "buttonText", 92 | type: "string", 93 | defaultValue: "Buy now", 94 | enum: ["Buy now", "Let's go", "Add to cart"], 95 | }, 96 | 97 | { 98 | name: "productImage", 99 | type: "file", 100 | allowedFileTypes: ["jpg", "png", "svg"], 101 | defaultValue: "/svgs/yellow-smiley-blob.svg", 102 | }, 103 | ], 104 | }); 105 | -------------------------------------------------------------------------------- /public/svgs/purple-straight-face.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/pages/[...page].js: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import DefaultErrorPage from "next/error"; 3 | import Head from "next/head"; 4 | import React from "react"; 5 | import { 6 | BuilderComponent, 7 | builder, 8 | useIsPreviewing, 9 | Builder, 10 | } from "@builder.io/react"; 11 | import "@builder.io/widgets"; 12 | import { MyFooter } from "../components/footer"; 13 | import { MyHeader } from "../components/header"; 14 | 15 | import "../components/icon-component"; 16 | import "../components/code-block"; 17 | import "../components/cards/product-card"; 18 | import "../components/cards/blog-card"; 19 | import "../components/cards/video-card"; 20 | import "../components/cards/testimonial-card"; 21 | 22 | /* 23 | Initialize the Builder SDK with your organization's API Key 24 | The API Key can be found on: https://builder.io/account/settings 25 | */ 26 | builder.init("ccda6c7abf4c4b8195aa67d47de420dd"); 27 | 28 | export async function getStaticProps({ params }) { 29 | /* 30 | Fetch the first page from Builder that matches the current URL. 31 | The `userAttributes` field is used for targeting content, 32 | learn more here: https://www.builder.io/c/docs/targeting-with-builder 33 | */ 34 | const page = await builder 35 | .get("page", { 36 | userAttributes: { 37 | urlPath: "/" + (params?.page?.join("/") || ""), 38 | }, 39 | }) 40 | .toPromise(); 41 | 42 | return { 43 | props: { 44 | page: page || null, 45 | }, 46 | revalidate: 5, 47 | }; 48 | } 49 | 50 | export async function getStaticPaths() { 51 | /* 52 | Fetch all published pages for the current model. 53 | Using the `fields` option will limit the size of the response 54 | and only return the `data.url` field from the matching pages. 55 | */ 56 | const pages = await builder.getAll("page", { 57 | fields: "data.url", // only request the `data.url` field 58 | options: { noTargeting: true }, 59 | limit: 0, 60 | }); 61 | 62 | return { 63 | paths: pages.map((page) => `${page.data?.url}`), 64 | fallback: true, 65 | }; 66 | } 67 | 68 | export default function Page({ page }) { 69 | const router = useRouter(); 70 | /* 71 | This flag indicates if you are viewing the page in the Builder editor. 72 | */ 73 | const isPreviewing = useIsPreviewing(); 74 | 75 | if (router.isFallback) { 76 | return

Loading...

; 77 | } 78 | 79 | /* 80 | Add your error page here. This will happen if there are no matching 81 | content entries published in Builder. 82 | */ 83 | if (!page && !isPreviewing) { 84 | return ; 85 | } 86 | 87 | return ( 88 | <> 89 | 90 | {/* Add any relevant SEO metadata or open graph tags here */} 91 | {page?.data.title} 92 | 93 | 94 | {/* Render the Builder page */} 95 | 96 | 97 | 98 | 99 | ); 100 | } 101 | 102 | /* 103 | Example of a custom insert menu, this will add a new section to the top 104 | of your Builder editor. You can add custom icons to your components as well. 105 | https://forum.builder.io/t/how-to-override-and-re-arrange-the-insert-menu-completely-in-builder/680 106 | */ 107 | Builder.register("insertMenu", { 108 | name: "Sample Components", 109 | items: [ 110 | { 111 | name: "IconComponent", 112 | }, 113 | { 114 | name: "ProductCard", 115 | }, 116 | { 117 | name: "BlogCard", 118 | }, 119 | { 120 | name: "VideoCard", 121 | }, 122 | { 123 | name: "TestimonialCard", 124 | }, 125 | { 126 | name: "CodeBlock", 127 | }, 128 | ], 129 | }); 130 | -------------------------------------------------------------------------------- /public/svgs/purple-rhomboid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/svgs/pointer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /public/svgs/s-block.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /public/svgs/circle-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/svgs/yellow-right-arrow.svg: -------------------------------------------------------------------------------- 1 | 8 | 12 | 16 | 20 | -------------------------------------------------------------------------------- /public/svgs/blue-atom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/svgs/multi-color-f.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /public/svgs/pink-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /public/svgs/yellow-smiley-blob.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/svgs/blue-cloud.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | --------------------------------------------------------------------------------