mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-11-22 01:24:49 +03:00
Run prettier format
This commit is contained in:
parent
4c362f3651
commit
6cfc495ca4
@ -1,3 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React from "react";
|
||||
import React from 'react'
|
||||
|
||||
const DiscordLink = (props) => {
|
||||
return (
|
||||
<span>
|
||||
<a href="https://discord.gg/rzdnErX"> Discord </a>
|
||||
<a href="https://discord.gg/rzdnErX"> Discord </a>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default DiscordLink;
|
||||
export default DiscordLink
|
||||
|
@ -1,19 +1,26 @@
|
||||
import React from "react";
|
||||
import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||
import React from 'react'
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl'
|
||||
|
||||
const ImgWithCaption = (props) => {
|
||||
return (
|
||||
<div>
|
||||
<p align='center'>
|
||||
<p align="center">
|
||||
<figure>
|
||||
<img style={{ width: props.width }} alt={props.alt} src={useBaseUrl(props.source)} />
|
||||
<figcaption class='image-caption' style={{ fontStyle: 'italic', opacity: 0.6, fontSize: '0.9rem' }}>
|
||||
<img
|
||||
style={{ width: props.width }}
|
||||
alt={props.alt}
|
||||
src={useBaseUrl(props.source)}
|
||||
/>
|
||||
<figcaption
|
||||
class="image-caption"
|
||||
style={{ fontStyle: 'italic', opacity: 0.6, fontSize: '0.9rem' }}
|
||||
>
|
||||
{props.caption}
|
||||
</figcaption>
|
||||
</figure>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default ImgWithCaption;
|
||||
export default ImgWithCaption
|
||||
|
@ -1,28 +1,30 @@
|
||||
import React from 'react'
|
||||
|
||||
import Link from '@docusaurus/Link';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import Link from '@docusaurus/Link'
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl'
|
||||
|
||||
const Divider = () => (
|
||||
<span className='in-blog-cta--divider'> → </span>
|
||||
)
|
||||
const Divider = () => <span className="in-blog-cta--divider"> → </span>
|
||||
|
||||
const InBlogCta = () => (
|
||||
<p className='in-blog-cta-link-container'>
|
||||
<Link className='in-blog-cta--link'
|
||||
to='https://e44cy1h4s0q.typeform.com/to/ycUzQa5A'>
|
||||
We are in Beta (try it out)!
|
||||
</Link>
|
||||
<Divider />
|
||||
<Link className='in-blog-cta--link' to='https://discord.gg/rzdnErX'>
|
||||
Join our community
|
||||
</Link>
|
||||
<Divider />
|
||||
<Link className='in-blog-cta--link'
|
||||
to='https://wasp-lang.notion.site/Founding-Engineer-at-Wasp-402274568afa4d7eb7f428f8fa2c0816'>
|
||||
Work with us
|
||||
</Link>
|
||||
</p>
|
||||
<p className="in-blog-cta-link-container">
|
||||
<Link
|
||||
className="in-blog-cta--link"
|
||||
to="https://e44cy1h4s0q.typeform.com/to/ycUzQa5A"
|
||||
>
|
||||
We are in Beta (try it out)!
|
||||
</Link>
|
||||
<Divider />
|
||||
<Link className="in-blog-cta--link" to="https://discord.gg/rzdnErX">
|
||||
Join our community
|
||||
</Link>
|
||||
<Divider />
|
||||
<Link
|
||||
className="in-blog-cta--link"
|
||||
to="https://wasp-lang.notion.site/Founding-Engineer-at-Wasp-402274568afa4d7eb7f428f8fa2c0816"
|
||||
>
|
||||
Work with us
|
||||
</Link>
|
||||
</p>
|
||||
)
|
||||
|
||||
export default InBlogCta
|
||||
|
@ -1,13 +1,13 @@
|
||||
import Admonition from "@theme/Admonition";
|
||||
import Link from "@docusaurus/Link";
|
||||
import React from "react";
|
||||
import Admonition from '@theme/Admonition'
|
||||
import Link from '@docusaurus/Link'
|
||||
import React from 'react'
|
||||
|
||||
export default function OldDocsNote() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "sticky",
|
||||
top: "calc(var(--ifm-navbar-height) + 1rem)",
|
||||
position: 'sticky',
|
||||
top: 'calc(var(--ifm-navbar-height) + 1rem)',
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
@ -21,5 +21,5 @@ export default function OldDocsNote() {
|
||||
content.
|
||||
</Admonition>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -26,4 +26,4 @@
|
||||
}
|
||||
.deployment-methods-info {
|
||||
color: var(--ifm-color-secondary-contrast-foreground);
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React from "react";
|
||||
import "./DeploymentOptionsGrid.css";
|
||||
import React from 'react'
|
||||
import './DeploymentOptionsGrid.css'
|
||||
|
||||
export function DeploymentOptionsGrid() {
|
||||
const deploymentMethods = [
|
||||
{
|
||||
title: "Using Wasp CLI",
|
||||
description: "One command deployment & redeployment",
|
||||
linkToDocs: "/docs/advanced/deployment/cli",
|
||||
title: 'Using Wasp CLI',
|
||||
description: 'One command deployment & redeployment',
|
||||
linkToDocs: '/docs/advanced/deployment/cli',
|
||||
},
|
||||
{
|
||||
title: "Deploying Manually",
|
||||
description: "Build the app and deploy it manually",
|
||||
linkToDocs: "/docs/advanced/deployment/manually",
|
||||
title: 'Deploying Manually',
|
||||
description: 'Build the app and deploy it manually',
|
||||
linkToDocs: '/docs/advanced/deployment/manually',
|
||||
},
|
||||
];
|
||||
]
|
||||
return (
|
||||
<>
|
||||
<div className="deployment-methods-grid">
|
||||
@ -29,7 +29,7 @@ export function DeploymentOptionsGrid() {
|
||||
<small>Click on each deployment method for more details.</small>
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function DeploymentOptionBox({
|
||||
@ -37,14 +37,14 @@ function DeploymentOptionBox({
|
||||
title,
|
||||
description,
|
||||
}: {
|
||||
linkToDocs: string;
|
||||
title: string;
|
||||
description: string;
|
||||
linkToDocs: string
|
||||
title: string
|
||||
description: string
|
||||
}) {
|
||||
return (
|
||||
<a href={linkToDocs} className="deployment-method-box">
|
||||
<h3>{title} »</h3>
|
||||
<p>{description}</p>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -6,10 +6,10 @@
|
||||
--auth-pills-username-and-pass: #fce7f3;
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
:root[data-theme='dark'] {
|
||||
--auth-pills-color: #fff;
|
||||
--auth-pills-email: #0c4a6e;
|
||||
--auth-pills-github: #334155;
|
||||
--auth-pills-google: #365314;
|
||||
--auth-pills-username-and-pass: #831843;
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,23 @@
|
||||
import React from "react";
|
||||
import './Pills.css';
|
||||
import Link from '@docusaurus/Link';
|
||||
import React from 'react'
|
||||
import './Pills.css'
|
||||
import Link from '@docusaurus/Link'
|
||||
|
||||
export function Pill({ children, linkToPage, style = {} }) {
|
||||
return <Link to={linkToPage}
|
||||
style={{
|
||||
padding: "0.1rem 0.5rem",
|
||||
borderRadius: "0.375rem",
|
||||
color: "var(--auth-pills-color)",
|
||||
textDecoration: "none",
|
||||
display: "inline-block",
|
||||
...style,
|
||||
}}
|
||||
>{children}</Link>;
|
||||
return (
|
||||
<Link
|
||||
to={linkToPage}
|
||||
style={{
|
||||
padding: '0.1rem 0.5rem',
|
||||
borderRadius: '0.375rem',
|
||||
color: 'var(--auth-pills-color)',
|
||||
textDecoration: 'none',
|
||||
display: 'inline-block',
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
@ -24,25 +29,53 @@ export function Pill({ children, linkToPage, style = {} }) {
|
||||
}
|
||||
*/
|
||||
export function EmailPill() {
|
||||
return <Pill style={{
|
||||
backgroundColor: "var(--auth-pills-email)",
|
||||
}} linkToPage="/docs/auth/email">Email</Pill>;
|
||||
return (
|
||||
<Pill
|
||||
style={{
|
||||
backgroundColor: 'var(--auth-pills-email)',
|
||||
}}
|
||||
linkToPage="/docs/auth/email"
|
||||
>
|
||||
Email
|
||||
</Pill>
|
||||
)
|
||||
}
|
||||
|
||||
export function UsernameAndPasswordPill() {
|
||||
return <Pill style={{
|
||||
backgroundColor: "var(--auth-pills-username-and-pass)",
|
||||
}} linkToPage="/docs/auth/username-and-pass">Username & Password</Pill>;
|
||||
return (
|
||||
<Pill
|
||||
style={{
|
||||
backgroundColor: 'var(--auth-pills-username-and-pass)',
|
||||
}}
|
||||
linkToPage="/docs/auth/username-and-pass"
|
||||
>
|
||||
Username & Password
|
||||
</Pill>
|
||||
)
|
||||
}
|
||||
|
||||
export function GithubPill() {
|
||||
return <Pill style={{
|
||||
backgroundColor: "var(--auth-pills-github)",
|
||||
}} linkToPage="/docs/auth/social-auth/github">Github</Pill>;
|
||||
return (
|
||||
<Pill
|
||||
style={{
|
||||
backgroundColor: 'var(--auth-pills-github)',
|
||||
}}
|
||||
linkToPage="/docs/auth/social-auth/github"
|
||||
>
|
||||
Github
|
||||
</Pill>
|
||||
)
|
||||
}
|
||||
|
||||
export function GooglePill() {
|
||||
return <Pill style={{
|
||||
backgroundColor: "var(--auth-pills-google)",
|
||||
}} linkToPage="/docs/auth/social-auth/google">Google</Pill>;
|
||||
return (
|
||||
<Pill
|
||||
style={{
|
||||
backgroundColor: 'var(--auth-pills-google)',
|
||||
}}
|
||||
linkToPage="/docs/auth/social-auth/google"
|
||||
>
|
||||
Google
|
||||
</Pill>
|
||||
)
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
import React from "react";
|
||||
import Link from '@docusaurus/Link';
|
||||
import "./SocialAuthGrid.css";
|
||||
import React from 'react'
|
||||
import Link from '@docusaurus/Link'
|
||||
import './SocialAuthGrid.css'
|
||||
|
||||
export function SocialAuthGrid({
|
||||
pagePart = "", // e.g. #overrides
|
||||
pagePart = '', // e.g. #overrides
|
||||
}) {
|
||||
const authMethods = [
|
||||
{
|
||||
title: "Google",
|
||||
description: "Users sign in with their Google account.",
|
||||
linkToDocs: "/docs/auth/social-auth/google" + pagePart,
|
||||
title: 'Google',
|
||||
description: 'Users sign in with their Google account.',
|
||||
linkToDocs: '/docs/auth/social-auth/google' + pagePart,
|
||||
},
|
||||
{
|
||||
title: "Github",
|
||||
description: "Users sign in with their Github account.",
|
||||
linkToDocs: "/docs/auth/social-auth/github" + pagePart,
|
||||
title: 'Github',
|
||||
description: 'Users sign in with their Github account.',
|
||||
linkToDocs: '/docs/auth/social-auth/github' + pagePart,
|
||||
},
|
||||
];
|
||||
]
|
||||
return (
|
||||
<>
|
||||
<div className="social-auth-grid">
|
||||
@ -32,7 +32,7 @@ export function SocialAuthGrid({
|
||||
<small>Click on each provider for more details.</small>
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function AuthMethodBox({
|
||||
@ -40,14 +40,14 @@ function AuthMethodBox({
|
||||
title,
|
||||
description,
|
||||
}: {
|
||||
linkToDocs: string;
|
||||
title: string;
|
||||
description: string;
|
||||
linkToDocs: string
|
||||
title: string
|
||||
description: string
|
||||
}) {
|
||||
return (
|
||||
<Link to={linkToDocs} className="auth-method-box">
|
||||
<h3>{title} »</h3>
|
||||
<p>{description}</p>
|
||||
</Link>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -1,25 +1,25 @@
|
||||
const lightCodeTheme = require("prism-react-renderer/themes/github");
|
||||
const lightCodeTheme = require('prism-react-renderer/themes/github')
|
||||
|
||||
const autoImportTabs = require("./src/remark/auto-import-tabs");
|
||||
const fileExtSwitcher = require("./src/remark/file-ext-switcher");
|
||||
const autoImportTabs = require('./src/remark/auto-import-tabs')
|
||||
const fileExtSwitcher = require('./src/remark/file-ext-switcher')
|
||||
|
||||
/** @type {import('@docusaurus/types').DocusaurusConfig} */
|
||||
module.exports = {
|
||||
title: "Wasp",
|
||||
title: 'Wasp',
|
||||
tagline:
|
||||
"A simple language for developing full-stack web apps with less code.",
|
||||
'A simple language for developing full-stack web apps with less code.',
|
||||
// url, baseUrl, organizationName, projectName and trailingSlash are set according to the
|
||||
// instructions in https://docusaurus.io/docs/deployment#deploying-to-github-pages .
|
||||
url: "https://wasp-lang.dev",
|
||||
baseUrl: "/", // Should be name of repo if hosted on Github Pages, but can be just '/' if custom domain is used.
|
||||
organizationName: "wasp-lang", // Should be GitHub org/user name if hosted on Github Pages.
|
||||
projectName: "wasp", // Should be repo name if hosted on Github Pages.
|
||||
url: 'https://wasp-lang.dev',
|
||||
baseUrl: '/', // Should be name of repo if hosted on Github Pages, but can be just '/' if custom domain is used.
|
||||
organizationName: 'wasp-lang', // Should be GitHub org/user name if hosted on Github Pages.
|
||||
projectName: 'wasp', // Should be repo name if hosted on Github Pages.
|
||||
trailingSlash: false,
|
||||
onBrokenLinks: "throw",
|
||||
onBrokenMarkdownLinks: "warn",
|
||||
favicon: "img/favicon.ico",
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
favicon: 'img/favicon.ico',
|
||||
stylesheets: [
|
||||
"https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap",
|
||||
'https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap',
|
||||
],
|
||||
themeConfig: {
|
||||
/*
|
||||
@ -47,86 +47,86 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
navbar: {
|
||||
title: ".wasp (beta)",
|
||||
title: '.wasp (beta)',
|
||||
logo: {
|
||||
alt: "Wasp logo",
|
||||
src: "img/wasp-logo-eqpar-circle.png",
|
||||
href: "https://wasp-lang.dev/",
|
||||
target: "_self"
|
||||
alt: 'Wasp logo',
|
||||
src: 'img/wasp-logo-eqpar-circle.png',
|
||||
href: 'https://wasp-lang.dev/',
|
||||
target: '_self'
|
||||
},
|
||||
items: [
|
||||
{
|
||||
to: "docs/",
|
||||
activeBasePath: "docs",
|
||||
label: "Docs",
|
||||
position: "left",
|
||||
className: "navbar-item-docs navbar-item-outside",
|
||||
to: 'docs/',
|
||||
activeBasePath: 'docs',
|
||||
label: 'Docs',
|
||||
position: 'left',
|
||||
className: 'navbar-item-docs navbar-item-outside',
|
||||
},
|
||||
{
|
||||
to: "blog",
|
||||
label: "Blog",
|
||||
position: "left",
|
||||
to: 'blog',
|
||||
label: 'Blog',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
href: "https://github.com/wasp-lang/wasp",
|
||||
className: "navbar-item-github",
|
||||
position: "right",
|
||||
href: 'https://github.com/wasp-lang/wasp',
|
||||
className: 'navbar-item-github',
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
href: "https://twitter.com/WaspLang",
|
||||
className: "navbar-item-twitter",
|
||||
position: "right",
|
||||
href: 'https://twitter.com/WaspLang',
|
||||
className: 'navbar-item-twitter',
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
href: "https://discord.gg/rzdnErX",
|
||||
className: "navbar-item-discord",
|
||||
position: "right",
|
||||
href: 'https://discord.gg/rzdnErX',
|
||||
className: 'navbar-item-discord',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
prism: {
|
||||
additionalLanguages: ["shell-session", "haskell"],
|
||||
additionalLanguages: ['shell-session', 'haskell'],
|
||||
theme: lightCodeTheme,
|
||||
},
|
||||
footer: {
|
||||
style: "dark",
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: "Docs",
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
label: "Getting started",
|
||||
to: "docs",
|
||||
label: 'Getting started',
|
||||
to: 'docs',
|
||||
},
|
||||
{
|
||||
label: "Todo app tutorial",
|
||||
to: "docs/tutorial/create",
|
||||
label: 'Todo app tutorial',
|
||||
to: 'docs/tutorial/create',
|
||||
},
|
||||
{
|
||||
label: "Reference",
|
||||
to: "docs/language/features",
|
||||
label: 'Reference',
|
||||
to: 'docs/language/features',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Community",
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: "Discord",
|
||||
href: "https://discord.gg/rzdnErX",
|
||||
label: 'Discord',
|
||||
href: 'https://discord.gg/rzdnErX',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "More",
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: "GitHub",
|
||||
href: "https://github.com/wasp-lang/wasp",
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/wasp-lang/wasp',
|
||||
},
|
||||
{
|
||||
label: "Contact",
|
||||
to: "docs/contact",
|
||||
label: 'Contact',
|
||||
to: 'docs/contact',
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -134,59 +134,59 @@ module.exports = {
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Wasp.`,
|
||||
},
|
||||
algolia: {
|
||||
appId: "RG0JSZOWH4",
|
||||
apiKey: "feaa2a25dc596d40418c82cd040e2cbe",
|
||||
indexName: "wasp-lang",
|
||||
appId: 'RG0JSZOWH4',
|
||||
apiKey: 'feaa2a25dc596d40418c82cd040e2cbe',
|
||||
indexName: 'wasp-lang',
|
||||
// TODO: contextualSearch is useful when you are doing versioning,
|
||||
// it searches only in v1 docs if you are searching from v1 docs.
|
||||
// We should enable it if we start doing versioning.
|
||||
// contextualSearch: true
|
||||
},
|
||||
image: "img/wasp_twitter_cover.png",
|
||||
metadata: [{ name: "twitter:card", content: "summary_large_image" }],
|
||||
image: 'img/wasp_twitter_cover.png',
|
||||
metadata: [{ name: 'twitter:card', content: 'summary_large_image' }],
|
||||
},
|
||||
presets: [
|
||||
[
|
||||
"@docusaurus/preset-classic",
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
gtag: {
|
||||
trackingID: "GTM-PQ4JFCK",
|
||||
trackingID: 'GTM-PQ4JFCK',
|
||||
anonymizeIP: true,
|
||||
},
|
||||
docs: {
|
||||
sidebarPath: require.resolve("./sidebars.js"),
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
sidebarCollapsible: true,
|
||||
// Please change this to your repo.
|
||||
editUrl: "https://github.com/wasp-lang/wasp/edit/release/web",
|
||||
editUrl: 'https://github.com/wasp-lang/wasp/edit/release/web',
|
||||
remarkPlugins: [autoImportTabs, fileExtSwitcher],
|
||||
},
|
||||
blog: {
|
||||
showReadingTime: true,
|
||||
// Please change this to your repo.
|
||||
blogSidebarCount: "ALL",
|
||||
blogSidebarTitle: "All our posts",
|
||||
postsPerPage: "ALL",
|
||||
editUrl: "https://github.com/wasp-lang/wasp/edit/release/web",
|
||||
blogSidebarCount: 'ALL',
|
||||
blogSidebarTitle: 'All our posts',
|
||||
postsPerPage: 'ALL',
|
||||
editUrl: 'https://github.com/wasp-lang/wasp/edit/release/web',
|
||||
},
|
||||
theme: {
|
||||
customCss: [require.resolve("./src/css/custom.css")],
|
||||
customCss: [require.resolve('./src/css/custom.css')],
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
scripts: ["/scripts/posthog.js", "/js/fix-multiple-trailing-slashes.js"],
|
||||
scripts: ['/scripts/posthog.js', '/js/fix-multiple-trailing-slashes.js'],
|
||||
plugins: [
|
||||
"plugin-image-zoom",
|
||||
'plugin-image-zoom',
|
||||
async function myPlugin(context, options) {
|
||||
return {
|
||||
name: "docusaurus-tailwindcss",
|
||||
name: 'docusaurus-tailwindcss',
|
||||
configurePostCss(postcssOptions) {
|
||||
// Appends TailwindCSS and AutoPrefixer.
|
||||
postcssOptions.plugins.push(require("tailwindcss"));
|
||||
postcssOptions.plugins.push(require("autoprefixer"));
|
||||
return postcssOptions;
|
||||
postcssOptions.plugins.push(require('tailwindcss'))
|
||||
postcssOptions.plugins.push(require('autoprefixer'))
|
||||
return postcssOptions
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
'@docusaurus/plugin-client-redirects',
|
||||
@ -218,7 +218,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
from: '/docs/guides/email-auth',
|
||||
to: '/docs/auth/email'
|
||||
to: '/docs/auth/email',
|
||||
},
|
||||
{
|
||||
from: '/docs/guides/crud',
|
||||
@ -244,4 +244,4 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
}
|
||||
|
@ -26,4 +26,4 @@
|
||||
}
|
||||
.auth-methods-info {
|
||||
color: var(--ifm-color-secondary-contrast-foreground);
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,29 @@
|
||||
import React from "react";
|
||||
import "./AuthMethodsGrid.css";
|
||||
import React from 'react'
|
||||
import './AuthMethodsGrid.css'
|
||||
|
||||
export function AuthMethodsGrid() {
|
||||
const authMethods = [
|
||||
{
|
||||
title: "Email",
|
||||
description: "Email verification, password reset, etc.",
|
||||
linkToDocs: "/docs/auth/email",
|
||||
title: 'Email',
|
||||
description: 'Email verification, password reset, etc.',
|
||||
linkToDocs: '/docs/auth/email',
|
||||
},
|
||||
{
|
||||
title: "Username & Password",
|
||||
description: "The simplest way to get started",
|
||||
linkToDocs: "/docs/auth/username-and-pass",
|
||||
title: 'Username & Password',
|
||||
description: 'The simplest way to get started',
|
||||
linkToDocs: '/docs/auth/username-and-pass',
|
||||
},
|
||||
{
|
||||
title: "Google",
|
||||
description: "Users sign in with their Google account",
|
||||
linkToDocs: "/docs/auth/social-auth/google",
|
||||
title: 'Google',
|
||||
description: 'Users sign in with their Google account',
|
||||
linkToDocs: '/docs/auth/social-auth/google',
|
||||
},
|
||||
{
|
||||
title: "Github",
|
||||
description: "Users sign in with their Github account",
|
||||
linkToDocs: "/docs/auth/social-auth/github",
|
||||
title: 'Github',
|
||||
description: 'Users sign in with their Github account',
|
||||
linkToDocs: '/docs/auth/social-auth/github',
|
||||
},
|
||||
];
|
||||
]
|
||||
return (
|
||||
<>
|
||||
<div className="auth-methods-grid">
|
||||
@ -39,7 +39,7 @@ export function AuthMethodsGrid() {
|
||||
<small>Click on each auth method for more details.</small>
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function AuthMethodBox({
|
||||
@ -47,14 +47,14 @@ function AuthMethodBox({
|
||||
title,
|
||||
description,
|
||||
}: {
|
||||
linkToDocs: string;
|
||||
title: string;
|
||||
description: string;
|
||||
linkToDocs: string
|
||||
title: string
|
||||
description: string
|
||||
}) {
|
||||
return (
|
||||
<a href={linkToDocs} className="auth-method-box">
|
||||
<h3>{title} »</h3>
|
||||
<p>{description}</p>
|
||||
</a>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -8,52 +8,47 @@ import styles from '../pages/styles.module.css'
|
||||
|
||||
const Lang = () => (
|
||||
<>
|
||||
<span className='underline decoration-yellow-500 font-bold'>
|
||||
language
|
||||
</span>
|
||||
<span className="font-bold underline decoration-yellow-500">language</span>
|
||||
</>
|
||||
)
|
||||
|
||||
const Benefit = ({ Icon, title, description }) => (
|
||||
<div className='mb-10 md:mb-0 space-y-4'>
|
||||
<div className='flex items-center'>
|
||||
<div className="mb-10 space-y-4 md:mb-0">
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className={`
|
||||
inline-flex h-8 w-8 rounded-md
|
||||
items-center justify-center
|
||||
text-yellow-500 bg-neutral-700
|
||||
inline-flex h-8 w-8 items-center
|
||||
justify-center rounded-md
|
||||
bg-neutral-700 text-yellow-500
|
||||
`}
|
||||
>
|
||||
<Icon size={20} />
|
||||
</div>
|
||||
<dt className='ml-4 text-neutral-700'>
|
||||
{ title }
|
||||
</dt>
|
||||
<dt className="ml-4 text-neutral-700">{title}</dt>
|
||||
</div>
|
||||
<p className='text-neutral-700'>
|
||||
{ description }
|
||||
</p>
|
||||
<p className="text-neutral-700">{description}</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
const Benefits = () => {
|
||||
return (
|
||||
<SectionContainer className='space-y-16'>
|
||||
<div className='grid grid-cols-12'>
|
||||
<div className='col-span-12 text-center'>
|
||||
<h2 className='text-xl lg:text-2xl text-neutral-700 mb-4'>
|
||||
<SectionContainer className="space-y-16">
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 text-center">
|
||||
<h2 className="mb-4 text-xl text-neutral-700 lg:text-2xl">
|
||||
Get started in minutes - zero config required.
|
||||
</h2>
|
||||
<p className='text-neutral-500'>
|
||||
Wasp provides all the best practices out-of-the-box and lets you focus on your code.
|
||||
<p className="text-neutral-500">
|
||||
Wasp provides all the best practices out-of-the-box and lets you
|
||||
focus on your code.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dl className='grid grid-cols-1 lg:grid-cols-3 md:gap-16 lg:gap-x-8 xl:gap-x-24'>
|
||||
<dl className="grid grid-cols-1 md:gap-16 lg:grid-cols-3 lg:gap-x-8 xl:gap-x-24">
|
||||
<Benefit
|
||||
Icon={Layers}
|
||||
title='Truly full-stack'
|
||||
title="Truly full-stack"
|
||||
description={`
|
||||
When we say full-stack, we really mean it. Wasp has you covered from front-end,
|
||||
back-end and database to deployment. Zero config required to get started.
|
||||
@ -62,7 +57,7 @@ const Benefits = () => {
|
||||
|
||||
<Benefit
|
||||
Icon={Coffee}
|
||||
title='The wheel can take a break'
|
||||
title="The wheel can take a break"
|
||||
description={`
|
||||
No reinventing the wheel here. Write your code in React & Node.js as you are used to,
|
||||
along with your favourite NPM packages.
|
||||
@ -71,7 +66,7 @@ const Benefits = () => {
|
||||
|
||||
<Benefit
|
||||
Icon={Code}
|
||||
title='Less boilerplate'
|
||||
title="Less boilerplate"
|
||||
description={`
|
||||
The .wasp config file allows us to immensely improve developer experience.
|
||||
E.g., full-stack auth takes only 5 lines of code.
|
||||
@ -83,17 +78,16 @@ const Benefits = () => {
|
||||
}
|
||||
|
||||
const BenefitsWithSkewedBorder = () => (
|
||||
<div className='relative'>
|
||||
<div className="relative">
|
||||
<div className={classNames(styles.sectionSkewedContainer)}>
|
||||
<div
|
||||
className={classNames(
|
||||
styles.sectionSkewed,
|
||||
'border-t border-b border-yellow-500/25 bg-neutral-100/50'
|
||||
'border-b border-t border-yellow-500/25 bg-neutral-100/50'
|
||||
)}
|
||||
>
|
||||
</div>
|
||||
></div>
|
||||
</div>
|
||||
<div className='relative'>
|
||||
<div className="relative">
|
||||
<Benefits />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,14 +1,12 @@
|
||||
import React, { useState } from 'react'
|
||||
import CodeBlock from '@theme/CodeBlock'
|
||||
|
||||
export default function CodeBlockWithTitle ({ title, children, language }) {
|
||||
export default function CodeBlockWithTitle({ title, children, language }) {
|
||||
return (
|
||||
<div className='code-with-header'>
|
||||
<div className="code-header">{ title }</div>
|
||||
<div className="code-with-header">
|
||||
<div className="code-header">{title}</div>
|
||||
|
||||
<CodeBlock language={language}>
|
||||
{ children }
|
||||
</CodeBlock>
|
||||
<CodeBlock language={language}>{children}</CodeBlock>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,39 +1,39 @@
|
||||
import React, { useEffect } from "react";
|
||||
import Prism from "prismjs";
|
||||
import "../css/prismjs-github-theme.css";
|
||||
import React, { useEffect } from 'react'
|
||||
import Prism from 'prismjs'
|
||||
import '../css/prismjs-github-theme.css'
|
||||
|
||||
export default function CodeHighlight(props = {}) {
|
||||
const codeRef = React.createRef();
|
||||
const codeRef = React.createRef()
|
||||
const {
|
||||
prefixCls = "code-highlight-wrapper",
|
||||
prefixCls = 'code-highlight-wrapper',
|
||||
className,
|
||||
language,
|
||||
source,
|
||||
children,
|
||||
...others
|
||||
} = props;
|
||||
const langCls = language ? `language-${language}` : "";
|
||||
} = props
|
||||
const langCls = language ? `language-${language}` : ''
|
||||
async function highlight() {
|
||||
if (codeRef.current) {
|
||||
Prism.highlightElement(codeRef.current);
|
||||
Prism.highlightElement(codeRef.current)
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
highlight();
|
||||
}, [language, source]);
|
||||
highlight()
|
||||
}, [language, source])
|
||||
return (
|
||||
<pre
|
||||
className={`${prefixCls} ${className || ""} ${langCls}`}
|
||||
className={`${prefixCls} ${className || ''} ${langCls}`}
|
||||
{...others}
|
||||
style={{
|
||||
borderBottomLeftRadius: "10px",
|
||||
borderBottomRightRadius: "10px",
|
||||
paddingLeft: "15px",
|
||||
borderBottomLeftRadius: '10px',
|
||||
borderBottomRightRadius: '10px',
|
||||
paddingLeft: '15px',
|
||||
}}
|
||||
>
|
||||
<code className={langCls} ref={codeRef}>
|
||||
{source || children}
|
||||
</code>
|
||||
</pre>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
import React from 'react'
|
||||
import Details from '@theme/MDXComponents/Details'
|
||||
|
||||
export default function Collapse(props: { children: React.ReactNode; title: string }) {
|
||||
const { children, title } = props;
|
||||
return (
|
||||
<Details>
|
||||
<summary mdxType="summary">{title}</summary>
|
||||
{children}
|
||||
</Details>
|
||||
)
|
||||
export default function Collapse(props: {
|
||||
children: React.ReactNode
|
||||
title: string
|
||||
}) {
|
||||
const { children, title } = props
|
||||
return (
|
||||
<Details>
|
||||
<summary mdxType="summary">{title}</summary>
|
||||
{children}
|
||||
</Details>
|
||||
)
|
||||
}
|
||||
|
@ -3,20 +3,20 @@ import { Sun, Moon } from 'react-feather'
|
||||
|
||||
const DarkModeToggle = () => {
|
||||
const [isDarkMode, setIsDarkMode] = useState(false)
|
||||
|
||||
|
||||
const toggleDarkMode = () => {
|
||||
setIsDarkMode(!isDarkMode)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className='flex items-end'>
|
||||
<Sun strokeWidth={2} size={22} className='text-neutral-500' />
|
||||
<div className="flex items-end">
|
||||
<Sun strokeWidth={2} size={22} className="text-neutral-500" />
|
||||
<button
|
||||
type='button'
|
||||
aria-pressed='false'
|
||||
type="button"
|
||||
aria-pressed="false"
|
||||
className={`
|
||||
relative inline-flex
|
||||
h-6 w-11 mx-3 flex-shrink-0 cursor-pointer
|
||||
relative mx-3
|
||||
inline-flex h-6 w-11 flex-shrink-0 cursor-pointer
|
||||
rounded-full border-2 border-transparent
|
||||
bg-neutral-500
|
||||
transition-colors duration-200 ease-in-out focus:outline-none
|
||||
@ -24,20 +24,18 @@ const DarkModeToggle = () => {
|
||||
onClick={() => toggleDarkMode()}
|
||||
>
|
||||
<span
|
||||
aria-hidden='true'
|
||||
aria-hidden="true"
|
||||
className={`
|
||||
${isDarkMode ? 'translate-x-5' : 'translate-x-0'}
|
||||
inline-block h-5 w-5
|
||||
bg-white shadow-lg rounded-full ring-0
|
||||
transform transition duration-200 ease-in-out
|
||||
transform rounded-full bg-white shadow-lg
|
||||
ring-0 transition duration-200 ease-in-out
|
||||
`}
|
||||
/>
|
||||
</button>
|
||||
|
||||
<Moon strokeWidth={2} size={22} className='text-neutral-500' />
|
||||
<Moon strokeWidth={2} size={22} className="text-neutral-500" />
|
||||
</div>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,31 +1,29 @@
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import './emailSignupForm.css'
|
||||
|
||||
const EmailSignupForm = ({ placeholder }) => {
|
||||
return (
|
||||
<form
|
||||
className="email-signup-form"
|
||||
action="https://gmail.us4.list-manage.com/subscribe/post?u=8139c7de74df98aa17054b235&id=f0c6ba5f1d"
|
||||
method="post"
|
||||
className="email-signup-form"
|
||||
action="https://gmail.us4.list-manage.com/subscribe/post?u=8139c7de74df98aa17054b235&id=f0c6ba5f1d"
|
||||
method="post"
|
||||
>
|
||||
|
||||
<input
|
||||
aria-label="Email address"
|
||||
name="EMAIL"
|
||||
type="email"
|
||||
required
|
||||
className="input"
|
||||
placeholder={placeholder || "Enter your email"}
|
||||
placeholder={placeholder || 'Enter your email'}
|
||||
/>
|
||||
<div className="">
|
||||
<button className="button button--primary" type="submit">
|
||||
Subscribe
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default EmailSignupForm;
|
||||
export default EmailSignupForm
|
||||
|
@ -40,11 +40,11 @@ const SeeTheCodeButton = ({ repoUrl }) => (
|
||||
<button
|
||||
className={`
|
||||
flex items-center
|
||||
text-xs
|
||||
px-2.5 py-1 rounded
|
||||
bg-transparent border border-yellow-500 text-neutral-500
|
||||
hover:text-neutral-400
|
||||
transition ease-out duration-200
|
||||
rounded
|
||||
border border-yellow-500 bg-transparent
|
||||
px-2.5 py-1 text-xs text-neutral-500
|
||||
transition
|
||||
duration-200 ease-out hover:text-neutral-400
|
||||
`}
|
||||
>
|
||||
<span>See the code</span>
|
||||
@ -58,11 +58,11 @@ const DemoButton = ({ demoUrl }) => (
|
||||
<button
|
||||
className={`
|
||||
flex items-center
|
||||
text-xs
|
||||
px-2.5 py-1 rounded
|
||||
bg-yellow-500 text-white
|
||||
hover:bg-yellow-400
|
||||
transition ease-out duration-200
|
||||
rounded
|
||||
bg-yellow-500 px-2.5 py-1
|
||||
text-xs text-white
|
||||
transition
|
||||
duration-200 ease-out hover:bg-yellow-400
|
||||
`}
|
||||
>
|
||||
<span>Demo</span>
|
||||
@ -76,17 +76,17 @@ const ExampleCard = (props) => (
|
||||
{/* Top half */}
|
||||
<div
|
||||
className={`
|
||||
flex
|
||||
h-40 flex-col rounded rounded-b-none
|
||||
border-l border-r
|
||||
border-t border-yellow-500/25
|
||||
bg-yellow-500/5
|
||||
border-t border-l border-r border-yellow-500/25
|
||||
rounded rounded-b-none
|
||||
flex flex-col
|
||||
h-40
|
||||
p-5
|
||||
`}
|
||||
>
|
||||
<div className="mb-4">
|
||||
<h4 className="mb-4 text-neutral-700">{props.title}</h4>
|
||||
<p className="text-sm mb-4 text-neutral-500">{props.description}</p>
|
||||
<p className="mb-4 text-sm text-neutral-500">{props.description}</p>
|
||||
<div>
|
||||
<img
|
||||
className="inline w-6 rounded-full"
|
||||
@ -103,10 +103,10 @@ const ExampleCard = (props) => (
|
||||
{/* Bottom half */}
|
||||
<div
|
||||
className={`
|
||||
bg-yellow-500/20
|
||||
border-b border-l border-r border-yellow-500/25
|
||||
rounded rounded-t-none
|
||||
flex flex-col
|
||||
flex
|
||||
flex-col rounded rounded-t-none border-b
|
||||
border-l border-r
|
||||
border-yellow-500/25 bg-yellow-500/20
|
||||
p-5
|
||||
`}
|
||||
>
|
||||
@ -136,7 +136,7 @@ const ExampleWaspApps = () => {
|
||||
<SectionContainer className="space-y-16" id="examples">
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 text-center">
|
||||
<h2 className="text-xl lg:text-2xl text-neutral-700 mb-4">
|
||||
<h2 className="mb-4 text-xl text-neutral-700 lg:text-2xl">
|
||||
Show, don't tell.
|
||||
</h2>
|
||||
<p className="text-neutral-500">
|
||||
@ -158,11 +158,11 @@ const ExampleWaspApps = () => {
|
||||
<Link to="https://github.com/wasp-lang/wasp/tree/main/examples">
|
||||
<span
|
||||
className={`
|
||||
text-neutral-500
|
||||
underline decoration-2 decoration-yellow-500 font-medium
|
||||
hover:text-neutral-400
|
||||
transition ease-out duration-200
|
||||
flex items-center
|
||||
flex
|
||||
items-center font-medium text-neutral-500 underline
|
||||
decoration-yellow-500
|
||||
decoration-2 transition duration-200
|
||||
ease-out hover:text-neutral-400
|
||||
`}
|
||||
>
|
||||
<span>See all examples</span>
|
||||
|
@ -7,75 +7,113 @@ import SectionContainer from './Layouts/SectionContainer'
|
||||
const faqs = [
|
||||
{
|
||||
question: 'How is Wasp different from Next.js / Nuxt.js / Gatsby?',
|
||||
answer: <p>
|
||||
<strong>TL;DR</strong> - These are frontend-first frameworks, with some limited backend capabilities.
|
||||
Wasp is a full-stack framework.
|
||||
<br/><br/>
|
||||
The main difference between Wasp and the solutions listed above is that Wasp is a trully full-stack
|
||||
framework, meaning it brings both back-end and database next to front-end. You can think of it as
|
||||
Ruby on Rails, but made for JS (React & Node.js) and full-stack.
|
||||
<br/><br/>
|
||||
Next.js, Gatsby and others started out as frontend frameworks for static sites. Although some of them
|
||||
now offer an option to use serverless functions, you still have to bring your own database and you'll
|
||||
also need some kind of a server/backend if you'll need to run more complex operations.
|
||||
</p>
|
||||
answer: (
|
||||
<p>
|
||||
<strong>TL;DR</strong> - These are frontend-first frameworks, with some
|
||||
limited backend capabilities. Wasp is a full-stack framework.
|
||||
<br />
|
||||
<br />
|
||||
The main difference between Wasp and the solutions listed above is that
|
||||
Wasp is a trully full-stack framework, meaning it brings both back-end
|
||||
and database next to front-end. You can think of it as Ruby on Rails,
|
||||
but made for JS (React & Node.js) and full-stack.
|
||||
<br />
|
||||
<br />
|
||||
Next.js, Gatsby and others started out as frontend frameworks for static
|
||||
sites. Although some of them now offer an option to use serverless
|
||||
functions, you still have to bring your own database and you'll also
|
||||
need some kind of a server/backend if you'll need to run more complex
|
||||
operations.
|
||||
</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
question: 'How is Wasp different from Ruby on Rails or Django?',
|
||||
answer: <p>
|
||||
<strong>TL;DR</strong> - while Ruby on Rails and Django are considered full-stack frameworks, they require extra work to support modern “desktop” experience that most web apps offer today.
|
||||
Wasp is made specifically for that use case and supports it out-of-the-box, with a lot of extra niceties that make developer's life easier.
|
||||
<br/><br/>
|
||||
Ruby on Rails and Django both fall in the category of full-stack web frameworks - they allow you to write backend/server code and also generate html/css that gets sent to the client.
|
||||
<br/><br/>
|
||||
The main reason why they are often today not used as a standalone solution, but rather as an API server combined with frontend libraries such as React & Vue, is to add support for the client side manipulation of DOM.
|
||||
That’s especially important for web applications with a lot of dynamic content (e.g. dashboards) where you want “smooth” experience of a desktop app.
|
||||
Imagine expanding a post on Twitter or moving a Trello card and suddenly the whole site starts reloading - that's why you need React or Vue.
|
||||
<br/><br/>
|
||||
Wasp supports this behaviour out-of-the-box, along with all the best practices. One of the biggest time savers is automatic sharing of data models between the database, frontend
|
||||
and the client - with RoR of Django you’d typically have implement a custom API (e.g. rest or graphql), while with Wasp you can skip that step in entirety.
|
||||
</p>
|
||||
answer: (
|
||||
<p>
|
||||
<strong>TL;DR</strong> - while Ruby on Rails and Django are considered
|
||||
full-stack frameworks, they require extra work to support modern
|
||||
“desktop” experience that most web apps offer today. Wasp is made
|
||||
specifically for that use case and supports it out-of-the-box, with a
|
||||
lot of extra niceties that make developer's life easier.
|
||||
<br />
|
||||
<br />
|
||||
Ruby on Rails and Django both fall in the category of full-stack web
|
||||
frameworks - they allow you to write backend/server code and also
|
||||
generate html/css that gets sent to the client.
|
||||
<br />
|
||||
<br />
|
||||
The main reason why they are often today not used as a standalone
|
||||
solution, but rather as an API server combined with frontend libraries
|
||||
such as React & Vue, is to add support for the client side manipulation
|
||||
of DOM. That’s especially important for web applications with a lot of
|
||||
dynamic content (e.g. dashboards) where you want “smooth” experience of
|
||||
a desktop app. Imagine expanding a post on Twitter or moving a Trello
|
||||
card and suddenly the whole site starts reloading - that's why you need
|
||||
React or Vue.
|
||||
<br />
|
||||
<br />
|
||||
Wasp supports this behaviour out-of-the-box, along with all the best
|
||||
practices. One of the biggest time savers is automatic sharing of data
|
||||
models between the database, frontend and the client - with RoR of
|
||||
Django you’d typically have implement a custom API (e.g. rest or
|
||||
graphql), while with Wasp you can skip that step in entirety.
|
||||
</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
question: 'How hard is it to learn Wasp?',
|
||||
answer: <p>
|
||||
We measured! <strong>It takes about 30 minutes to get going</strong>, and
|
||||
most users find it pretty straight-forward.
|
||||
Since the majority of your coding will still be done in the tools you're familiar with (currently
|
||||
React & Node.js), it's really a marginal change to what you're used to.
|
||||
<br/><br/>
|
||||
The reason for that is that Wasp is a really simple configuration language, without any
|
||||
loops or variables - you can think of it as a JSON that is easier to read and is a bit smarter.
|
||||
<br/><br/>
|
||||
Still, although simple (and we plan to keep it that way), it's a real language so you get all the
|
||||
IDE goodies with it - syntax highlighting, auto-completion, live error reporting, ...
|
||||
</p>
|
||||
answer: (
|
||||
<p>
|
||||
We measured! <strong>It takes about 30 minutes to get going</strong>,
|
||||
and most users find it pretty straight-forward. Since the majority of
|
||||
your coding will still be done in the tools you're familiar with
|
||||
(currently React & Node.js), it's really a marginal change to what
|
||||
you're used to.
|
||||
<br />
|
||||
<br />
|
||||
The reason for that is that Wasp is a really simple configuration
|
||||
language, without any loops or variables - you can think of it as a JSON
|
||||
that is easier to read and is a bit smarter.
|
||||
<br />
|
||||
<br />
|
||||
Still, although simple (and we plan to keep it that way), it's a real
|
||||
language so you get all the IDE goodies with it - syntax highlighting,
|
||||
auto-completion, live error reporting, ...
|
||||
</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
question: 'Do you support only React & Node.js currently?',
|
||||
answer:<p>
|
||||
Yes, that is currently the supported stack. But, Wasp is being developed as a language/framework and
|
||||
architecture-agnostic tool, so we plan to add support for more languages and frameworks in the future.
|
||||
<br/><br/>
|
||||
This is something we're pretty excited about and think could be potentially be a unique opportunity
|
||||
due to the language approach we're taking with Wasp.
|
||||
</p>
|
||||
}
|
||||
answer: (
|
||||
<p>
|
||||
Yes, that is currently the supported stack. But, Wasp is being developed
|
||||
as a language/framework and architecture-agnostic tool, so we plan to
|
||||
add support for more languages and frameworks in the future.
|
||||
<br />
|
||||
<br />
|
||||
This is something we're pretty excited about and think could be
|
||||
potentially be a unique opportunity due to the language approach we're
|
||||
taking with Wasp.
|
||||
</p>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
const FaqItem = ({ keyP, faq }) => {
|
||||
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
|
||||
|
||||
return (
|
||||
<div className='py-6'>
|
||||
<dt key={keyP} className='text-base text-neutral-700'>
|
||||
<div className="py-6">
|
||||
<dt key={keyP} className="text-base text-neutral-700">
|
||||
<button
|
||||
className='text-left w-full flex items-center justify-between'
|
||||
onClick={() => { setIsExpanded(!isExpanded) }}
|
||||
className="flex w-full items-center justify-between text-left"
|
||||
onClick={() => {
|
||||
setIsExpanded(!isExpanded)
|
||||
}}
|
||||
>
|
||||
<span>{faq.question}</span>
|
||||
<div className='ml-6 text-yellow-500'>
|
||||
<div className="ml-6 text-yellow-500">
|
||||
{isExpanded ? (
|
||||
<ChevronDown size={20} />
|
||||
) : (
|
||||
@ -84,11 +122,7 @@ const FaqItem = ({ keyP, faq }) => {
|
||||
</div>
|
||||
</button>
|
||||
</dt>
|
||||
{isExpanded && (
|
||||
<dd className='mt-2 text-neutral-500'>
|
||||
{faq.answer}
|
||||
</dd>
|
||||
)}
|
||||
{isExpanded && <dd className="mt-2 text-neutral-500">{faq.answer}</dd>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -96,29 +130,29 @@ const FaqItem = ({ keyP, faq }) => {
|
||||
const Faq = () => {
|
||||
return (
|
||||
<SectionContainer>
|
||||
<div className='grid grid-cols-12' id='faq'>
|
||||
<div className='col-span-12 text-center'>
|
||||
<h2 className='text-xl lg:text-2xl text-neutral-700 mb-4'>
|
||||
<div className="grid grid-cols-12" id="faq">
|
||||
<div className="col-span-12 text-center">
|
||||
<h2 className="mb-4 text-xl text-neutral-700 lg:text-2xl">
|
||||
Frequently asked questions
|
||||
</h2>
|
||||
<p className='text-neutral-500'>
|
||||
<p className="text-neutral-500">
|
||||
For anything not covered here, join
|
||||
<a
|
||||
href='https://discord.gg/rzdnErX'
|
||||
className='underline decoration-2 decoration-yellow-500 font-medium'
|
||||
<a
|
||||
href="https://discord.gg/rzdnErX"
|
||||
className="font-medium underline decoration-yellow-500 decoration-2"
|
||||
>
|
||||
our Discord
|
||||
</a>!
|
||||
</a>
|
||||
!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dl className='mt-6 max-w-3xl mx-auto divide-y divide-neutral-300'>
|
||||
<dl className="mx-auto mt-6 max-w-3xl divide-y divide-neutral-300">
|
||||
{faqs.map((faq, idx) => (
|
||||
<FaqItem keyP={idx} key={idx} faq={faq} />
|
||||
))}
|
||||
</dl>
|
||||
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,23 @@
|
||||
import React from 'react'
|
||||
import Link from '@docusaurus/Link'
|
||||
import classNames from 'classnames'
|
||||
import { Terminal, Layers, Coffee, Code, Unlock, Repeat, Send, Link2, Grid, ArrowRight, Globe, Settings, Mail, Type, Star } from 'react-feather'
|
||||
import {
|
||||
Terminal,
|
||||
Layers,
|
||||
Coffee,
|
||||
Code,
|
||||
Unlock,
|
||||
Repeat,
|
||||
Send,
|
||||
Link2,
|
||||
Grid,
|
||||
ArrowRight,
|
||||
Globe,
|
||||
Settings,
|
||||
Mail,
|
||||
Type,
|
||||
Star,
|
||||
} from 'react-feather'
|
||||
|
||||
import SectionContainer from './Layouts/SectionContainer'
|
||||
|
||||
@ -9,33 +25,27 @@ import styles from '../pages/styles.module.css'
|
||||
|
||||
const Lang = () => (
|
||||
<>
|
||||
<span className='underline decoration-yellow-500 font-bold'>
|
||||
language
|
||||
</span>
|
||||
<span className="font-bold underline decoration-yellow-500">language</span>
|
||||
</>
|
||||
)
|
||||
|
||||
const Feature = ({ Icon, title, description, url }) => (
|
||||
<div className='mb-10 md:mb-0 space-y-4'>
|
||||
<div className='flex items-center'>
|
||||
<div className="mb-10 space-y-4 md:mb-0">
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className={`
|
||||
inline-flex h-8 w-8 rounded-md
|
||||
items-center justify-center
|
||||
text-yellow-500 bg-neutral-700
|
||||
inline-flex h-8 w-8 items-center
|
||||
justify-center rounded-md
|
||||
bg-neutral-700 text-yellow-500
|
||||
|
||||
`}
|
||||
>
|
||||
<Icon size={20} />
|
||||
</div>
|
||||
<dt className='ml-4 text-neutral-700'>
|
||||
{ title }
|
||||
</dt>
|
||||
<dt className="ml-4 text-neutral-700">{title}</dt>
|
||||
</div>
|
||||
<p className='text-neutral-700'>
|
||||
{ description }
|
||||
</p>
|
||||
<TextLink url={url} label='Learn more' />
|
||||
<p className="text-neutral-700">{description}</p>
|
||||
<TextLink url={url} label="Learn more" />
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -48,10 +58,10 @@ const TextLink = ({ url, label }) => (
|
||||
text-neutral-500 hover:text-neutral-400
|
||||
`}
|
||||
>
|
||||
<div className='group flex gap-1 items-center'>
|
||||
<div className="group flex items-center gap-1">
|
||||
<span>{label}</span>
|
||||
<div className='transition-all group-hover:ml-0.5'>
|
||||
<span className='text-yellow-600'>
|
||||
<div className="transition-all group-hover:ml-0.5">
|
||||
<span className="text-yellow-600">
|
||||
<ArrowRight size={14} strokeWidth={2} />
|
||||
</span>
|
||||
</div>
|
||||
@ -62,13 +72,12 @@ const TextLink = ({ url, label }) => (
|
||||
|
||||
const Features = () => {
|
||||
return (
|
||||
<SectionContainer className='space-y-16 lg:py-18'>
|
||||
<dl className='grid grid-cols-1 lg:grid-cols-4 md:gap-16 lg:gap-x-8 xl:gap-x-16'>
|
||||
|
||||
<SectionContainer className="lg:py-18 space-y-16">
|
||||
<dl className="grid grid-cols-1 md:gap-16 lg:grid-cols-4 lg:gap-x-8 xl:gap-x-16">
|
||||
<Feature
|
||||
Icon={Star}
|
||||
title='Open Source'
|
||||
url='https://github.com/wasp-lang/wasp'
|
||||
title="Open Source"
|
||||
url="https://github.com/wasp-lang/wasp"
|
||||
description={`
|
||||
This is the way. Wasp is fully open-source and you're welcome to contribute!
|
||||
`}
|
||||
@ -76,8 +85,8 @@ const Features = () => {
|
||||
|
||||
<Feature
|
||||
Icon={Unlock}
|
||||
title='Full-stack Auth'
|
||||
url='/blog/2023/04/12/auth-ui'
|
||||
title="Full-stack Auth"
|
||||
url="/blog/2023/04/12/auth-ui"
|
||||
description={`
|
||||
Add login with social providers or email in a few lines of code with powerful UI helpers. No third party vendor lock-in.
|
||||
`}
|
||||
@ -85,8 +94,8 @@ const Features = () => {
|
||||
|
||||
<Feature
|
||||
Icon={Link2}
|
||||
title='RPC (Client <-> Server)'
|
||||
url='/docs/data-model/operations/overview'
|
||||
title="RPC (Client <-> Server)"
|
||||
url="/docs/data-model/operations/overview"
|
||||
description={`
|
||||
Wasp provides a typesafe RPC layer that instantly brings your data models and server logic to the client.
|
||||
`}
|
||||
@ -94,18 +103,17 @@ const Features = () => {
|
||||
|
||||
<Feature
|
||||
Icon={Send}
|
||||
title='Simple Deployment'
|
||||
url='/docs/advanced/deployment/overview'
|
||||
title="Simple Deployment"
|
||||
url="/docs/advanced/deployment/overview"
|
||||
description={`
|
||||
Deploy your app to any platform. Wasp offers CLI helpers for the most popular options.
|
||||
`}
|
||||
/>
|
||||
|
||||
|
||||
<Feature
|
||||
Icon={Settings}
|
||||
title='Jobs'
|
||||
url='/docs/advanced/jobs'
|
||||
title="Jobs"
|
||||
url="/docs/advanced/jobs"
|
||||
description={`
|
||||
Easily define, schedule and run specialized server tasks.
|
||||
Persistent, retryable, delayable.
|
||||
@ -114,8 +122,8 @@ const Features = () => {
|
||||
|
||||
<Feature
|
||||
Icon={Mail}
|
||||
title='Email Sending'
|
||||
url='/docs/advanced/email'
|
||||
title="Email Sending"
|
||||
url="/docs/advanced/email"
|
||||
description={`
|
||||
All you need to do is connect an email provider and you can send emails!
|
||||
`}
|
||||
@ -123,8 +131,8 @@ const Features = () => {
|
||||
|
||||
<Feature
|
||||
Icon={Type}
|
||||
title='Full-stack Type Safety'
|
||||
url='/docs/tutorial/queries#implementing-a-query'
|
||||
title="Full-stack Type Safety"
|
||||
url="/docs/tutorial/queries#implementing-a-query"
|
||||
description={`
|
||||
Full support for TypeScript with auto-generated types that span the whole stack.
|
||||
`}
|
||||
@ -132,8 +140,8 @@ const Features = () => {
|
||||
|
||||
<Feature
|
||||
Icon={Grid}
|
||||
title='And More!'
|
||||
url='/docs'
|
||||
title="And More!"
|
||||
url="/docs"
|
||||
description={`
|
||||
Custom API routes, database seeding, optimistic updates, automatic cache invalidation on the client, ...
|
||||
`}
|
||||
@ -144,17 +152,16 @@ const Features = () => {
|
||||
}
|
||||
|
||||
const FeaturesWithSkewedBorder = () => (
|
||||
<div className='relative'>
|
||||
<div className="relative">
|
||||
<div className={classNames(styles.sectionSkewedContainer)}>
|
||||
<div
|
||||
className={classNames(
|
||||
styles.sectionSkewed,
|
||||
'border-b border-yellow-500/25 bg-neutral-100/50'
|
||||
)}
|
||||
>
|
||||
</div>
|
||||
></div>
|
||||
</div>
|
||||
<div className='relative'>
|
||||
<div className="relative">
|
||||
<Features />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copied from
|
||||
// https://github.com/redwoodjs/redwood/blob/bd903c5755925ea7174775a2fdaba371b700c910/docs/src/components/FileExtSwitcher.tsx
|
||||
// Copied from
|
||||
// https://github.com/redwoodjs/redwood/blob/bd903c5755925ea7174775a2fdaba371b700c910/docs/src/components/FileExtSwitcher.tsx
|
||||
|
||||
import * as React from 'react'
|
||||
|
||||
|
@ -57,7 +57,7 @@ const Logo = () => (
|
||||
<Link to="/">
|
||||
<img src="img/lp/wasp-logo.png" width={35} height={35} alt="Wasp Logo" />
|
||||
</Link>
|
||||
<span className="ml-3 font-semibold text-lg text-neutral-700">Wasp</span>
|
||||
<span className="ml-3 text-lg font-semibold text-neutral-700">Wasp</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -71,8 +71,8 @@ const Segment = ({ title, links }) => (
|
||||
<a
|
||||
href={l.url}
|
||||
className={`
|
||||
text-sm text-neutral-500 hover:text-neutral-400
|
||||
transition-colors
|
||||
text-sm text-neutral-500 transition-colors
|
||||
hover:text-neutral-400
|
||||
`}
|
||||
>
|
||||
{l.text}
|
||||
@ -111,17 +111,17 @@ const Footer = () => {
|
||||
inputBgColor="bg-transparent"
|
||||
/>
|
||||
|
||||
<span className="flex items-center mt-6">
|
||||
<small className="text-neutral-500 text-xs">Backed by</small>
|
||||
<span className="mt-6 flex items-center">
|
||||
<small className="text-xs text-neutral-500">Backed by</small>
|
||||
<img
|
||||
className="w-24 ml-2"
|
||||
className="ml-2 w-24"
|
||||
src="img/lp/yc-logo-rounded.png"
|
||||
alt="YC"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-8 mt-8">
|
||||
<div className="mt-8 pt-8">
|
||||
<Logo />
|
||||
<div className="flex justify-between">
|
||||
<p className="mt-4 text-xs text-neutral-400">
|
||||
|
@ -5,9 +5,17 @@ import './prismCustomization'
|
||||
|
||||
import CodeHighlight from './CodeHighlight'
|
||||
|
||||
import { Terminal, ArrowUpRight, Play, BookOpen, Grid, Layout, Trello } from 'react-feather'
|
||||
import {
|
||||
Terminal,
|
||||
ArrowUpRight,
|
||||
Play,
|
||||
BookOpen,
|
||||
Grid,
|
||||
Layout,
|
||||
Trello,
|
||||
} from 'react-feather'
|
||||
|
||||
// Terminal, BookOpen, Grid, Layout, Trello, FileText
|
||||
// Terminal, BookOpen, Grid, Layout, Trello, FileText
|
||||
|
||||
import InstallCmd from './InstallCmd'
|
||||
import SectionContainer from './Layouts/SectionContainer'
|
||||
@ -15,9 +23,15 @@ import SectionContainer from './Layouts/SectionContainer'
|
||||
const StartIcon = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" strokeWidth="2" strokeLinecap="round"
|
||||
strokeLinejoin="round" opacity="0.5"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
opacity="0.5"
|
||||
>
|
||||
<polyline points="13 17 18 12 13 7"></polyline>
|
||||
<polyline points="6 17 11 12 6 7"></polyline>
|
||||
@ -25,16 +39,16 @@ const StartIcon = () => (
|
||||
)
|
||||
|
||||
const ActionButtons = () => (
|
||||
<div className='flex items-center gap-2'>
|
||||
<Link to='/docs/quick-start'>
|
||||
<div className="flex items-center gap-2">
|
||||
<Link to="/docs/quick-start">
|
||||
<button
|
||||
className={`
|
||||
inline-flex items-center space-x-2
|
||||
px-3 py-2 rounded
|
||||
bg-yellow-500 text-white text-sm leading-4
|
||||
border border-yellow-500 hover:border-yellow-400
|
||||
hover:bg-yellow-400
|
||||
transition ease-out duration-200
|
||||
rounded border border-yellow-500
|
||||
bg-yellow-500 px-3 py-2 text-sm
|
||||
leading-4 text-white transition
|
||||
duration-200
|
||||
ease-out hover:border-yellow-400 hover:bg-yellow-400
|
||||
`}
|
||||
>
|
||||
<Terminal size={16} />
|
||||
@ -42,16 +56,16 @@ const ActionButtons = () => (
|
||||
</button>
|
||||
</Link>
|
||||
|
||||
<Link to='/docs'>
|
||||
<Link to="/docs">
|
||||
<button
|
||||
className={`
|
||||
inline-flex items-center space-x-2
|
||||
px-3 py-2 rounded
|
||||
border border-neutral-500
|
||||
rounded border border-neutral-500
|
||||
px-3 py-2
|
||||
text-sm leading-4
|
||||
text-neutral-700
|
||||
hover:text-neutral-400 hover:border-neutral-400
|
||||
transition ease-out duration-200
|
||||
transition duration-200
|
||||
ease-out hover:border-neutral-400 hover:text-neutral-400
|
||||
`}
|
||||
>
|
||||
<BookOpen size={16} />
|
||||
@ -68,7 +82,7 @@ const PHBadge = () => (
|
||||
rel="noreferrer"
|
||||
>
|
||||
<img
|
||||
className='w-32 md:w-[180px]'
|
||||
className="w-32 md:w-[180px]"
|
||||
src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=277135&theme=light&period=daily"
|
||||
alt="Wasp-lang Alpha - Develop web apps in React & Node.js with no boilerplate | Product Hunt"
|
||||
/>
|
||||
@ -76,8 +90,7 @@ const PHBadge = () => (
|
||||
)
|
||||
|
||||
const Hero = () => {
|
||||
const codeString =
|
||||
`app todoApp {
|
||||
const codeString = `app todoApp {
|
||||
title: "ToDo App", // visible in the browser tab
|
||||
auth: { // full-stack auth out-of-the-box
|
||||
userEntity: User,
|
||||
@ -100,96 +113,92 @@ entity Task {=psl ... psl=} // Your Prisma data model.
|
||||
`
|
||||
|
||||
return (
|
||||
<SectionContainer className='pb-5 pt-24'>
|
||||
<div className='lg:grid lg:grid-cols-12 lg:gap-16'>
|
||||
|
||||
<div className='lg:col-span-6 space-y-12 z-10'>
|
||||
<SectionContainer className="pb-5 pt-24">
|
||||
<div className="lg:grid lg:grid-cols-12 lg:gap-16">
|
||||
<div className="z-10 space-y-12 lg:col-span-6">
|
||||
{/* Hero title and subtitle */}
|
||||
<div>
|
||||
<h1
|
||||
className={`
|
||||
text-4xl lg:text-5xl lg:leading-tight
|
||||
font-extrabold text-neutral-700
|
||||
text-4xl font-extrabold text-neutral-700
|
||||
lg:text-5xl lg:leading-tight
|
||||
`}
|
||||
>
|
||||
Develop full-stack web apps <span className='underline decoration-yellow-500'>faster</span>.
|
||||
Develop full-stack web apps{' '}
|
||||
<span className="underline decoration-yellow-500">faster</span>.
|
||||
</h1>
|
||||
|
||||
<p className='mt-4 sm:mt-5 text-xl lg:text-xl text-neutral-500'>
|
||||
Rails-like framework for React, Node.js and Prisma. Build your app in a day and deploy it with a single CLI command.
|
||||
<p className="mt-4 text-xl text-neutral-500 sm:mt-5 lg:text-xl">
|
||||
Rails-like framework for React, Node.js and Prisma. Build your app
|
||||
in a day and deploy it with a single CLI command.
|
||||
</p>
|
||||
</div> {/* EOF Hero title and subtitle */}
|
||||
|
||||
</div>{' '}
|
||||
{/* EOF Hero title and subtitle */}
|
||||
<ActionButtons />
|
||||
<div className="flex flex-col gap-4">
|
||||
<small className="text-xs text-neutral-500">Works with</small>
|
||||
|
||||
<div className='flex flex-col gap-4'>
|
||||
<small className='text-neutral-500 text-xs'>Works with</small>
|
||||
|
||||
<div className='flex'>
|
||||
<div className="flex">
|
||||
<img
|
||||
className='h-8 md:h-10 pr-5 md:pr-10'
|
||||
src='img/lp/react-logo-gray.svg'
|
||||
alt='React'
|
||||
className="h-8 pr-5 md:h-10 md:pr-10"
|
||||
src="img/lp/react-logo-gray.svg"
|
||||
alt="React"
|
||||
/>
|
||||
<img
|
||||
className='h-8 md:h-10 pr-5 md:pr-10'
|
||||
src='img/lp/nodejs-logo-gray.svg'
|
||||
alt='Node'
|
||||
className="h-8 pr-5 md:h-10 md:pr-10"
|
||||
src="img/lp/nodejs-logo-gray.svg"
|
||||
alt="Node"
|
||||
/>
|
||||
<img
|
||||
className='h-8 md:h-10 pr-5 md:pr-10'
|
||||
src='img/lp/prisma-logo-gray.svg'
|
||||
alt='Prisma'
|
||||
className="h-8 pr-5 md:h-10 md:pr-10"
|
||||
src="img/lp/prisma-logo-gray.svg"
|
||||
alt="Prisma"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span className='flex items-center mt-6'>
|
||||
<small className='text-neutral-500 text-xs'>Backed by</small>
|
||||
<span className="mt-6 flex items-center">
|
||||
<small className="text-xs text-neutral-500">Backed by</small>
|
||||
<img
|
||||
className='w-24 ml-2'
|
||||
src='img/lp/yc-logo-rounded.png'
|
||||
alt='YC'
|
||||
className="ml-2 w-24"
|
||||
src="img/lp/yc-logo-rounded.png"
|
||||
alt="YC"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className='lg:col-span-6 lg:mt-0 mt-16'>
|
||||
<div className='relative flex flex-col items-center justify-center'>
|
||||
<div className="mt-16 lg:col-span-6 lg:mt-0">
|
||||
<div className="relative flex flex-col items-center justify-center">
|
||||
{/* Editor header bar */}
|
||||
<div className='bg-yellow-500/10 flex h-6 w-full items-center justify-between rounded-t-md px-2'>
|
||||
<Link to='https://github.com/wasp-lang/wasp/blob/main/examples/todo-typescript/main.wasp'>
|
||||
<div className="flex h-6 w-full items-center justify-between rounded-t-md bg-yellow-500/10 px-2">
|
||||
<Link to="https://github.com/wasp-lang/wasp/blob/main/examples/todo-typescript/main.wasp">
|
||||
<span
|
||||
className={`
|
||||
text-sm text-neutral-500 flex items-center space-x-1 hover:text-neutral-400
|
||||
transition ease-out duration-200
|
||||
flex items-center space-x-1 text-sm text-neutral-500 transition
|
||||
duration-200 ease-out hover:text-neutral-400
|
||||
`}
|
||||
>
|
||||
<span>todoApp.wasp</span>
|
||||
<ArrowUpRight size={14} />
|
||||
<span className='text-neutral-400'>· Wasp config file</span>
|
||||
<span className="text-neutral-400">· Wasp config file</span>
|
||||
</span>
|
||||
</Link>
|
||||
<div className='flex space-x-2'>
|
||||
<div className='bg-yellow-500 h-2 w-2 rounded-full' />
|
||||
<div className='bg-yellow-500 h-2 w-2 rounded-full' />
|
||||
<div className='bg-yellow-500 h-2 w-2 rounded-full' />
|
||||
<div className="flex space-x-2">
|
||||
<div className="h-2 w-2 rounded-full bg-yellow-500" />
|
||||
<div className="h-2 w-2 rounded-full bg-yellow-500" />
|
||||
<div className="h-2 w-2 rounded-full bg-yellow-500" />
|
||||
</div>
|
||||
</div>
|
||||
{/* Editor body */}
|
||||
<div className='w-full text-sm shadow-2xl rounded-b-md'>
|
||||
<CodeHighlight
|
||||
language='wasp'
|
||||
source={codeString}
|
||||
/>
|
||||
</div> {/* EOF code block wrapper */}
|
||||
</div> {/* EOF wrapper of header + code */}
|
||||
</div> {/* EOF col-span-6 */}
|
||||
|
||||
<div className="w-full rounded-b-md text-sm shadow-2xl">
|
||||
<CodeHighlight language="wasp" source={codeString} />
|
||||
</div>{' '}
|
||||
{/* EOF code block wrapper */}
|
||||
</div>{' '}
|
||||
{/* EOF wrapper of header + code */}
|
||||
</div>{' '}
|
||||
{/* EOF col-span-6 */}
|
||||
</div>
|
||||
|
||||
|
||||
{/* 1-min video */}
|
||||
{/*
|
||||
<div className='flex justify-center mt-20'>
|
||||
@ -227,10 +236,8 @@ entity Task {=psl ... psl=} // Your Prisma data model.
|
||||
/>
|
||||
</div>
|
||||
*/}
|
||||
|
||||
</SectionContainer>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default Hero
|
||||
|
@ -9,7 +9,7 @@ const Feature = ({ title, description, url }) => (
|
||||
<div className="lg:mt-5">
|
||||
<dt>
|
||||
<h4 className="mb-4">
|
||||
<span className="text-neutral-700 bg-yellow-500/25 px-2 py-1 rounded">
|
||||
<span className="rounded bg-yellow-500/25 px-2 py-1 text-neutral-700">
|
||||
{title}
|
||||
</span>
|
||||
</h4>
|
||||
@ -28,7 +28,7 @@ const TextLink = ({ url, label }) => (
|
||||
text-neutral-600 hover:text-neutral-500
|
||||
`}
|
||||
>
|
||||
<div className="group flex gap-1 items-center">
|
||||
<div className="group flex items-center gap-1">
|
||||
<span>{label}</span>
|
||||
<div className="transition-all group-hover:ml-0.5">
|
||||
<span className="text-yellow-600">
|
||||
@ -45,7 +45,7 @@ const HowItWorks = () => {
|
||||
<SectionContainer className="lg:pb-8">
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 lg:col-span-4">
|
||||
<h2 className="text-xl lg:text-2xl text-neutral-700 mb-4">
|
||||
<h2 className="mb-4 text-xl text-neutral-700 lg:text-2xl">
|
||||
How does it work? 🧐
|
||||
</h2>
|
||||
<p className="text-neutral-700">
|
||||
|
@ -2,22 +2,20 @@ import React from 'react'
|
||||
import ReactTooltip from 'react-tooltip'
|
||||
import { Clipboard } from 'react-feather'
|
||||
|
||||
|
||||
const copyToClipboard = (text) => {
|
||||
navigator.clipboard.writeText(text)
|
||||
}
|
||||
|
||||
const InstallCmd = () => {
|
||||
|
||||
const code = 'curl -sSL https://get.wasp-lang.dev/installer.sh | sh'
|
||||
|
||||
|
||||
return (
|
||||
<div
|
||||
className='cursor-pointer text-sm text-neutral-500 border border-yellow-500/75 rounded'
|
||||
className="cursor-pointer rounded border border-yellow-500/75 text-sm text-neutral-500"
|
||||
data-tip
|
||||
data-event='click'
|
||||
data-event-off='click'
|
||||
data-delay-hide='2000'
|
||||
data-event="click"
|
||||
data-event-off="click"
|
||||
data-delay-hide="2000"
|
||||
>
|
||||
<pre
|
||||
className={`
|
||||
@ -26,17 +24,17 @@ const InstallCmd = () => {
|
||||
>
|
||||
<strong>
|
||||
<code>
|
||||
<span className='select-none'>$ </span>
|
||||
<span className="select-none">$ </span>
|
||||
{code}
|
||||
</code>
|
||||
</strong>
|
||||
<Clipboard size={18} />
|
||||
</pre>
|
||||
<ReactTooltip
|
||||
place='top'
|
||||
effect='float'
|
||||
backgroundColor='#eab307'
|
||||
textColor='white'
|
||||
place="top"
|
||||
effect="float"
|
||||
backgroundColor="#eab307"
|
||||
textColor="white"
|
||||
afterShow={() => copyToClipboard(code)}
|
||||
>
|
||||
<b>Copied to clipboard!</b>
|
||||
|
@ -2,16 +2,16 @@ import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
const SectionContainer = ({ children, className, id }) => (
|
||||
<div
|
||||
<div
|
||||
className={classNames(
|
||||
'container mx-auto px-6 py-16 sm:py-18',
|
||||
'sm:py-18 container mx-auto px-6 py-16',
|
||||
'md:py-24',
|
||||
'lg:px-16 lg:py-24 xl:px-20',
|
||||
className
|
||||
)}
|
||||
id={id}
|
||||
>
|
||||
{ children }
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React from "react";
|
||||
import classNames from "classnames";
|
||||
import { useHistory } from "@docusaurus/router";
|
||||
import { ChevronRight, X } from "react-feather";
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { useHistory } from '@docusaurus/router'
|
||||
import { ChevronRight, X } from 'react-feather'
|
||||
|
||||
import styles from "../../pages/styles.module.css";
|
||||
import styles from '../../pages/styles.module.css'
|
||||
|
||||
const Announcement = () => {
|
||||
let history = useHistory();
|
||||
let history = useHistory()
|
||||
|
||||
const handleLink = () => {
|
||||
window.open('https://magic-app-generator.wasp-lang.dev/')
|
||||
@ -17,7 +17,7 @@ const Announcement = () => {
|
||||
//window.open('https://twitter.com/WaspLang/status/1647979490180575234')
|
||||
//window.open('https://www.producthunt.com/posts/free-saas-template-gpt-stripe-auth')
|
||||
// window.open("https://hackathon.wasp-lang.dev");
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -25,9 +25,9 @@ const Announcement = () => {
|
||||
className={classNames(
|
||||
styles.gradientBackground,
|
||||
`
|
||||
cursor-pointer
|
||||
flex-row space-x-3
|
||||
overflow-hidden
|
||||
cursor-pointer flex-row
|
||||
space-x-3
|
||||
text-white
|
||||
`
|
||||
)}
|
||||
@ -39,14 +39,14 @@ const Announcement = () => {
|
||||
lg:container lg:divide-x lg:px-16 xl:px-20
|
||||
`}
|
||||
>
|
||||
<span className='item-center flex gap-2 px-3'>
|
||||
<span className="item-center flex gap-2 px-3">
|
||||
<span>Try our GPT-Powered Web App Starter!</span>
|
||||
</span>
|
||||
|
||||
<span className='hidden items-center space-x-2 px-3 lg:flex'>
|
||||
<span className="hidden items-center space-x-2 px-3 lg:flex">
|
||||
<span
|
||||
className={`
|
||||
bg-neutral-700 px-2.5 py-1 text-xs rounded-full cursor-pointer
|
||||
cursor-pointer rounded-full bg-neutral-700 px-2.5 py-1 text-xs
|
||||
hover:bg-neutral-600
|
||||
`}
|
||||
>
|
||||
@ -55,7 +55,7 @@ const Announcement = () => {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Announcement;
|
||||
export default Announcement
|
||||
|
@ -7,32 +7,34 @@ import Transition from '../../lib/Transition'
|
||||
import { GitHubIcon, DiscordIcon, TwitterIcon } from './SocialIcons'
|
||||
|
||||
const Nav = () => {
|
||||
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
const Logo = () => (
|
||||
<div className='flex flex-shrink-0 items-center'>
|
||||
<Link to='/'>
|
||||
<div className="flex flex-shrink-0 items-center">
|
||||
<Link to="/">
|
||||
<img
|
||||
src='img/lp/wasp-logo.png'
|
||||
src="img/lp/wasp-logo.png"
|
||||
width={35}
|
||||
height={35}
|
||||
alt='Wasp Logo'
|
||||
alt="Wasp Logo"
|
||||
/>
|
||||
</Link>
|
||||
<span className='ml-3 font-semibold text-lg text-neutral-700'>
|
||||
Wasp <sup className='text-base text-yellow-500'>βeta</sup>
|
||||
<span className="ml-3 text-lg font-semibold text-neutral-700">
|
||||
Wasp <sup className="text-base text-yellow-500">βeta</sup>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
const SocialIcon = ({ Icon, url }) => (
|
||||
<a href={url} target='_blank' rel='noreferrer'
|
||||
<a
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={`
|
||||
text-neutral-700
|
||||
hidden lg:flex hover:opacity-75 py-5
|
||||
hover:text-yellow-500 hover:border-yellow-500
|
||||
border-b-2 border-transparent
|
||||
hidden
|
||||
border-b-2 border-transparent py-5 text-neutral-700
|
||||
hover:border-yellow-500 hover:text-yellow-500
|
||||
hover:opacity-75 lg:flex
|
||||
`}
|
||||
>
|
||||
<Icon />
|
||||
@ -43,58 +45,62 @@ const Nav = () => {
|
||||
<>
|
||||
{/* NOTE(matija): If I put width to 100 or less, the badge gets cut off in half. */}
|
||||
<iframe
|
||||
src="https://ghbtns.com/github-btn.html?user=wasp-lang&repo=wasp&type=star&count=true"
|
||||
src="https://ghbtns.com/github-btn.html?user=wasp-lang&repo=wasp&type=star&count=true"
|
||||
frameBorder="0"
|
||||
scrolling="0"
|
||||
width="101px"
|
||||
height="20px"
|
||||
>
|
||||
</iframe>
|
||||
></iframe>
|
||||
</>
|
||||
)
|
||||
|
||||
// NOTE(matija): this one does not show the exact count, but e.g. 2k.
|
||||
const WaspGhStarsShield = () => (
|
||||
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/wasp-lang/wasp?style=social" />
|
||||
<img
|
||||
alt="GitHub Repo stars"
|
||||
src="https://img.shields.io/github/stars/wasp-lang/wasp?style=social"
|
||||
/>
|
||||
)
|
||||
|
||||
const GitHubButton = () => (
|
||||
<a href='https://github.com/wasp-lang/wasp' target='_blank' rel='noreferrer'
|
||||
<a
|
||||
href="https://github.com/wasp-lang/wasp"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={`
|
||||
px-2.5 py-1 rounded
|
||||
hover:bg-neutral-200
|
||||
transition ease-out duration-200
|
||||
hidden lg:flex items-center space-x-2 text-xs
|
||||
group
|
||||
group hidden items-center
|
||||
space-x-2
|
||||
rounded px-2.5 py-1
|
||||
text-xs transition duration-200 ease-out hover:bg-neutral-200
|
||||
lg:flex
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
flex h-3 w-3 items-center justify-center
|
||||
group-hover:h-4 group-hover:w-4
|
||||
text-neutral-700
|
||||
text-neutral-700 group-hover:h-4
|
||||
group-hover:w-4
|
||||
group-hover:text-yellow-500
|
||||
`}
|
||||
>
|
||||
<Star strokeWidth={2} />
|
||||
</div>
|
||||
<span className='truncate text-neutral-700'>Star us on GitHub</span>
|
||||
<span className="truncate text-neutral-700">Star us on GitHub</span>
|
||||
</a>
|
||||
)
|
||||
|
||||
const HamburgerButton = ({ toggleFlyOut }) => (
|
||||
<div
|
||||
className='absolute inset-y-0 left-0 px-2 flex items-center lg:hidden'
|
||||
className="absolute inset-y-0 left-0 flex items-center px-2 lg:hidden"
|
||||
onClick={() => toggleFlyOut()}
|
||||
>
|
||||
<button
|
||||
className={`
|
||||
inline-flex items-center p-2
|
||||
rounded-md hover:bg-gray-50
|
||||
focus:ring-yellow-500 focus:outline-none focus:ring-2 focus:ring-inset
|
||||
inline-flex items-center rounded-md
|
||||
p-2 hover:bg-gray-50
|
||||
focus:outline-none focus:ring-2 focus:ring-inset focus:ring-yellow-500
|
||||
`}
|
||||
>
|
||||
|
||||
<span className="sr-only">Open menu</span>
|
||||
|
||||
<svg
|
||||
@ -114,103 +120,106 @@ const Nav = () => {
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Announcement />
|
||||
<div className='sticky top-0 z-50'>
|
||||
<div className='bg-[#f5f4f0] absolute top-0 h-full w-full opacity-80'></div>
|
||||
<nav className='border-b backdrop-blur-sm'>
|
||||
<div className='
|
||||
<div className="sticky top-0 z-50">
|
||||
<div className="absolute top-0 h-full w-full bg-[#f5f4f0] opacity-80"></div>
|
||||
<nav className="border-b backdrop-blur-sm">
|
||||
<div
|
||||
className="
|
||||
relative mx-auto
|
||||
flex justify-between
|
||||
h-16
|
||||
flex h-16
|
||||
justify-between
|
||||
lg:container lg:px-16 xl:px-20
|
||||
'
|
||||
"
|
||||
>
|
||||
<HamburgerButton toggleFlyOut={() => setOpen(true)} />
|
||||
<div className='
|
||||
<div
|
||||
className="
|
||||
flex flex-1
|
||||
items-center justify-center
|
||||
sm:items-stretch
|
||||
lg:justify-between
|
||||
'
|
||||
"
|
||||
>
|
||||
<div className='flex items-center'> {/* Navbar left side */}
|
||||
<div className="flex items-center">
|
||||
{' '}
|
||||
{/* Navbar left side */}
|
||||
<Logo />
|
||||
|
||||
<div className='hidden pl-4 sm:ml-6 sm:space-x-4 lg:flex'> {/* Left items */}
|
||||
<div className="hidden pl-4 sm:ml-6 sm:space-x-4 lg:flex">
|
||||
{' '}
|
||||
{/* Left items */}
|
||||
{/* Docs */}
|
||||
<Link to='/docs'>
|
||||
<Link to="/docs">
|
||||
<span
|
||||
className={`
|
||||
py-5 px-1
|
||||
text-neutral-700
|
||||
hover:text-yellow-500 hover:border-yellow-500
|
||||
border-b-solid border-b-2 border-transparent
|
||||
text-sm font-semibold
|
||||
border-b-solid border-b-2
|
||||
border-transparent
|
||||
px-1 py-5
|
||||
text-sm font-semibold text-neutral-700
|
||||
hover:border-yellow-500 hover:text-yellow-500
|
||||
`}
|
||||
>
|
||||
Docs
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Blog */}
|
||||
<Link to='/blog'>
|
||||
<Link to="/blog">
|
||||
<span
|
||||
className={`
|
||||
py-5 px-1
|
||||
text-neutral-700
|
||||
hover:text-yellow-500 hover:border-yellow-500
|
||||
border-b-2 border-transparent
|
||||
text-sm font-semibold
|
||||
px-1
|
||||
py-5 text-sm
|
||||
font-semibold text-neutral-700
|
||||
hover:border-yellow-500 hover:text-yellow-500
|
||||
`}
|
||||
>
|
||||
Blog
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* FAQ */}
|
||||
<Link to='#faq'>
|
||||
<Link to="#faq">
|
||||
<span
|
||||
className={`
|
||||
py-5 px-1
|
||||
text-neutral-700
|
||||
hover:text-yellow-500 hover:border-yellow-500
|
||||
border-b-2 border-transparent
|
||||
text-sm font-medium
|
||||
px-1
|
||||
py-5 text-sm
|
||||
font-medium text-neutral-700
|
||||
hover:border-yellow-500 hover:text-yellow-500
|
||||
`}
|
||||
>
|
||||
FAQ
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Join newsletter */}
|
||||
<Link to='#signup'>
|
||||
<Link to="#signup">
|
||||
<span
|
||||
className={`
|
||||
py-5 px-1
|
||||
border-b-2 border-transparent
|
||||
px-1 py-5
|
||||
text-sm font-medium
|
||||
`}
|
||||
>
|
||||
<span
|
||||
className={`
|
||||
text-neutral-700
|
||||
px-2 py-1 rounded bg-yellow-500/25 hover:bg-yellow-500/10
|
||||
rounded
|
||||
bg-yellow-500/25 px-2 py-1 text-neutral-700 hover:bg-yellow-500/10
|
||||
`}
|
||||
>
|
||||
📬 Join the list
|
||||
</span>
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
</div> {/* EOF left items */}
|
||||
</div> {/* EOF left side */}
|
||||
|
||||
<div className='flex items-center gap-2 space-x-2'> {/* Navbar right side */}
|
||||
</div>{' '}
|
||||
{/* EOF left items */}
|
||||
</div>{' '}
|
||||
{/* EOF left side */}
|
||||
<div className="flex items-center gap-2 space-x-2">
|
||||
{' '}
|
||||
{/* Navbar right side */}
|
||||
{/* GH stars badge */}
|
||||
{/*
|
||||
<span className='hidden lg:inline'>
|
||||
@ -219,38 +228,34 @@ const Nav = () => {
|
||||
</Link>
|
||||
</span>
|
||||
*/}
|
||||
|
||||
<GitHubButton />
|
||||
|
||||
<Link to='/docs/quick-start'>
|
||||
<Link to="/docs/quick-start">
|
||||
<button
|
||||
className={`
|
||||
hidden lg:block text-xs
|
||||
px-2.5 py-1 rounded
|
||||
bg-yellow-500 text-white
|
||||
hover:bg-yellow-400
|
||||
transition ease-out duration-200
|
||||
hidden rounded bg-yellow-500
|
||||
px-2.5 py-1 text-xs
|
||||
text-white transition
|
||||
duration-200
|
||||
ease-out hover:bg-yellow-400 lg:block
|
||||
`}
|
||||
>
|
||||
Get Started
|
||||
</button>
|
||||
</Link>
|
||||
|
||||
<SocialIcon
|
||||
Icon={ GitHubIcon }
|
||||
url='https://github.com/wasp-lang/wasp'
|
||||
Icon={GitHubIcon}
|
||||
url="https://github.com/wasp-lang/wasp"
|
||||
/>
|
||||
|
||||
<SocialIcon
|
||||
Icon={ DiscordIcon }
|
||||
url='https://discord.gg/rzdnErX'
|
||||
Icon={DiscordIcon}
|
||||
url="https://discord.gg/rzdnErX"
|
||||
/>
|
||||
|
||||
<SocialIcon
|
||||
Icon={ TwitterIcon }
|
||||
url='https://twitter.com/WaspLang'
|
||||
Icon={TwitterIcon}
|
||||
url="https://twitter.com/WaspLang"
|
||||
/>
|
||||
</div> {/* EOF right side */}
|
||||
</div>{' '}
|
||||
{/* EOF right side */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -270,14 +275,14 @@ const Nav = () => {
|
||||
fixed -inset-y-0 z-50 h-screen w-screen transform overflow-y-scroll bg-white p-4 md:p-8
|
||||
`}
|
||||
>
|
||||
<div className='absolute right-4 top-4 items-center justify-between'>
|
||||
<div className="absolute right-4 top-4 items-center justify-between">
|
||||
<div className="-mr-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(false)}
|
||||
className={`
|
||||
text-neutral-700 inline-flex items-center justify-center rounded-md
|
||||
bg-white p-2 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset
|
||||
inline-flex items-center justify-center rounded-md bg-white
|
||||
p-2 text-neutral-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset
|
||||
`}
|
||||
>
|
||||
<span className="sr-only">Close menu</span>
|
||||
@ -300,52 +305,53 @@ const Nav = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-6 mb-12'>
|
||||
<div className="mb-12 mt-6">
|
||||
{/* Docs */}
|
||||
<div className='space-y-1 pt-2 pb-4'>
|
||||
<div className="space-y-1 pb-4 pt-2">
|
||||
<Link to="/docs">
|
||||
<span className="text-neutral-700 block pl-3 pr-4 text-base font-medium">
|
||||
<span className="block pl-3 pr-4 text-base font-medium text-neutral-700">
|
||||
Docs
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Docs */}
|
||||
<div className='space-y-1 pt-2 pb-4'>
|
||||
<div className="space-y-1 pb-4 pt-2">
|
||||
<Link to="/blog">
|
||||
<span className="text-neutral-700 block pl-3 pr-4 text-base font-medium">
|
||||
<span className="block pl-3 pr-4 text-base font-medium text-neutral-700">
|
||||
Blog
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* FAQ */}
|
||||
<div className='space-y-1 pt-2 pb-4'>
|
||||
<div className="space-y-1 pb-4 pt-2">
|
||||
<Link to="#faq" onClick={() => setOpen(false)}>
|
||||
<span className="text-neutral-700 block pl-3 pr-4 text-base font-medium">
|
||||
<span className="block pl-3 pr-4 text-base font-medium text-neutral-700">
|
||||
FAQ
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Join the list */}
|
||||
<div className='space-y-1 pt-2 pb-4'>
|
||||
<div className="space-y-1 pb-4 pt-2">
|
||||
<Link to="#signup" onClick={() => setOpen(false)}>
|
||||
<span
|
||||
className={`
|
||||
text-neutral-700 block pl-3 pr-4 text-base font-medium
|
||||
px-2 py-1 rounded bg-yellow-500/25 hover:bg-yellow-500/10
|
||||
`}>
|
||||
block rounded bg-yellow-500/25 px-2 py-1 pl-3
|
||||
pr-4 text-base font-medium text-neutral-700 hover:bg-yellow-500/10
|
||||
`}
|
||||
>
|
||||
📬 Join the list
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* GitHub */}
|
||||
<div className='space-y-1 pt-2 pb-4'>
|
||||
<div className="space-y-1 pb-4 pt-2">
|
||||
<Link to="https://github.com/wasp-lang/wasp">
|
||||
<span className='flex items-center'>
|
||||
<span className="text-neutral-700 pl-3 pr-4 text-base font-medium">
|
||||
<span className="flex items-center">
|
||||
<span className="pl-3 pr-4 text-base font-medium text-neutral-700">
|
||||
⭐️ GitHub
|
||||
</span>
|
||||
<WaspGhStarsExactCount />
|
||||
@ -354,38 +360,29 @@ const Nav = () => {
|
||||
</div>
|
||||
|
||||
{/* Discord */}
|
||||
<div className='space-y-1 pt-2 pb-4'>
|
||||
<div className="space-y-1 pb-4 pt-2">
|
||||
<Link to="https://discord.gg/rzdnErX">
|
||||
<span className="text-neutral-700 block pl-3 pr-4 text-base font-medium">
|
||||
<span className="block pl-3 pr-4 text-base font-medium text-neutral-700">
|
||||
👾 Discord
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Twitter */}
|
||||
<div className='space-y-1 pt-2 pb-4'>
|
||||
<div className="space-y-1 pb-4 pt-2">
|
||||
<Link to="https://twitter.com/WaspLang">
|
||||
<span className="text-neutral-700 block pl-3 pr-4 text-base font-medium">
|
||||
<span className="block pl-3 pr-4 text-base font-medium text-neutral-700">
|
||||
🐦 Twitter
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default Nav
|
||||
|
@ -5,41 +5,33 @@ import SectionContainer from './Layouts/SectionContainer'
|
||||
|
||||
const Newsletter = () => {
|
||||
return (
|
||||
<SectionContainer id='signup'>
|
||||
<div className='grid grid-cols-12'>
|
||||
<div className='col-span-12'>
|
||||
|
||||
<SectionContainer id="signup">
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12">
|
||||
<div
|
||||
className={`
|
||||
px-6 py-6 bg-yellow-500/25 rounded-lg
|
||||
rounded-lg bg-yellow-500/25 px-6 py-6
|
||||
md:p-12 lg:p-16
|
||||
xl:flex xl:items-center
|
||||
`}
|
||||
>
|
||||
<div className='xl:w-0 xl:flex-1'>
|
||||
<h2 className='text-2xl font-extrabold text-neutral-700'>
|
||||
<div className="xl:w-0 xl:flex-1">
|
||||
<h2 className="text-2xl font-extrabold text-neutral-700">
|
||||
Stay up to date 📬
|
||||
</h2>
|
||||
<p className='mt-3 text-lg text-neutral-500 leading-6'>
|
||||
<p className="mt-3 text-lg leading-6 text-neutral-500">
|
||||
Be the first to know when we ship new features and updates!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className='mt-8 sm:w-full sm:max-w-md xl:mt-0 xl:ml-8'>
|
||||
<SubscribeForm
|
||||
inputBgColor='bg-[#f5f5f5]'
|
||||
/>
|
||||
|
||||
<div className="mt-8 sm:w-full sm:max-w-md xl:ml-8 xl:mt-0">
|
||||
<SubscribeForm inputBgColor="bg-[#f5f5f5]" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default Newsletter
|
||||
|
||||
|
@ -1,22 +1,22 @@
|
||||
import * as React from "react";
|
||||
import * as React from 'react'
|
||||
|
||||
const color = "#f59e0b";
|
||||
const color = '#f59e0b'
|
||||
|
||||
export function Required() {
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
border: `2px solid ${color}`,
|
||||
display: "inline-block",
|
||||
padding: "0.2em 0.4em",
|
||||
display: 'inline-block',
|
||||
padding: '0.2em 0.4em',
|
||||
color: color,
|
||||
borderRadius: "0.4em",
|
||||
fontSize: "0.8em",
|
||||
lineHeight: "1",
|
||||
fontWeight: "bold",
|
||||
borderRadius: '0.4em',
|
||||
fontSize: '0.8em',
|
||||
lineHeight: '1',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
>
|
||||
required
|
||||
</span>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -28,12 +28,12 @@ const GhIssueLink = ({ url, label }) => (
|
||||
<Link to={url}>
|
||||
<span
|
||||
className={`
|
||||
cursor-pointer text-xs
|
||||
bg-neutral-600 text-white
|
||||
px-2.5 py-1 rounded-full
|
||||
cursor-pointer rounded-full
|
||||
bg-neutral-600 px-2.5
|
||||
py-1 text-xs text-white
|
||||
`}
|
||||
>
|
||||
<div className="group inline-flex gap-1 items-center">
|
||||
<div className="group inline-flex items-center gap-1">
|
||||
<span>{label}</span>
|
||||
<div className="transition-all group-hover:ml-0.5">
|
||||
<span className="text-yellow-400">
|
||||
@ -49,7 +49,7 @@ const Section = ({ features }) => (
|
||||
<ul className="space-y-6">
|
||||
{features.map((f) => (
|
||||
<li className="grid grid-cols-12">
|
||||
<div className="flex items-center col-start-3 col-span-8">
|
||||
<div className="col-span-8 col-start-3 flex items-center">
|
||||
<span>
|
||||
<span className="text-neutral-600">{f[0]}</span>
|
||||
{f[1] && (
|
||||
@ -69,10 +69,10 @@ const Section = ({ features }) => (
|
||||
)
|
||||
|
||||
const Roadmap = () => (
|
||||
<SectionContainer className="space-y-16 lg:py-18" id="roadmap">
|
||||
<SectionContainer className="lg:py-18 space-y-16" id="roadmap">
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 text-center">
|
||||
<h2 className="text-xl lg:text-2xl text-neutral-700 mb-4">
|
||||
<h2 className="mb-4 text-xl text-neutral-700 lg:text-2xl">
|
||||
🚧 Roadmap 🚧
|
||||
</h2>
|
||||
<p className="text-neutral-500">
|
||||
@ -81,14 +81,14 @@ const Roadmap = () => (
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 md:gap-16">
|
||||
<div className="grid grid-cols-1 md:gap-16 lg:grid-cols-2">
|
||||
<div
|
||||
className={`
|
||||
bg-yellow-500/5 border border-yellow-500/25
|
||||
p-5 rounded-lg
|
||||
rounded-lg border border-yellow-500/25
|
||||
bg-yellow-500/5 p-5
|
||||
`}
|
||||
>
|
||||
<div className="font-bold text-center text-neutral-700 mb-6">
|
||||
<div className="mb-6 text-center font-bold text-neutral-700">
|
||||
Near-term improvements and features
|
||||
</div>
|
||||
<Section
|
||||
@ -106,12 +106,12 @@ const Roadmap = () => (
|
||||
|
||||
<div
|
||||
className={`
|
||||
bg-yellow-500/20 border border-yellow-500/25
|
||||
p-5 rounded-lg
|
||||
mt-6 lg:mt-0
|
||||
mt-6 rounded-lg border
|
||||
border-yellow-500/25 bg-yellow-500/20
|
||||
p-5 lg:mt-0
|
||||
`}
|
||||
>
|
||||
<div className="font-bold text-center text-neutral-700 mb-6">
|
||||
<div className="mb-6 text-center font-bold text-neutral-700">
|
||||
Advanced Features
|
||||
</div>
|
||||
<Section
|
||||
|
@ -4,10 +4,12 @@ import SectionContainer from './Layouts/SectionContainer'
|
||||
|
||||
const Tag = ({ text, className }) => (
|
||||
<span
|
||||
className={classNames(`
|
||||
text-sm border rounded-md px-2.5 py-0.5
|
||||
className={classNames(
|
||||
`
|
||||
rounded-md border px-2.5 py-0.5 text-sm
|
||||
|
||||
`, className
|
||||
`,
|
||||
className
|
||||
)}
|
||||
>
|
||||
{text}
|
||||
@ -17,45 +19,37 @@ const Tag = ({ text, className }) => (
|
||||
const ShowcaseItem = ({ url, thumb, title, description, children }) => (
|
||||
<div>
|
||||
<a href={url}>
|
||||
<div className='group inline-block min-w-full'>
|
||||
<div className='flex flex-col space-y-3 pb-8 md:pb-0'>
|
||||
|
||||
<div className="group inline-block min-w-full">
|
||||
<div className="flex flex-col space-y-3 pb-8 md:pb-0">
|
||||
<div
|
||||
className={`
|
||||
border-neutral-300 relative mb-4 h-60 w-full overflow-auto
|
||||
rounded-lg border shadow-lg overflow-y-hidden
|
||||
relative mb-4 h-60 w-full overflow-auto overflow-y-hidden
|
||||
rounded-lg border border-neutral-300 shadow-lg
|
||||
`}
|
||||
>
|
||||
<img
|
||||
src={thumb}
|
||||
className='object-cover'
|
||||
/>
|
||||
<img src={thumb} className="object-cover" />
|
||||
</div>
|
||||
|
||||
<h3 className='text-neutral-700 text-xl'>{title}</h3>
|
||||
<h3 className="text-xl text-neutral-700">{title}</h3>
|
||||
|
||||
<div className='flex space-x-2'>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
<p className='text-neutral-500 text-base'>{description}</p>
|
||||
<div className="flex space-x-2">{children}</div>
|
||||
|
||||
<p className="text-base text-neutral-500">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
)
|
||||
|
||||
const ShowcaseGallery = () => {
|
||||
return (
|
||||
<SectionContainer className='space-y-16' id='showcases'>
|
||||
<div className='grid grid-cols-12'>
|
||||
<div className='col-span-12 text-center'>
|
||||
<h2 className='text-xl lg:text-2xl text-neutral-700 mb-4'>
|
||||
<SectionContainer className="space-y-16" id="showcases">
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 text-center">
|
||||
<h2 className="mb-4 text-xl text-neutral-700 lg:text-2xl">
|
||||
🏆 Showcase Gallery 🏆
|
||||
</h2>
|
||||
<p className='text-neutral-500'>
|
||||
<p className="text-neutral-500">
|
||||
See what others are building with Wasp.
|
||||
</p>
|
||||
</div>
|
||||
@ -68,37 +62,49 @@ const ShowcaseGallery = () => {
|
||||
`}
|
||||
>
|
||||
<ShowcaseItem
|
||||
url='/blog/2022/10/28/farnance-hackathon-winner'
|
||||
thumb='img/lp/showcase/farnance-dashboard.png'
|
||||
title='Farnance: SaaS marketplace for farmers'
|
||||
url="/blog/2022/10/28/farnance-hackathon-winner"
|
||||
thumb="img/lp/showcase/farnance-dashboard.png"
|
||||
title="Farnance: SaaS marketplace for farmers"
|
||||
description="See how Julian won HackLBS 2021 among 250 participants and why Wasp was instrumental for the team's victory."
|
||||
>
|
||||
<Tag text='hackathon' className='text-yellow-600 border-yellow-600 bg-yellow-50' />
|
||||
<Tag text='material-ui' className='text-blue-500 border-blue-500 bg-slate-50' />
|
||||
<Tag
|
||||
text="hackathon"
|
||||
className="border-yellow-600 bg-yellow-50 text-yellow-600"
|
||||
/>
|
||||
<Tag
|
||||
text="material-ui"
|
||||
className="border-blue-500 bg-slate-50 text-blue-500"
|
||||
/>
|
||||
</ShowcaseItem>
|
||||
|
||||
<ShowcaseItem
|
||||
url='/blog/2022/11/26/michael-curry-usecase'
|
||||
thumb='img/lp/showcase/grabbit-hero.png'
|
||||
title='Grabbit: Easily manage dev environments'
|
||||
description='See how Michael built and deployed an internal tool for managing dev resources at StudentBeans.'
|
||||
url="/blog/2022/11/26/michael-curry-usecase"
|
||||
thumb="img/lp/showcase/grabbit-hero.png"
|
||||
title="Grabbit: Easily manage dev environments"
|
||||
description="See how Michael built and deployed an internal tool for managing dev resources at StudentBeans."
|
||||
>
|
||||
<Tag text='internal-tools' className='text-green-600 border-green-600 bg-green-50' />
|
||||
<Tag
|
||||
text="internal-tools"
|
||||
className="border-green-600 bg-green-50 text-green-600"
|
||||
/>
|
||||
</ShowcaseItem>
|
||||
|
||||
<ShowcaseItem
|
||||
url='/blog/2022/11/26/erlis-amicus-usecase'
|
||||
thumb='img/lp/showcase/amicus-landing.png'
|
||||
title='Amicus: Task and workflow management for legal teams'
|
||||
description='See how Erlis rolled out fully-fledged SaaS as a team of one in record time and got first paying customers.'
|
||||
url="/blog/2022/11/26/erlis-amicus-usecase"
|
||||
thumb="img/lp/showcase/amicus-landing.png"
|
||||
title="Amicus: Task and workflow management for legal teams"
|
||||
description="See how Erlis rolled out fully-fledged SaaS as a team of one in record time and got first paying customers."
|
||||
>
|
||||
<Tag text='startup' className='text-fuchsia-600 border-fuchsia-600 bg-fuchsia-50' />
|
||||
<Tag text='material-ui' className='text-blue-500 border-blue-500 bg-slate-50' />
|
||||
<Tag
|
||||
text="startup"
|
||||
className="border-fuchsia-600 bg-fuchsia-50 text-fuchsia-600"
|
||||
/>
|
||||
<Tag
|
||||
text="material-ui"
|
||||
className="border-blue-500 bg-slate-50 text-blue-500"
|
||||
/>
|
||||
</ShowcaseItem>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import React, { useState } from 'react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
const createNewEmailSubscriberApiEndpoint = "https://app.loops.so/api/newsletter-form/clg0zndc9000ajn0f8a1bhgmu"
|
||||
const createNewEmailSubscriberApiEndpoint =
|
||||
'https://app.loops.so/api/newsletter-form/clg0zndc9000ajn0f8a1bhgmu'
|
||||
|
||||
const SubscribeForm = ({ className, inputBgColor }) => {
|
||||
const [email, setEmail] = useState('')
|
||||
@ -13,14 +14,13 @@ const SubscribeForm = ({ className, inputBgColor }) => {
|
||||
|
||||
try {
|
||||
const res = await fetch(createNewEmailSubscriberApiEndpoint, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: 'userGroup=&email=' + email,
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
})
|
||||
setMessage('Thank you for subscribing! 🙏')
|
||||
|
||||
} catch (error) {
|
||||
setMessage('🛑 Oops! Something went wrong. Please try again.')
|
||||
}
|
||||
@ -28,9 +28,9 @@ const SubscribeForm = ({ className, inputBgColor }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{ message ?
|
||||
<p className='text-lg text-neutral-500'>{message}</p>
|
||||
:
|
||||
{message ? (
|
||||
<p className="text-lg text-neutral-500">{message}</p>
|
||||
) : (
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className={classNames('sm:flex', className)}
|
||||
@ -40,36 +40,39 @@ const SubscribeForm = ({ className, inputBgColor }) => {
|
||||
type="email"
|
||||
name="email"
|
||||
value={email}
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
id="email-address"
|
||||
required autoComplete='email'
|
||||
placeholder='you@awesomedev.com'
|
||||
className={`
|
||||
text-sm w-full
|
||||
appearance-none
|
||||
placeholder:text-neutral-400
|
||||
border border-yellow-500
|
||||
px-4 py-2 rounded-md
|
||||
required
|
||||
autoComplete="email"
|
||||
placeholder="you@awesomedev.com"
|
||||
className={
|
||||
`
|
||||
w-full appearance-none
|
||||
rounded-md
|
||||
border
|
||||
border-yellow-500 px-4
|
||||
py-2 text-sm placeholder:text-neutral-400
|
||||
focus:outline-none focus:ring-2 focus:ring-yellow-400
|
||||
` + ` ${inputBgColor}`}
|
||||
` + ` ${inputBgColor}`
|
||||
}
|
||||
/>
|
||||
<div className='rounded-md mt-3 sm:mt-0 sm:ml-3'>
|
||||
<div className="mt-3 rounded-md sm:ml-3 sm:mt-0">
|
||||
<button
|
||||
type='submit'
|
||||
type="submit"
|
||||
className={`
|
||||
w-full
|
||||
text-sm border border-transparent rounded-md
|
||||
bg-yellow-500 text-white
|
||||
rounded-md border border-transparent bg-yellow-500
|
||||
px-4 py-2
|
||||
hover:bg-yellow-400
|
||||
transition ease-out duration-200
|
||||
text-sm text-white
|
||||
transition
|
||||
duration-200 ease-out hover:bg-yellow-400
|
||||
`}
|
||||
>
|
||||
Subscribe
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Link from '@docusaurus/Link'
|
||||
import classNames from 'classnames'
|
||||
import create from "@kodingdotninja/use-tailwind-breakpoint";
|
||||
import create from '@kodingdotninja/use-tailwind-breakpoint'
|
||||
|
||||
import resolveConfig from 'tailwindcss/resolveConfig'
|
||||
import tailwindConfig from '../../tailwind.config.js'
|
||||
@ -18,28 +18,28 @@ const PH = 'ph'
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
text: "I spent the one weekend building with Wasp and it was amazing, a real pleasure. I normally develop in Vue.js, but in a weekend I had time to learn Wasp, React and finish a full-stack app (only missing styling). This would have been impossible before.\n\nSo glad to see Wasp in Beta! 🍻",
|
||||
text: 'I spent the one weekend building with Wasp and it was amazing, a real pleasure. I normally develop in Vue.js, but in a weekend I had time to learn Wasp, React and finish a full-stack app (only missing styling). This would have been impossible before.\n\nSo glad to see Wasp in Beta! 🍻',
|
||||
url: 'https://www.producthunt.com/posts/wasp-lang-beta?comment=2048094',
|
||||
name: 'Joan Reyero',
|
||||
handle: '@joanreyero',
|
||||
img: 'img/lp/tm/reyero.jpg',
|
||||
source: PH
|
||||
source: PH,
|
||||
},
|
||||
{
|
||||
text: "The simplification of the main.wasp file is 👍. And it feels like a very light weight version of a few larger frameworks.",
|
||||
text: 'The simplification of the main.wasp file is 👍. And it feels like a very light weight version of a few larger frameworks.',
|
||||
url: 'https://twitter.com/tskaggs/status/1602513968207101954',
|
||||
name: 'Tim ✌️',
|
||||
handle: '@tskaggs',
|
||||
img: 'img/lp/tm/tskaggs.png',
|
||||
source: TWITTER
|
||||
source: TWITTER,
|
||||
},
|
||||
{
|
||||
text: "@WaspLang has been in the back of my mind for months now. It left an impression, and I’m really not easy to impress. That’s gotta mean something… #programming #webdevelopment #FullStack",
|
||||
text: '@WaspLang has been in the back of my mind for months now. It left an impression, and I’m really not easy to impress. That’s gotta mean something… #programming #webdevelopment #FullStack',
|
||||
url: 'https://twitter.com/AttilaTheDev/status/1583530646047117317',
|
||||
name: 'Attila Vago',
|
||||
handle: '@AttilaTheDev',
|
||||
img: 'img/lp/tm/attila.jpg',
|
||||
source: TWITTER
|
||||
source: TWITTER,
|
||||
},
|
||||
{
|
||||
text: "If it weren't for Wasp, my app Amicus would probably have never been finished. I estimate it saved me 100+ hours from the start and I'm still amazed that I did all this work as a team-of-one. Being able to quickly change existing features and add the new ones is the biggest advantage of Wasp for me. Wasp is my favorite producthunt find!",
|
||||
@ -47,7 +47,7 @@ const testimonials = [
|
||||
name: 'Erlis Kllogjri',
|
||||
handle: '@erlis_kllogjri',
|
||||
img: 'img/lp/tm/erlis.jpg',
|
||||
source: PH
|
||||
source: PH,
|
||||
},
|
||||
{
|
||||
text: "When I first learned about Wasp on HN I was really excited about its DSL approach. It was amazing how fast I could get things running with Wasp - I had the first version within an hour! The language is also fairly simple and straightforward and plays well with React & Node.js + it removes a ton of boilerplate.\n\nI've used Wasp for a lot of personal projects and for some small utility tools at various workplaces. I'm looking forward to what Wasp will bring and mean not only for rapid prototyping but also for removing the friction of getting something going in the first instance, it'll save a lot of people a lot of time!",
|
||||
@ -55,83 +55,77 @@ const testimonials = [
|
||||
name: 'Michael Curry',
|
||||
handle: '@michael_curry1',
|
||||
img: 'img/lp/tm/cursorial.jpg',
|
||||
source: PH
|
||||
source: PH,
|
||||
},
|
||||
{
|
||||
text: "I used Wasp to win a hackathon this year - it was such a pleasure to use! I’ve done plenty of hackathons before where I’ve built small SaaS apps, and there’s just so much time wasted setting up common utilities - stuff like user management, databases, routing, etc. Wasp handled all that for me and let me build out our web app in record time.\n\nAlso, deploying the wasp app was incredibly easy - I didn’t have time to stand up full infrastructure in the 2 day hackathon and don’t have an infra/devops background, but I had something running on Netlify within an hour. Other projects at the hackathon struggled to do this, and putting access in the hands of the judges certainly helped get us 1st place.\n\n@matijash @martin_sosic keep up the great work.",
|
||||
text: 'I used Wasp to win a hackathon this year - it was such a pleasure to use! I’ve done plenty of hackathons before where I’ve built small SaaS apps, and there’s just so much time wasted setting up common utilities - stuff like user management, databases, routing, etc. Wasp handled all that for me and let me build out our web app in record time.\n\nAlso, deploying the wasp app was incredibly easy - I didn’t have time to stand up full infrastructure in the 2 day hackathon and don’t have an infra/devops background, but I had something running on Netlify within an hour. Other projects at the hackathon struggled to do this, and putting access in the hands of the judges certainly helped get us 1st place.\n\n@matijash @martin_sosic keep up the great work.',
|
||||
url: 'https://www.producthunt.com/posts/wasp-lang-beta?comment=2048039',
|
||||
name: 'Julian LaNeve',
|
||||
handle: '@julian_laneve',
|
||||
img: 'img/lp/tm/jlaneve.jpg',
|
||||
source: PH
|
||||
source: PH,
|
||||
},
|
||||
{
|
||||
text: "I was a bit reluctant to contribute at first due to the complexity project, but I was really encouraged when I saw the HF issue list, documentation for developers and the activity on Discord; all of the great feedback from the maintainers made my experience even better!",
|
||||
text: 'I was a bit reluctant to contribute at first due to the complexity project, but I was really encouraged when I saw the HF issue list, documentation for developers and the activity on Discord; all of the great feedback from the maintainers made my experience even better!',
|
||||
url: 'https://twitter.com/NeoLight1010/status/1595032349552566277',
|
||||
name: 'NeoLight1010',
|
||||
handle: '@NeoLight1010',
|
||||
img: 'img/lp/tm/neolight.jpg',
|
||||
source: TWITTER
|
||||
source: TWITTER,
|
||||
},
|
||||
{
|
||||
text: "Yes, @WaspLang is amazing and anyone who wants to bootstrap a full stack React app should try it! 😍",
|
||||
text: 'Yes, @WaspLang is amazing and anyone who wants to bootstrap a full stack React app should try it! 😍',
|
||||
url: 'https://twitter.com/panphora/status/1547980602334294020',
|
||||
name: 'David Miranda',
|
||||
handle: '@panphora',
|
||||
img: 'img/lp/tm/panphora.jpg',
|
||||
source: TWITTER
|
||||
source: TWITTER,
|
||||
},
|
||||
{
|
||||
text: "Got my first @WaspLang PR merged. A big shoutout to the maintainers for leaving such helpful comments on my Haskell code!",
|
||||
text: 'Got my first @WaspLang PR merged. A big shoutout to the maintainers for leaving such helpful comments on my Haskell code!',
|
||||
url: 'https://twitter.com/infiniteverma/status/1582027815570264065',
|
||||
name: 'Anant Verma',
|
||||
handle: '@infiniteverma',
|
||||
img: 'img/lp/tm/infiniteverma.jpg',
|
||||
source: TWITTER
|
||||
source: TWITTER,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
const TestimonialCard = ({ url, text, name, handle, img, source }) => (
|
||||
<div className=''>
|
||||
<div className="">
|
||||
<Link to={url}>
|
||||
<div className='bg-yellow-500/5 border border-yellow-500/25 rounded-md p-6 shadow-sm drop-shadow-sm'>
|
||||
<div className="rounded-md border border-yellow-500/25 bg-yellow-500/5 p-6 shadow-sm drop-shadow-sm">
|
||||
{/* Header */}
|
||||
<div className='flex'>
|
||||
<img
|
||||
className='rounded-full'
|
||||
src={img}
|
||||
width={45}
|
||||
height={45}
|
||||
/>
|
||||
<div className="flex">
|
||||
<img className="rounded-full" src={img} width={45} height={45} />
|
||||
{/* Header right side */}
|
||||
<div className='pl-3 w-full flex justify-between'>
|
||||
<div className=''> {/* Name and handle */}
|
||||
<h6 className='font-semibold text-md text-neutral-700'>{name}</h6>
|
||||
<p className='text-sm text-neutral-500'>{handle}</p>
|
||||
<div className="flex w-full justify-between pl-3">
|
||||
<div className="">
|
||||
{' '}
|
||||
{/* Name and handle */}
|
||||
<h6 className="text-md font-semibold text-neutral-700">{name}</h6>
|
||||
<p className="text-sm text-neutral-500">{handle}</p>
|
||||
</div>
|
||||
|
||||
<div> {/* Twitter or PH icon */}
|
||||
{source === TWITTER &&
|
||||
<div>
|
||||
{' '}
|
||||
{/* Twitter or PH icon */}
|
||||
{source === TWITTER && (
|
||||
<img className="h-5 w-5" src="img/lp/twitter-logo.png" />
|
||||
)}
|
||||
{source === PH && (
|
||||
<img
|
||||
className='w-5 h-5'
|
||||
src='img/lp/twitter-logo.png'
|
||||
className="h-5 w-5 rounded-full"
|
||||
src="img/lp/ph-logo.png"
|
||||
/>
|
||||
}
|
||||
{source === PH &&
|
||||
<img
|
||||
className='w-5 h-5 rounded-full'
|
||||
src='img/lp/ph-logo.png'
|
||||
/>
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</div> {/* EOF Header right side */}
|
||||
</div>{' '}
|
||||
{/* EOF Header right side */}
|
||||
</div>
|
||||
|
||||
{/* Text */}
|
||||
<div className='mt-2 text-neutral-700 whitespace-pre-wrap'>
|
||||
{text}
|
||||
</div>
|
||||
<div className="mt-2 whitespace-pre-wrap text-neutral-700">{text}</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
@ -144,7 +138,6 @@ const testimonialLayoutConfig = {
|
||||
}
|
||||
|
||||
const Testimonials = () => {
|
||||
|
||||
const [loadMoreCount, setLoadMoreCount] = useState(0)
|
||||
|
||||
const isSm = useBreakpoint('sm')
|
||||
@ -152,75 +145,79 @@ const Testimonials = () => {
|
||||
const isLg = useBreakpoint('lg')
|
||||
|
||||
useEffect(() => {
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
}, []);
|
||||
window.dispatchEvent(new Event('resize'))
|
||||
}, [])
|
||||
|
||||
let layoutConfig = testimonialLayoutConfig.mobile
|
||||
if (isLg) { layoutConfig = testimonialLayoutConfig.lg }
|
||||
else if (isMd) { layoutConfig = testimonialLayoutConfig.md }
|
||||
if (isLg) {
|
||||
layoutConfig = testimonialLayoutConfig.lg
|
||||
} else if (isMd) {
|
||||
layoutConfig = testimonialLayoutConfig.md
|
||||
}
|
||||
|
||||
const numOfItemsToShow = Math.min(
|
||||
layoutConfig.initialNumOfItemsToShow + loadMoreCount * layoutConfig.loadMoreStep,
|
||||
layoutConfig.initialNumOfItemsToShow +
|
||||
loadMoreCount * layoutConfig.loadMoreStep,
|
||||
testimonials.length
|
||||
)
|
||||
|
||||
// Data structure for rendering - assign each testimonial into the appropriate column.
|
||||
const cols = Array.from({length: layoutConfig.colsNum}, e => [])
|
||||
const cols = Array.from({ length: layoutConfig.colsNum }, (e) => [])
|
||||
for (let itemIdx = 0; itemIdx < numOfItemsToShow; itemIdx++) {
|
||||
const targetCol = itemIdx % layoutConfig.colsNum
|
||||
cols[targetCol].push(testimonials[itemIdx])
|
||||
}
|
||||
|
||||
return (
|
||||
<SectionContainer className='space-y-16' id='testimonials'>
|
||||
<div className='grid grid-cols-12'>
|
||||
<div className='col-span-12 text-center'>
|
||||
<h2 className='text-xl lg:text-2xl text-neutral-700 mb-4'>
|
||||
<SectionContainer className="space-y-16" id="testimonials">
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 text-center">
|
||||
<h2 className="mb-4 text-xl text-neutral-700 lg:text-2xl">
|
||||
You're in a good crowd
|
||||
</h2>
|
||||
<p className='text-neutral-500'>
|
||||
<p className="text-neutral-500">
|
||||
Here's what folks using Wasp say about it. Join
|
||||
<a
|
||||
href='https://discord.gg/rzdnErX'
|
||||
className='underline decoration-2 decoration-yellow-500 font-medium'
|
||||
<a
|
||||
href="https://discord.gg/rzdnErX"
|
||||
className="font-medium underline decoration-yellow-500 decoration-2"
|
||||
>
|
||||
our Discord
|
||||
</a> for more!
|
||||
</a>{' '}
|
||||
for more!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex space-x-4'>
|
||||
<div className="flex space-x-4">
|
||||
{cols.map((col, colIdx) => (
|
||||
<div key={colIdx} className={`flex flex-col space-y-4 w-1/${layoutConfig.colsNum}`}>
|
||||
<div
|
||||
key={colIdx}
|
||||
className={`flex flex-col space-y-4 w-1/${layoutConfig.colsNum}`}
|
||||
>
|
||||
{col.map((item, itemIdx) => (
|
||||
<TestimonialCard
|
||||
key={itemIdx}
|
||||
{...item}
|
||||
/>
|
||||
<TestimonialCard key={itemIdx} {...item} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{numOfItemsToShow < testimonials.length &&
|
||||
<div className='flex justify-center'>
|
||||
{numOfItemsToShow < testimonials.length && (
|
||||
<div className="flex justify-center">
|
||||
<button
|
||||
className={`
|
||||
inline-flex items-center space-x-2
|
||||
px-3 py-2 rounded
|
||||
bg-yellow-500 text-white text-sm leading-4
|
||||
border border-yellow-500 hover:border-yellow-400
|
||||
hover:bg-yellow-400
|
||||
transition ease-out duration-200
|
||||
rounded border border-yellow-500
|
||||
bg-yellow-500 px-3 py-2 text-sm
|
||||
leading-4 text-white transition
|
||||
duration-200
|
||||
ease-out hover:border-yellow-400 hover:bg-yellow-400
|
||||
`}
|
||||
onClick={() => setLoadMoreCount(loadMoreCount + 1)}
|
||||
>
|
||||
🐝 Load more
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
)}
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ export function ShowForTs({ children }: Props) {
|
||||
return jsTs === 'ts' && <MDXContent>{children}</MDXContent>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Only renders this block if user has selected JS in the codeblocks
|
||||
* @Note leave a blank space after opening the tag e.g.
|
||||
|
@ -6,41 +6,37 @@ import SectionContainer from './Layouts/SectionContainer'
|
||||
|
||||
const VideoAndTutorial = () => {
|
||||
return (
|
||||
<SectionContainer id='demo'>
|
||||
|
||||
<SectionContainer id="demo">
|
||||
{/* 1-min video - a hacky way to hide controls */}
|
||||
<div className='flex justify-center md:mt-10'>
|
||||
<div className='flex flex-col items-center w-full gap-6'>
|
||||
|
||||
<div className='w-full lg:w-2/3 xl:w-3/5 overflow-hidden rounded-md shadow-lg'>
|
||||
<div className='relative w-[200%] -left-[50%] pb-[56.25%] pt-25px'>
|
||||
<div className="flex justify-center md:mt-10">
|
||||
<div className="flex w-full flex-col items-center gap-6">
|
||||
<div className="w-full overflow-hidden rounded-md shadow-lg lg:w-2/3 xl:w-3/5">
|
||||
<div className="pt-25px relative -left-[50%] w-[200%] pb-[56.25%]">
|
||||
<iframe
|
||||
src='https://www.youtube-nocookie.com/embed/YaaTJOhx68I?playlist=YaaTJOhx68I&autoplay=0&loop=1&controls=0&showinfo=1&modestbranding=0&rel=0&disablekb=0&mute=1'
|
||||
title='Demo video showcasing Wasp'
|
||||
className='absolute h-full w-full top-0 left-0 rounded-md'
|
||||
frameborder='0'
|
||||
allow='accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; allowfullscreen;'
|
||||
src="https://www.youtube-nocookie.com/embed/YaaTJOhx68I?playlist=YaaTJOhx68I&autoplay=0&loop=1&controls=0&showinfo=1&modestbranding=0&rel=0&disablekb=0&mute=1"
|
||||
title="Demo video showcasing Wasp"
|
||||
className="absolute left-0 top-0 h-full w-full rounded-md"
|
||||
frameborder="0"
|
||||
allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; allowfullscreen;"
|
||||
allowfullscreen
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Link to='/docs/tutorial/create'>
|
||||
<Link to="/docs/tutorial/create">
|
||||
<div
|
||||
className={`
|
||||
text-neutral-500 text-md
|
||||
text-md text-neutral-500
|
||||
hover:text-neutral-400
|
||||
`}
|
||||
>
|
||||
<span className='underline decoration-neutral-500'>Want to jump in and try it yourself? Take our tutorial!</span>
|
||||
<span className="underline decoration-neutral-500">
|
||||
Want to jump in and try it yourself? Take our tutorial!
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Prism from "prismjs";
|
||||
import addWaspLangauge from "../prism/wasp";
|
||||
import addPrismaLanguage from "../prism/prisma";
|
||||
import Prism from 'prismjs'
|
||||
import addWaspLangauge from '../prism/wasp'
|
||||
import addPrismaLanguage from '../prism/prisma'
|
||||
|
||||
addPrismaLanguage(Prism);
|
||||
addWaspLangauge(Prism);
|
||||
addPrismaLanguage(Prism)
|
||||
addWaspLangauge(Prism)
|
||||
|
@ -5,7 +5,7 @@
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap');
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@ -90,7 +90,7 @@
|
||||
--sidebar-category-spacing: 2em;
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
:root[data-theme='dark'] {
|
||||
--custom-background-color-diff: #2a2a2a;
|
||||
|
||||
/* Blog */
|
||||
@ -106,11 +106,13 @@
|
||||
/******** DOCS SIDEBAR **********/
|
||||
|
||||
/* remove background from sidebar items (except for active) */
|
||||
.menu__link:not(.menu__link--active), .menu__list-item-collapsible {
|
||||
.menu__link:not(.menu__link--active),
|
||||
.menu__list-item-collapsible {
|
||||
background: initial !important;
|
||||
}
|
||||
/* less opaque on hover/focus */
|
||||
.menu__link:hover:not(.menu__link--active):not(.menu__link--sublist), .menu__link:focus:not(.menu__link--active):not(.menu__link--sublist) {
|
||||
.menu__link:hover:not(.menu__link--active):not(.menu__link--sublist),
|
||||
.menu__link:focus:not(.menu__link--active):not(.menu__link--sublist) {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
@ -123,7 +125,9 @@
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.theme-doc-sidebar-item-category-level-1 > .menu__list-item-collapsible > .menu__link {
|
||||
.theme-doc-sidebar-item-category-level-1
|
||||
> .menu__list-item-collapsible
|
||||
> .menu__link {
|
||||
color: var(--sidebar-category-color);
|
||||
font-weight: bold;
|
||||
font-size: var(--ifm-h6-font-size);
|
||||
|
@ -3,11 +3,11 @@
|
||||
* Inspired by Github syntax coloring
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'] {
|
||||
color: #393a34;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
"Liberation Mono", "Courier New", monospace;
|
||||
'Liberation Mono', 'Courier New', monospace;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
@ -26,26 +26,26 @@ pre[class*="language-"] {
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre > code[class*="language-"] {
|
||||
pre > code[class*='language-'] {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
pre[class*='language-']::-moz-selection,
|
||||
pre[class*='language-'] ::-moz-selection,
|
||||
code[class*='language-']::-moz-selection,
|
||||
code[class*='language-'] ::-moz-selection {
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
pre[class*='language-']::selection,
|
||||
pre[class*='language-'] ::selection,
|
||||
code[class*='language-']::selection,
|
||||
code[class*='language-'] ::selection {
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
pre[class*='language-'] {
|
||||
/* padding: 1em; */
|
||||
/* margin: 0.5em 0; */
|
||||
overflow: auto;
|
||||
@ -54,7 +54,7 @@ pre[class*="language-"] {
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
:not(pre) > code[class*='language-'] {
|
||||
padding: 0.2em;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
html {
|
||||
font-family: Inter, sans-serif;
|
||||
}
|
||||
@ -34,7 +33,6 @@ body {
|
||||
linear-gradient(90deg,#B71 2%,#fb1 0,#fb1 98%,#B71 0%)0 0 #fb1;
|
||||
background-size: 40px 60px;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
div.twLandingPage {
|
||||
|
@ -21,43 +21,52 @@ import styles from './styles.module.css'
|
||||
import './index.css'
|
||||
import './preflight.css'
|
||||
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
|
||||
|
||||
const Background = () => {
|
||||
return (
|
||||
<div className='absolute top-0 left-0 w-full h-full overflow-hidden pointer-events-none'>
|
||||
<div className="pointer-events-none absolute left-0 top-0 h-full w-full overflow-hidden">
|
||||
<span className={classNames(styles.leftLights, 'opacity-100')} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const LightsTwo = () => (
|
||||
<div className='absolute top-[1800px] lg:top-[1000px] left-0 w-full h-full overflow-hidden pointer-events-none'>
|
||||
<div className="pointer-events-none absolute left-0 top-[1800px] h-full w-full overflow-hidden lg:top-[1000px]">
|
||||
<span className={classNames(styles.lightsTwo, 'opacity-100')} />
|
||||
</div>
|
||||
);
|
||||
)
|
||||
|
||||
const Index = () => {
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
const coverPhotoAbsoluteUrl = `${siteConfig.url}${waspCoverPhoto}`;
|
||||
const { siteConfig } = useDocusaurusContext()
|
||||
const coverPhotoAbsoluteUrl = `${siteConfig.url}${waspCoverPhoto}`
|
||||
return (
|
||||
<div className='twLandingPage'>
|
||||
<div className="twLandingPage">
|
||||
<Head>
|
||||
{/* opengraph / facebook */}
|
||||
<meta property='og:type' content='website' />
|
||||
<meta property='og:url' content='https://wasp-lang.dev/' />
|
||||
<meta property='og:description' content='Develop full-stack web apps without boilerplate.' />
|
||||
<meta property='og:image' content={coverPhotoAbsoluteUrl} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://wasp-lang.dev/" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Develop full-stack web apps without boilerplate."
|
||||
/>
|
||||
<meta property="og:image" content={coverPhotoAbsoluteUrl} />
|
||||
{/* twitter */}
|
||||
<meta property='twitter:card' content='summary_large_image' />
|
||||
<meta property='twitter:url' content='https://wasp-lang.dev/' />
|
||||
<meta property='twitter:title' content='Develop full-stack web apps without boilerplate.' />
|
||||
<meta property='twitter:image' content={coverPhotoAbsoluteUrl} />
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:url" content="https://wasp-lang.dev/" />
|
||||
<meta
|
||||
property="twitter:title"
|
||||
content="Develop full-stack web apps without boilerplate."
|
||||
/>
|
||||
<meta property="twitter:image" content={coverPhotoAbsoluteUrl} />
|
||||
|
||||
<script id="wasp-langdev-2392a8eb" src="https://letsask.ai/widget.js"></script>
|
||||
<script
|
||||
id="wasp-langdev-2392a8eb"
|
||||
src="https://letsask.ai/widget.js"
|
||||
></script>
|
||||
</Head>
|
||||
<Nav />
|
||||
<div className='min-h-screen'>
|
||||
<div className="min-h-screen">
|
||||
<main>
|
||||
<Background />
|
||||
<div>
|
||||
@ -78,7 +87,7 @@ const Index = () => {
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Index;
|
||||
export default Index
|
||||
|
@ -30,8 +30,27 @@ html {
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
-moz-tab-size: 4; /* 3 */
|
||||
tab-size: 4; /* 3 */
|
||||
font-family: theme('fontFamily.sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); /* 4 */
|
||||
font-feature-settings: theme('fontFamily.sans[1].fontFeatureSettings', normal); /* 5 */
|
||||
font-family: theme(
|
||||
'fontFamily.sans',
|
||||
ui-sans-serif,
|
||||
system-ui,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
'Helvetica Neue',
|
||||
Arial,
|
||||
'Noto Sans',
|
||||
sans-serif,
|
||||
'Apple Color Emoji',
|
||||
'Segoe UI Emoji',
|
||||
'Segoe UI Symbol',
|
||||
'Noto Color Emoji'
|
||||
); /* 4 */
|
||||
font-feature-settings: theme(
|
||||
'fontFamily.sans[1].fontFeatureSettings',
|
||||
normal
|
||||
); /* 5 */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -105,7 +124,17 @@ Add the correct font weight in Edge and Safari.
|
||||
.twLandingPage kbd,
|
||||
.twLandingPage samp,
|
||||
.twLandingPage pre {
|
||||
font-family: theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); /* 1 */
|
||||
font-family: theme(
|
||||
'fontFamily.mono',
|
||||
ui-monospace,
|
||||
SFMono-Regular,
|
||||
Menlo,
|
||||
Monaco,
|
||||
Consolas,
|
||||
'Liberation Mono',
|
||||
'Courier New',
|
||||
monospace
|
||||
); /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
@ -322,7 +351,7 @@ Set the default cursor for buttons.
|
||||
*/
|
||||
|
||||
button,
|
||||
[role="button"] {
|
||||
[role='button'] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
}
|
||||
|
||||
.leftLights::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
width: 1223px;
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
background: radial-gradient(
|
||||
50% 50% at 50% 50%,
|
||||
rgba(255, 214, 0, 0.2) 0%,
|
||||
rgba(255, 214, 0, 0.2) 0%,
|
||||
rgba(255, 168, 0, 0) 100%
|
||||
);
|
||||
will-change: filter;
|
||||
@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
.lightsTwo::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
width: 1223px;
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
background: radial-gradient(
|
||||
50% 50% at 50% 50%,
|
||||
rgba(255, 214, 0, 0.2) 0%,
|
||||
rgba(255, 214, 0, 0.2) 0%,
|
||||
rgba(255, 168, 0, 0) 100%
|
||||
);
|
||||
will-change: filter;
|
||||
|
@ -1,26 +1,26 @@
|
||||
// Taken from the Prisma docs
|
||||
module.exports = (Prism) => {
|
||||
Prism.languages.prisma = Prism.languages.extend("clike", {
|
||||
Prism.languages.prisma = Prism.languages.extend('clike', {
|
||||
keyword: /\b(?:datasource|enum|generator|model|type|view)\b/,
|
||||
"type-class-name": /(\s+)[A-Z]\w+/, ///(\b)(\s+)[A-Z]\w+/
|
||||
});
|
||||
'type-class-name': /(\s+)[A-Z]\w+/, ///(\b)(\s+)[A-Z]\w+/
|
||||
})
|
||||
|
||||
Prism.languages.javascript["class-name"][0].pattern =
|
||||
/(\b(?:model|datasource|enum|generator|type)\s+)[\w.\\]+/;
|
||||
Prism.languages.javascript['class-name'][0].pattern =
|
||||
/(\b(?:model|datasource|enum|generator|type)\s+)[\w.\\]+/
|
||||
|
||||
Prism.languages.insertBefore("prisma", "function", {
|
||||
Prism.languages.insertBefore('prisma', 'function', {
|
||||
annotation: {
|
||||
pattern: /(^|[^.])@+\w+/,
|
||||
lookbehind: true,
|
||||
alias: "punctuation",
|
||||
alias: 'punctuation',
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
Prism.languages.insertBefore("prisma", "punctuation", {
|
||||
"type-args": /\b(?:references|fields|onDelete|onUpdate):/,
|
||||
});
|
||||
Prism.languages.insertBefore('prisma', 'punctuation', {
|
||||
'type-args': /\b(?:references|fields|onDelete|onUpdate):/,
|
||||
})
|
||||
|
||||
Prism.languages.insertBefore("prisma", "type-class-name", {
|
||||
"not-class": /\n(\s+)[A-Z]\w+/,
|
||||
});
|
||||
};
|
||||
Prism.languages.insertBefore('prisma', 'type-class-name', {
|
||||
'not-class': /\n(\s+)[A-Z]\w+/,
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Converted from the TextMate definition at https://github.com/wasp-lang/vscode-wasp/blob/main/syntaxes/wasp.tmLanguage.yaml
|
||||
module.exports = (Prism) => {
|
||||
Prism.languages.wasp = {
|
||||
"prisma-closure": {
|
||||
'prisma-closure': {
|
||||
pattern: /{=psl[\s\S]*?psl=}/,
|
||||
inside: {
|
||||
prisma: {
|
||||
@ -14,7 +14,7 @@ module.exports = (Prism) => {
|
||||
pattern: /\/\/.*|\/\*[\s\S]*?\*\//,
|
||||
greedy: true,
|
||||
},
|
||||
"json-closure": {
|
||||
'json-closure': {
|
||||
pattern: /{=json[\s\S]*?json=}/,
|
||||
inside: {
|
||||
punctuation: /[{}[\],]/,
|
||||
@ -33,11 +33,11 @@ module.exports = (Prism) => {
|
||||
boolean: /\b(?:false|true)\b/,
|
||||
null: {
|
||||
pattern: /\bnull\b/,
|
||||
alias: "keyword",
|
||||
alias: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
"js-import": {
|
||||
'js-import': {
|
||||
pattern: /import.*",?/,
|
||||
inside: Prism.languages.javascript,
|
||||
},
|
||||
@ -50,23 +50,24 @@ module.exports = (Prism) => {
|
||||
enum: {
|
||||
pattern:
|
||||
/\b(EmailAndPassword|PostgreSQL|SQLite|Simple|PgBoss|SMTP|SendGrid|Mailgun)\b/,
|
||||
alias: "constant",
|
||||
alias: 'constant',
|
||||
},
|
||||
"dict-key": {
|
||||
'dict-key': {
|
||||
pattern: /[a-zA-Z]+(?=:)/,
|
||||
alias: "plain",
|
||||
alias: 'plain',
|
||||
},
|
||||
"declaration-type": {
|
||||
pattern: /\b(action|apiNamespace|api|app|entity|job|page|query|route|crud)\b/,
|
||||
alias: "keyword",
|
||||
'declaration-type': {
|
||||
pattern:
|
||||
/\b(action|apiNamespace|api|app|entity|job|page|query|route|crud)\b/,
|
||||
alias: 'keyword',
|
||||
},
|
||||
"class-name": {
|
||||
'class-name': {
|
||||
pattern: /[a-zA-Z][0-9a-zA-Z]*/,
|
||||
alias: "variable",
|
||||
alias: 'variable',
|
||||
},
|
||||
"http-method": {
|
||||
'http-method': {
|
||||
pattern: /\b(ALL|GET|POST|PUT|DELETE)\b/,
|
||||
alias: "constant",
|
||||
alias: 'constant',
|
||||
},
|
||||
array: {
|
||||
pattern: /\[[\s\S]*?\]/,
|
||||
@ -74,10 +75,10 @@ module.exports = (Prism) => {
|
||||
punctuation: /[{}[\],]/,
|
||||
value: {
|
||||
pattern: /[^,\s\]]+/,
|
||||
alias: "variable",
|
||||
alias: 'variable',
|
||||
},
|
||||
},
|
||||
},
|
||||
punctuation: /[{}[\],]/,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copied from
|
||||
// https://github.com/redwoodjs/redwood/blob/bd903c5755925ea7174775a2fdaba371b700c910/docs/src/remark/auto-import-tabs.js
|
||||
// https://github.com/redwoodjs/redwood/blob/bd903c5755925ea7174775a2fdaba371b700c910/docs/src/remark/auto-import-tabs.js
|
||||
|
||||
const needImports = (tree) =>
|
||||
tree.children.some(
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Layout from '@theme/Layout';
|
||||
import BlogSidebar from '@theme/BlogSidebar';
|
||||
import React from 'react'
|
||||
import clsx from 'clsx'
|
||||
import Layout from '@theme/Layout'
|
||||
import BlogSidebar from '@theme/BlogSidebar'
|
||||
|
||||
/*
|
||||
|
||||
@ -22,7 +22,7 @@ import BlogSidebar from '@theme/BlogSidebar';
|
||||
// NOTE(matija): this component is used both when listing all the posts (on /blog) and when rendering a
|
||||
// specific blog post.
|
||||
export default function BlogLayout(props) {
|
||||
const {sidebar, toc, children, ...layoutProps} = props;
|
||||
const { sidebar, toc, children, ...layoutProps } = props
|
||||
|
||||
// NOTE(matija): if false, then it is an individual blog post.
|
||||
//
|
||||
@ -34,7 +34,7 @@ export default function BlogLayout(props) {
|
||||
<Layout {...layoutProps}>
|
||||
<div
|
||||
className={clsx({
|
||||
'container margin-vert--lg': !isListOfBlogPosts
|
||||
'margin-vert--lg container': !isListOfBlogPosts,
|
||||
})}
|
||||
>
|
||||
<div className="row">
|
||||
@ -44,12 +44,13 @@ export default function BlogLayout(props) {
|
||||
'col--7': !isListOfBlogPosts,
|
||||
})}
|
||||
itemScope
|
||||
itemType="http://schema.org/Blog">
|
||||
itemType="http://schema.org/Blog"
|
||||
>
|
||||
{children}
|
||||
</main>
|
||||
{toc && <div className="col col--2">{toc}</div>}
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import BlogPostItem from '@theme-original/BlogPostItem';
|
||||
import React from 'react'
|
||||
import BlogPostItem from '@theme-original/BlogPostItem'
|
||||
import Link from '@docusaurus/Link'
|
||||
|
||||
import SubscribeForm from '../../components/SubscribeForm'
|
||||
@ -9,41 +9,38 @@ export default function BlogPostItemWrapper(props) {
|
||||
<>
|
||||
<BlogPostItem {...props} />
|
||||
|
||||
<div className='grid grid-cols-1 xl:grid-cols-2 gap-6 mt-8'>
|
||||
|
||||
<JoinOurCommunityCard/>
|
||||
<JoinNewsletterCard/>
|
||||
|
||||
<div className="mt-8 grid grid-cols-1 gap-6 xl:grid-cols-2">
|
||||
<JoinOurCommunityCard />
|
||||
<JoinNewsletterCard />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
// TODO(matija): unifiy this with the icons used in navbar.
|
||||
//
|
||||
//import { DiscordIcon } from '../../components/Nav/SocialIcons'
|
||||
const DiscordIcon = () => (
|
||||
<svg height='100%' fill='currentColor' viewBox='0 5 30.67 23.25'>
|
||||
<svg height="100%" fill="currentColor" viewBox="0 5 30.67 23.25">
|
||||
<title>Discord</title>
|
||||
<path d='M26.0015 6.9529C24.0021 6.03845 21.8787 5.37198 19.6623 5C19.3833 5.48048 19.0733 6.13144 18.8563 6.64292C16.4989 6.30193 14.1585 6.30193 11.8336 6.64292C11.6166 6.13144 11.2911 5.48048 11.0276 5C8.79575 5.37198 6.67235 6.03845 4.6869 6.9529C0.672601 12.8736 -0.41235 18.6548 0.130124 24.3585C2.79599 26.2959 5.36889 27.4739 7.89682 28.2489C8.51679 27.4119 9.07477 26.5129 9.55525 25.5675C8.64079 25.2265 7.77283 24.808 6.93587 24.312C7.15286 24.1571 7.36986 23.9866 7.57135 23.8161C12.6241 26.1255 18.0969 26.1255 23.0876 23.8161C23.3046 23.9866 23.5061 24.1571 23.7231 24.312C22.8861 24.808 22.0182 25.2265 21.1037 25.5675C21.5842 26.5129 22.1422 27.4119 22.7621 28.2489C25.2885 27.4739 27.8769 26.2959 30.5288 24.3585C31.1952 17.7559 29.4733 12.0212 26.0015 6.9529ZM10.2527 20.8402C8.73376 20.8402 7.49382 19.4608 7.49382 17.7714C7.49382 16.082 8.70276 14.7025 10.2527 14.7025C11.7871 14.7025 13.0425 16.082 13.0115 17.7714C13.0115 19.4608 11.7871 20.8402 10.2527 20.8402ZM20.4373 20.8402C18.9183 20.8402 17.6768 19.4608 17.6768 17.7714C17.6768 16.082 18.8873 14.7025 20.4373 14.7025C21.9717 14.7025 23.2271 16.082 23.1961 17.7714C23.1961 19.4608 21.9872 20.8402 20.4373 20.8402Z'></path>
|
||||
<path d="M26.0015 6.9529C24.0021 6.03845 21.8787 5.37198 19.6623 5C19.3833 5.48048 19.0733 6.13144 18.8563 6.64292C16.4989 6.30193 14.1585 6.30193 11.8336 6.64292C11.6166 6.13144 11.2911 5.48048 11.0276 5C8.79575 5.37198 6.67235 6.03845 4.6869 6.9529C0.672601 12.8736 -0.41235 18.6548 0.130124 24.3585C2.79599 26.2959 5.36889 27.4739 7.89682 28.2489C8.51679 27.4119 9.07477 26.5129 9.55525 25.5675C8.64079 25.2265 7.77283 24.808 6.93587 24.312C7.15286 24.1571 7.36986 23.9866 7.57135 23.8161C12.6241 26.1255 18.0969 26.1255 23.0876 23.8161C23.3046 23.9866 23.5061 24.1571 23.7231 24.312C22.8861 24.808 22.0182 25.2265 21.1037 25.5675C21.5842 26.5129 22.1422 27.4119 22.7621 28.2489C25.2885 27.4739 27.8769 26.2959 30.5288 24.3585C31.1952 17.7559 29.4733 12.0212 26.0015 6.9529ZM10.2527 20.8402C8.73376 20.8402 7.49382 19.4608 7.49382 17.7714C7.49382 16.082 8.70276 14.7025 10.2527 14.7025C11.7871 14.7025 13.0425 16.082 13.0115 17.7714C13.0115 19.4608 11.7871 20.8402 10.2527 20.8402ZM20.4373 20.8402C18.9183 20.8402 17.6768 19.4608 17.6768 17.7714C17.6768 16.082 18.8873 14.7025 20.4373 14.7025C21.9717 14.7025 23.2271 16.082 23.1961 17.7714C23.1961 19.4608 21.9872 20.8402 20.4373 20.8402Z"></path>
|
||||
</svg>
|
||||
)
|
||||
|
||||
|
||||
const JoinOurCommunityCard = () => {
|
||||
const JoinOurCommunityButton = () => (
|
||||
<Link to='https://discord.gg/rzdnErX'>
|
||||
<span className={`
|
||||
<Link to="https://discord.gg/rzdnErX">
|
||||
<span
|
||||
className={`
|
||||
cursor-pointer
|
||||
`}
|
||||
>
|
||||
<div className='group inline-flex gap-1 items-center'>
|
||||
<div className="group inline-flex items-center gap-1">
|
||||
<span>Join our Discord 👾</span>
|
||||
<div className='transition-all group-hover:ml-0.5'>
|
||||
<span className='text-yellow-400'>→</span>
|
||||
<div className="transition-all group-hover:ml-0.5">
|
||||
<span className="text-yellow-400">→</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</span>
|
||||
</Link>
|
||||
)
|
||||
@ -51,29 +48,28 @@ const JoinOurCommunityCard = () => {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
bg-yellow-500/5 border border-yellow-500/25
|
||||
p-8 rounded-lg
|
||||
flex flex-col items-start
|
||||
space-y-3
|
||||
space-y-3 rounded-lg
|
||||
border border-yellow-500/25 bg-yellow-500/5
|
||||
p-8
|
||||
`}
|
||||
>
|
||||
<span
|
||||
<span
|
||||
className={`
|
||||
h-20
|
||||
border border-yellow-500/25
|
||||
px-4 py-5 rounded-full
|
||||
bg-white text-neutral-800
|
||||
rounded-full border
|
||||
border-yellow-500/25 bg-white px-4
|
||||
py-5 text-neutral-800
|
||||
`}
|
||||
>
|
||||
<DiscordIcon/>
|
||||
<DiscordIcon />
|
||||
</span>
|
||||
|
||||
<h3 className='font-semibold text-xl'>
|
||||
Join our developer community
|
||||
</h3>
|
||||
<h3 className="text-xl font-semibold">Join our developer community</h3>
|
||||
|
||||
<p>
|
||||
Wasp is 100% open source. Join our Discord to learn from others and get help whenever you need it!
|
||||
Wasp is 100% open source. Join our Discord to learn from others and get
|
||||
help whenever you need it!
|
||||
</p>
|
||||
|
||||
<JoinOurCommunityButton />
|
||||
@ -82,41 +78,32 @@ const JoinOurCommunityCard = () => {
|
||||
}
|
||||
|
||||
const JoinNewsletterCard = () => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
bg-yellow-500/20 border border-yellow-500/25
|
||||
p-8 rounded-lg
|
||||
flex flex-col items-start
|
||||
space-y-3
|
||||
space-y-3 rounded-lg
|
||||
border border-yellow-500/25 bg-yellow-500/20
|
||||
p-8
|
||||
`}
|
||||
>
|
||||
<span
|
||||
<span
|
||||
className={`
|
||||
h-20
|
||||
border border-yellow-500/25
|
||||
px-5 py-5 rounded-full
|
||||
bg-white text-neutral-800
|
||||
text-4xl
|
||||
rounded-full border
|
||||
border-yellow-500/25 bg-white px-5
|
||||
py-5 text-4xl
|
||||
text-neutral-800
|
||||
`}
|
||||
>
|
||||
📫
|
||||
</span>
|
||||
|
||||
<h3 className='font-semibold text-xl'>
|
||||
Subscribe to our newsletter
|
||||
</h3>
|
||||
<h3 className="text-xl font-semibold">Subscribe to our newsletter</h3>
|
||||
|
||||
<p>
|
||||
Once per month - receive useful blog posts and Wasp news.
|
||||
</p>
|
||||
|
||||
<SubscribeForm className='self-stretch'/>
|
||||
<p>Once per month - receive useful blog posts and Wasp news.</p>
|
||||
|
||||
<SubscribeForm className="self-stretch" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,27 +1,28 @@
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
import Link from '@docusaurus/Link'
|
||||
import {BlogPostProvider} from '@docusaurus/theme-common/internal';
|
||||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import { BlogPostProvider } from '@docusaurus/theme-common/internal'
|
||||
import BlogPostItem from '@theme/BlogPostItem'
|
||||
|
||||
import { ArrowRight } from 'react-feather'
|
||||
|
||||
const getReadingTimeStatement = (readingTimeFloat) => Math.ceil(readingTimeFloat) + ' min read'
|
||||
const getReadingTimeStatement = (readingTimeFloat) =>
|
||||
Math.ceil(readingTimeFloat) + ' min read'
|
||||
|
||||
export default function BlogPostItems({
|
||||
items,
|
||||
component: BlogPostItemComponent = BlogPostItem,
|
||||
}) {
|
||||
|
||||
// TODO(matija): what if there are no items (blog posts)?
|
||||
const featuredItem = items[0]
|
||||
const coverImgSrc = featuredItem.content.frontMatter.image || 'img/blog-default-img.png'
|
||||
const coverImgSrc =
|
||||
featuredItem.content.frontMatter.image || 'img/blog-default-img.png'
|
||||
|
||||
return (
|
||||
<>
|
||||
<section
|
||||
className={`
|
||||
pb-20 py-20 md:py-36
|
||||
bg-yellow-500
|
||||
bg-yellow-500 py-20 pb-20
|
||||
md:py-36
|
||||
`}
|
||||
>
|
||||
<div
|
||||
@ -31,95 +32,100 @@ export default function BlogPostItems({
|
||||
>
|
||||
<article
|
||||
className={`
|
||||
lg:grid grid-cols-2 gap-5 md:px-20 lg:px-24
|
||||
items-stretch
|
||||
relative
|
||||
relative grid-cols-2 items-stretch gap-5 md:px-20
|
||||
lg:grid
|
||||
lg:px-24
|
||||
`}
|
||||
>
|
||||
{/* Content - left col */}
|
||||
<div className='self-center lg:pr-16'>
|
||||
<div className="self-center lg:pr-16">
|
||||
<span
|
||||
className={`
|
||||
flex items-center justify-between
|
||||
uppercase text-[11px] text-neutral-600
|
||||
font-semibold tracking-wider
|
||||
mb-6
|
||||
mb-6 flex items-center
|
||||
justify-between text-[11px] font-semibold
|
||||
uppercase tracking-wider
|
||||
text-neutral-600
|
||||
`}
|
||||
>
|
||||
<span>By {featuredItem.content.metadata.authors[0].name}</span>
|
||||
<div className='flex-1 bg-neutral-600/20 h-px mx-2'></div>
|
||||
<span>{getReadingTimeStatement(featuredItem.content.metadata.readingTime)}</span>
|
||||
<div className="mx-2 h-px flex-1 bg-neutral-600/20"></div>
|
||||
<span>
|
||||
{getReadingTimeStatement(
|
||||
featuredItem.content.metadata.readingTime
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{/* Title */}
|
||||
<h1 className='text-4xl leading-tight text-neutral-800'>
|
||||
<h1 className="text-4xl leading-tight text-neutral-800">
|
||||
{featuredItem.content.frontMatter.title}
|
||||
</h1>
|
||||
|
||||
|
||||
{/* Read more button */}
|
||||
<div className='mt-24'>
|
||||
<span className={`
|
||||
bg-neutral-600 text-white
|
||||
px-3 py-1.5 rounded-md
|
||||
<div className="mt-24">
|
||||
<span
|
||||
className={`
|
||||
rounded-md bg-neutral-600
|
||||
px-3 py-1.5 text-white
|
||||
`}
|
||||
>
|
||||
<div className='group inline-flex gap-1 items-center'>
|
||||
<div className="group inline-flex items-center gap-1">
|
||||
<span>Read more</span>
|
||||
<span className='text-yellow-400'>→</span>
|
||||
<span className="text-yellow-400">→</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Image - right col */}
|
||||
<img
|
||||
<img
|
||||
src={coverImgSrc}
|
||||
className={`
|
||||
object-cover
|
||||
rounded-2xl mb-6
|
||||
hidden lg:flex
|
||||
className={`
|
||||
mb-6
|
||||
hidden rounded-2xl
|
||||
object-cover lg:flex
|
||||
`}
|
||||
/>
|
||||
|
||||
<Link to={featuredItem.content.metadata.permalink} className='opacity-0 absolute inset-0'/>
|
||||
<Link
|
||||
to={featuredItem.content.metadata.permalink}
|
||||
className="absolute inset-0 opacity-0"
|
||||
/>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
<section className='container mx-auto px-4 sm:px-6 md:px-20 lg:px-28'>
|
||||
<div className='grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-5 mb-8 md:-mt-12'>
|
||||
<section className="container mx-auto px-4 sm:px-6 md:px-20 lg:px-28">
|
||||
<div className="mb-8 grid grid-cols-1 gap-5 md:-mt-12 md:grid-cols-2 xl:grid-cols-3">
|
||||
{items.slice(1).map((item) => {
|
||||
const BlogPostContent = item.content
|
||||
const coverImgSrc = item.content.frontMatter.image || 'img/blog-default-img.png'
|
||||
const coverImgSrc =
|
||||
item.content.frontMatter.image || 'img/blog-default-img.png'
|
||||
|
||||
return (
|
||||
<article
|
||||
key={item.content.metadata.permalink}
|
||||
className={`
|
||||
relative
|
||||
flex
|
||||
|
||||
flex-col
|
||||
rounded-2xl
|
||||
|
||||
bg-[--custom-blog-card-background-color]
|
||||
transition-all
|
||||
shadow-sm shadow-yellow-500/25
|
||||
hover:shadow-lg hover:shadow-yellow-500/25
|
||||
|
||||
border border-neutral-200/20
|
||||
flex flex-col
|
||||
p-8
|
||||
bg-[--custom-blog-card-background-color] p-8
|
||||
|
||||
shadow-sm shadow-yellow-500/25
|
||||
transition-all hover:shadow-lg
|
||||
hover:shadow-yellow-500/25
|
||||
`}
|
||||
>
|
||||
{/* Image */}
|
||||
<img
|
||||
<img
|
||||
src={coverImgSrc}
|
||||
className={`
|
||||
object-cover
|
||||
rounded-xl mb-6
|
||||
md:max-w-none h-64 md:-mx-6 md:-mt-6
|
||||
className={`
|
||||
mb-6
|
||||
h-64 rounded-xl
|
||||
object-cover md:-mx-6 md:-mt-6 md:max-w-none
|
||||
`}
|
||||
/>
|
||||
|
||||
@ -127,23 +133,32 @@ export default function BlogPostItems({
|
||||
<span
|
||||
className={`
|
||||
flex items-center
|
||||
uppercase text-[11px] text-[--custom-blog-card-timestamp-color]
|
||||
font-semibold tracking-wider
|
||||
text-[11px] font-semibold uppercase
|
||||
tracking-wider text-[--custom-blog-card-timestamp-color]
|
||||
`}
|
||||
>
|
||||
<span className='truncate'>By {item.content.metadata.authors[0].name}</span>
|
||||
<div className='flex-1 bg-gray-200 h-px mx-2'></div>
|
||||
<span>{getReadingTimeStatement(item.content.metadata.readingTime)}</span>
|
||||
<span className="truncate">
|
||||
By {item.content.metadata.authors[0].name}
|
||||
</span>
|
||||
<div className="mx-2 h-px flex-1 bg-gray-200"></div>
|
||||
<span>
|
||||
{getReadingTimeStatement(item.content.metadata.readingTime)}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{/* Title */}
|
||||
<h1 className='text-xl h-28 my-4'>
|
||||
<h1 className="my-4 h-28 text-xl">
|
||||
{item.content.frontMatter.title}
|
||||
</h1>
|
||||
|
||||
<p className='text-yellow-600 font-semibold mt-0 mb-0'>Read more →</p>
|
||||
<p className="mb-0 mt-0 font-semibold text-yellow-600">
|
||||
Read more →
|
||||
</p>
|
||||
|
||||
<Link to={item.content.metadata.permalink} className='opacity-0 absolute inset-0'/>
|
||||
<Link
|
||||
to={item.content.metadata.permalink}
|
||||
className="absolute inset-0 opacity-0"
|
||||
/>
|
||||
</article>
|
||||
)
|
||||
|
||||
@ -162,5 +177,5 @@ export default function BlogPostItems({
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
// This file gets auto-generated when you "eject" to add custom languages to Docosaurus
|
||||
// We use it to add support for Prisma and Wasp syntax highlighting
|
||||
import siteConfig from "@generated/docusaurus.config";
|
||||
import siteConfig from '@generated/docusaurus.config'
|
||||
export default function prismIncludeLanguages(PrismObject) {
|
||||
const {
|
||||
themeConfig: { prism },
|
||||
} = siteConfig;
|
||||
const { additionalLanguages } = prism;
|
||||
} = siteConfig
|
||||
const { additionalLanguages } = prism
|
||||
// Prism components work on the Prism instance on the window, while prism-
|
||||
// react-renderer uses its own Prism instance. We temporarily mount the
|
||||
// instance onto window, import components to enhance it, then remove it to
|
||||
// avoid polluting global namespace.
|
||||
// You can mutate PrismObject: registering plugins, deleting languages... As
|
||||
// long as you don't re-assign it
|
||||
globalThis.Prism = PrismObject;
|
||||
globalThis.Prism = PrismObject
|
||||
additionalLanguages.forEach((lang) => {
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require
|
||||
require(`prismjs/components/prism-${lang}`);
|
||||
});
|
||||
require(`prismjs/components/prism-${lang}`)
|
||||
})
|
||||
|
||||
require("./prism-prisma");
|
||||
require("./prism-wasp");
|
||||
delete globalThis.Prism;
|
||||
require('./prism-prisma')
|
||||
require('./prism-wasp')
|
||||
delete globalThis.Prism
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
require("../prism/prisma")(Prism);
|
||||
require('../prism/prisma')(Prism)
|
||||
|
@ -1 +1 @@
|
||||
require("../prism/wasp")(Prism);
|
||||
require('../prism/wasp')(Prism)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./src/**/*.{js,jsx,ts,tsx}"],
|
||||
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
||||
important: true,
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
@ -8,9 +8,9 @@ module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Inter']
|
||||
}
|
||||
sans: ['Inter'],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user