mirror of
https://github.com/wasp-lang/open-saas.git
synced 2025-05-19 00:30:19 +02:00
address feedback
This commit is contained in:
parent
c1b99c6e55
commit
6e8fb18eab
@ -19,7 +19,7 @@ export default function GptPage() {
|
|||||||
const response = await generateGptResponse({ instructions, command, temperature });
|
const response = await generateGptResponse({ instructions, command, temperature });
|
||||||
if (response) {
|
if (response) {
|
||||||
setResponse(response.split('\n'));
|
setResponse(response.split('\n'));
|
||||||
console.log(response)
|
console.log(response);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
alert(error.message);
|
alert(error.message);
|
||||||
@ -138,7 +138,7 @@ export default function GptPage() {
|
|||||||
} mt-4 mx-6 flex justify-center rounded-lg border border-dashed border-gray-900/25 sm:w-[90%] md:w-[50%] mx-auto mt-12 px-6 py-10`}
|
} mt-4 mx-6 flex justify-center rounded-lg border border-dashed border-gray-900/25 sm:w-[90%] md:w-[50%] mx-auto mt-12 px-6 py-10`}
|
||||||
>
|
>
|
||||||
<div className='space-y-2 flex flex-col gap-2 text-center text-sm text-gray-500 w-full'>
|
<div className='space-y-2 flex flex-col gap-2 text-center text-sm text-gray-500 w-full'>
|
||||||
{response.length > 0 ? response.map((str) => <p key={str}>{str}</p>) : <p>GPT Response will load here</p>}
|
{response.length > 0 ? response.map((str) => <p key={str}>{str}</p>) : <p>GPT Response will load here</p>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,6 @@ const DropdownUser = ({ user } : { user: Partial<User> }) => {
|
|||||||
|
|
||||||
const toggleDropdown = () => setDropdownOpen((prev) => !prev);
|
const toggleDropdown = () => setDropdownOpen((prev) => !prev);
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const clickHandler = ({ target }: MouseEvent) => {
|
const clickHandler = ({ target }: MouseEvent) => {
|
||||||
if (!dropdown.current) return
|
if (!dropdown.current) return
|
||||||
@ -62,7 +61,7 @@ const DropdownUser = ({ user } : { user: Partial<User> }) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* <!-- Dropdown Start --> */}
|
{/* <!-- Dropdown --> */}
|
||||||
<div
|
<div
|
||||||
ref={dropdown}
|
ref={dropdown}
|
||||||
className={`absolute right-0 mt-4 flex w-62.5 flex-col rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark ${
|
className={`absolute right-0 mt-4 flex w-62.5 flex-col rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark ${
|
||||||
@ -71,7 +70,6 @@ const DropdownUser = ({ user } : { user: Partial<User> }) => {
|
|||||||
>
|
>
|
||||||
<UserMenuItems user={user} />
|
<UserMenuItems user={user} />
|
||||||
</div>
|
</div>
|
||||||
{/* <!-- Dropdown End --> */}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState } from 'react';
|
||||||
import { Dialog } from '@headlessui/react';
|
import { Dialog } from '@headlessui/react';
|
||||||
import { AiFillCloseCircle } from 'react-icons/ai';
|
import { AiFillCloseCircle, AiFillGithub } from 'react-icons/ai';
|
||||||
import { HiBars3 } from 'react-icons/hi2';
|
import { HiBars3 } from 'react-icons/hi2';
|
||||||
import { BiLogIn } from 'react-icons/bi';
|
import { BiLogIn } from 'react-icons/bi';
|
||||||
import { Link } from '@wasp/router';
|
import { Link } from '@wasp/router';
|
||||||
@ -8,54 +8,19 @@ import logo from '../static/logo.png';
|
|||||||
import openSaasBanner from '../static/open-saas-banner.png';
|
import openSaasBanner from '../static/open-saas-banner.png';
|
||||||
import { features, navigation, faqs, footerNavigation, testimonials } from './contentSections';
|
import { features, navigation, faqs, footerNavigation, testimonials } from './contentSections';
|
||||||
import DropdownUser from '../components/DropdownUser';
|
import DropdownUser from '../components/DropdownUser';
|
||||||
import { DOCS_URL } from '@wasp/shared/constants';
|
import { DOCS_URL, GITHUB_URL } from '@wasp/shared/constants';
|
||||||
import { UserMenuItems } from '../components/UserMenuItems';
|
import { UserMenuItems } from '../components/UserMenuItems';
|
||||||
import useAuth from '@wasp/auth/useAuth';
|
import useAuth from '@wasp/auth/useAuth';
|
||||||
|
|
||||||
export default function LandingPage() {
|
export default function LandingPage() {
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||||
const [isDemoInfoVisible, setIsDemoInfoVisible] = useState(false);
|
|
||||||
|
|
||||||
const { data: user, isLoading: isUserLoading } = useAuth();
|
const { data: user, isLoading: isUserLoading } = useAuth();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
if (localStorage.getItem('isDemoInfoVisible') === 'false') {
|
|
||||||
// do nothing
|
|
||||||
} else {
|
|
||||||
setIsDemoInfoVisible(true);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDemoInfoClose = () => {
|
|
||||||
try {
|
|
||||||
localStorage.setItem('isDemoInfoVisible', 'false');
|
|
||||||
setIsDemoInfoVisible(false);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const NavLogo = () => <img className='h-8 w-8' src={logo} alt='Open SaaS App' />;
|
const NavLogo = () => <img className='h-8 w-8' src={logo} alt='Open SaaS App' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='bg-white'>
|
<div className='bg-white'>
|
||||||
{/* Floating Demo Announcement */}
|
|
||||||
{isDemoInfoVisible && (
|
|
||||||
<div className='fixed z-999 bottom-0 mb-2 left-1/2 -translate-x-1/2 lg:mb-4 bg-gray-700 rounded-full px-3.5 py-2 text-sm text-white duration-300 ease-in-out hover:bg-gray-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-indigo-600'>
|
|
||||||
<div className='px-4 flex flex-row gap-2 items-center my-1'>
|
|
||||||
<span className='text-gray-100'>
|
|
||||||
This demo app <span className='italic'>is</span> the SaaS template. Feel free to play around!
|
|
||||||
</span>
|
|
||||||
<button className=' pl-2.5 text-gray-400 text-xl font-bold' onClick={() => handleDemoInfoClose()}>
|
|
||||||
X
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<header className='absolute inset-x-0 top-0 z-50'>
|
<header className='absolute inset-x-0 top-0 z-50'>
|
||||||
<nav className='flex items-center justify-between p-6 lg:px-8' aria-label='Global'>
|
<nav className='flex items-center justify-between p-6 lg:px-8' aria-label='Global'>
|
||||||
@ -94,7 +59,7 @@ export default function LandingPage() {
|
|||||||
{isUserLoading ? null : !user ? (
|
{isUserLoading ? null : !user ? (
|
||||||
<Link to='/login'>
|
<Link to='/login'>
|
||||||
<div className='flex justify-end items-center duration-300 ease-in-out text-gray-900 hover:text-yellow-500'>
|
<div className='flex justify-end items-center duration-300 ease-in-out text-gray-900 hover:text-yellow-500'>
|
||||||
Log in <BiLogIn size='1.1rem' className='ml-1 mt-[0.1rem]' />
|
Try the Demo App <BiLogIn size='1.1rem' className='ml-1' />
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
@ -137,7 +102,7 @@ export default function LandingPage() {
|
|||||||
{isUserLoading ? null : !user ? (
|
{isUserLoading ? null : !user ? (
|
||||||
<Link to='/login'>
|
<Link to='/login'>
|
||||||
<div className='flex justify-end items-center duration-300 ease-in-out text-gray-900 hover:text-yellow-500'>
|
<div className='flex justify-end items-center duration-300 ease-in-out text-gray-900 hover:text-yellow-500'>
|
||||||
Log in <BiLogIn size='1.1rem' className='ml-1 mt-[0.1rem]' />
|
Try the Demo App <BiLogIn size='1.1rem' className='ml-1' />
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
@ -185,16 +150,18 @@ export default function LandingPage() {
|
|||||||
An open-source, feature-rich, full-stack React + NodeJS template that manages features for you.
|
An open-source, feature-rich, full-stack React + NodeJS template that manages features for you.
|
||||||
</p>
|
</p>
|
||||||
<div className='mt-10 flex items-center justify-center gap-x-6'>
|
<div className='mt-10 flex items-center justify-center gap-x-6'>
|
||||||
{/* <a
|
|
||||||
href='https://github.com/wasp-lang/open-saas'
|
|
||||||
className='rounded-md bg-yellow-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:text-white shadow-sm hover:bg-yellow-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
|
|
||||||
></a> */}
|
|
||||||
<a
|
<a
|
||||||
href={DOCS_URL}
|
href={DOCS_URL}
|
||||||
className='rounded-md px-3.5 py-2.5 text-sm font-semibold text-gray-700 ring-1 ring-inset ring-gray-200 hover:ring-2 hover:ring-purple-200 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
|
className='rounded-md px-3.5 py-2.5 text-sm font-semibold text-gray-700 ring-1 ring-inset ring-gray-200 hover:ring-2 hover:ring-yellow-300 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
|
||||||
>
|
>
|
||||||
Get Started <span aria-hidden='true'>→</span>
|
Get Started <span aria-hidden='true'>→</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a
|
||||||
|
href={GITHUB_URL}
|
||||||
|
className='flex items-center justify-center rounded-md bg-gray-100 px-3.5 py-2.5 text-sm font-semibold shadow-sm ring-1 ring-inset ring-gray-200 hover:ring-2 hover:ring-yellow-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
|
||||||
|
>
|
||||||
|
View the Repo <AiFillGithub size='1rem' className='ml-1' />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-14 flow-root sm:mt-14 '>
|
<div className='mt-14 flow-root sm:mt-14 '>
|
||||||
@ -269,11 +236,7 @@ export default function LandingPage() {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex justify-center col-span-1 w-full max-h-12 object-contain grayscale opacity-75'>
|
<div className='flex justify-center col-span-1 w-full max-h-12 object-contain grayscale opacity-75'>
|
||||||
<svg
|
<svg xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='xMidYMid' viewBox='0 0 256 260'>
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
|
||||||
preserveAspectRatio='xMidYMid'
|
|
||||||
viewBox='0 0 256 260'
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
fill='#545454'
|
fill='#545454'
|
||||||
d='M239.184 106.203a64.716 64.716 0 0 0-5.576-53.103C219.452 28.459 191 15.784 163.213 21.74A65.586 65.586 0 0 0 52.096 45.22a64.716 64.716 0 0 0-43.23 31.36c-14.31 24.602-11.061 55.634 8.033 76.74a64.665 64.665 0 0 0 5.525 53.102c14.174 24.65 42.644 37.324 70.446 31.36a64.72 64.72 0 0 0 48.754 21.744c28.481.025 53.714-18.361 62.414-45.481a64.767 64.767 0 0 0 43.229-31.36c14.137-24.558 10.875-55.423-8.083-76.483Zm-97.56 136.338a48.397 48.397 0 0 1-31.105-11.255l1.535-.87 51.67-29.825a8.595 8.595 0 0 0 4.247-7.367v-72.85l21.845 12.636c.218.111.37.32.409.563v60.367c-.056 26.818-21.783 48.545-48.601 48.601Zm-104.466-44.61a48.345 48.345 0 0 1-5.781-32.589l1.534.921 51.722 29.826a8.339 8.339 0 0 0 8.441 0l63.181-36.425v25.221a.87.87 0 0 1-.358.665l-52.335 30.184c-23.257 13.398-52.97 5.431-66.404-17.803ZM23.549 85.38a48.499 48.499 0 0 1 25.58-21.333v61.39a8.288 8.288 0 0 0 4.195 7.316l62.874 36.272-21.845 12.636a.819.819 0 0 1-.767 0L41.353 151.53c-23.211-13.454-31.171-43.144-17.804-66.405v.256Zm179.466 41.695-63.08-36.63L161.73 77.86a.819.819 0 0 1 .768 0l52.233 30.184a48.6 48.6 0 0 1-7.316 87.635v-61.391a8.544 8.544 0 0 0-4.4-7.213Zm21.742-32.69-1.535-.922-51.619-30.081a8.39 8.39 0 0 0-8.492 0L99.98 99.808V74.587a.716.716 0 0 1 .307-.665l52.233-30.133a48.652 48.652 0 0 1 72.236 50.391v.205ZM88.061 139.097l-21.845-12.585a.87.87 0 0 1-.41-.614V65.685a48.652 48.652 0 0 1 79.757-37.346l-1.535.87-51.67 29.825a8.595 8.595 0 0 0-4.246 7.367l-.051 72.697Zm11.868-25.58 28.138-16.217 28.188 16.218v32.434l-28.086 16.218-28.188-16.218-.052-32.434Z'
|
d='M239.184 106.203a64.716 64.716 0 0 0-5.576-53.103C219.452 28.459 191 15.784 163.213 21.74A65.586 65.586 0 0 0 52.096 45.22a64.716 64.716 0 0 0-43.23 31.36c-14.31 24.602-11.061 55.634 8.033 76.74a64.665 64.665 0 0 0 5.525 53.102c14.174 24.65 42.644 37.324 70.446 31.36a64.72 64.72 0 0 0 48.754 21.744c28.481.025 53.714-18.361 62.414-45.481a64.767 64.767 0 0 0 43.229-31.36c14.137-24.558 10.875-55.423-8.083-76.483Zm-97.56 136.338a48.397 48.397 0 0 1-31.105-11.255l1.535-.87 51.67-29.825a8.595 8.595 0 0 0 4.247-7.367v-72.85l21.845 12.636c.218.111.37.32.409.563v60.367c-.056 26.818-21.783 48.545-48.601 48.601Zm-104.466-44.61a48.345 48.345 0 0 1-5.781-32.589l1.534.921 51.722 29.826a8.339 8.339 0 0 0 8.441 0l63.181-36.425v25.221a.87.87 0 0 1-.358.665l-52.335 30.184c-23.257 13.398-52.97 5.431-66.404-17.803ZM23.549 85.38a48.499 48.499 0 0 1 25.58-21.333v61.39a8.288 8.288 0 0 0 4.195 7.316l62.874 36.272-21.845 12.636a.819.819 0 0 1-.767 0L41.353 151.53c-23.211-13.454-31.171-43.144-17.804-66.405v.256Zm179.466 41.695-63.08-36.63L161.73 77.86a.819.819 0 0 1 .768 0l52.233 30.184a48.6 48.6 0 0 1-7.316 87.635v-61.391a8.544 8.544 0 0 0-4.4-7.213Zm21.742-32.69-1.535-.922-51.619-30.081a8.39 8.39 0 0 0-8.492 0L99.98 99.808V74.587a.716.716 0 0 1 .307-.665l52.233-30.133a48.652 48.652 0 0 1 72.236 50.391v.205ZM88.061 139.097l-21.845-12.585a.87.87 0 0 1-.41-.614V65.685a48.652 48.652 0 0 1 79.757-37.346l-1.535.87-51.67 29.825a8.595 8.595 0 0 0-4.246 7.367l-.051 72.697Zm11.868-25.58 28.138-16.217 28.188 16.218v32.434l-28.086 16.218-28.188-16.218-.052-32.434Z'
|
||||||
@ -287,12 +250,11 @@ export default function LandingPage() {
|
|||||||
<div id='features' className='mx-auto mt-48 max-w-7xl px-6 lg:px-8'>
|
<div id='features' className='mx-auto mt-48 max-w-7xl px-6 lg:px-8'>
|
||||||
<div className='mx-auto max-w-2xl text-center'>
|
<div className='mx-auto max-w-2xl text-center'>
|
||||||
<p className='mt-2 text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl'>
|
<p className='mt-2 text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl'>
|
||||||
All the important <span className='text-yellow-500'>stuff</span>
|
<span className='text-yellow-500'>100%</span> Open-Source
|
||||||
</p>
|
</p>
|
||||||
<p className='mt-6 text-lg leading-8 text-gray-600'>
|
<p className='mt-6 text-lg leading-8 text-gray-600'>
|
||||||
We've pre-built the important stuff.
|
No vendor lock-in.
|
||||||
<br /> Wasp does the boilerplate stuff.
|
<br /> Deploy anywhere.
|
||||||
<br /> You get to do the fun stuff.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-4xl'>
|
<div className='mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-4xl'>
|
||||||
@ -316,7 +278,9 @@ export default function LandingPage() {
|
|||||||
<div className='mx-auto mt-32 max-w-7xl sm:mt-56 sm:px-6 lg:px-8'>
|
<div className='mx-auto mt-32 max-w-7xl sm:mt-56 sm:px-6 lg:px-8'>
|
||||||
<div className='relative sm:left-5 -m-2 rounded-xl bg-yellow-400/20 lg:ring-1 lg:ring-yellow-500/50 lg:-m-4 '>
|
<div className='relative sm:left-5 -m-2 rounded-xl bg-yellow-400/20 lg:ring-1 lg:ring-yellow-500/50 lg:-m-4 '>
|
||||||
<div className='relative sm:top-5 sm:right-5 bg-gray-900 px-8 py-20 shadow-xl sm:rounded-xl sm:px-10 sm:py-16 md:px-12 lg:px-20'>
|
<div className='relative sm:top-5 sm:right-5 bg-gray-900 px-8 py-20 shadow-xl sm:rounded-xl sm:px-10 sm:py-16 md:px-12 lg:px-20'>
|
||||||
<h2 className='text-left font-semibold tracking-wide leading-7 text-gray-500'>Testimonials</h2>
|
<h2 className='text-left text-xl font-semibold tracking-wide leading-7 text-gray-500'>
|
||||||
|
What Our Users Say
|
||||||
|
</h2>
|
||||||
<div className='relative flex flex-wrap gap-6 w-full mt-6 z-10 justify-between lg:mx-0'>
|
<div className='relative flex flex-wrap gap-6 w-full mt-6 z-10 justify-between lg:mx-0'>
|
||||||
{testimonials.map((testimonial) => (
|
{testimonials.map((testimonial) => (
|
||||||
<figure className='w-full lg:w-1/4 box-content flex flex-col justify-between p-8 rounded-xl bg-gray-500/5 '>
|
<figure className='w-full lg:w-1/4 box-content flex flex-col justify-between p-8 rounded-xl bg-gray-500/5 '>
|
||||||
@ -348,6 +312,11 @@ export default function LandingPage() {
|
|||||||
<dt className='text-base font-semibold leading-7 text-gray-900 lg:col-span-5'>{faq.question}</dt>
|
<dt className='text-base font-semibold leading-7 text-gray-900 lg:col-span-5'>{faq.question}</dt>
|
||||||
<dd className='mt-4 lg:col-span-7 lg:mt-0'>
|
<dd className='mt-4 lg:col-span-7 lg:mt-0'>
|
||||||
<p className='text-base leading-7 text-gray-600'>{faq.answer}</p>
|
<p className='text-base leading-7 text-gray-600'>{faq.answer}</p>
|
||||||
|
{faq.href && (
|
||||||
|
<a href={faq.href} className='mt-4 text-base leading-7 text-yellow-500 hover:text-yellow-600'>
|
||||||
|
Learn more →
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -361,7 +330,7 @@ export default function LandingPage() {
|
|||||||
<h2 id='footer-heading' className='sr-only'>
|
<h2 id='footer-heading' className='sr-only'>
|
||||||
Footer
|
Footer
|
||||||
</h2>
|
</h2>
|
||||||
<div className='flex items-center justify-end mt-10 gap-20'>
|
<div className='flex items-start justify-end mt-10 gap-20'>
|
||||||
<div>
|
<div>
|
||||||
<h3 className='text-sm font-semibold leading-6 text-gray-900'>App</h3>
|
<h3 className='text-sm font-semibold leading-6 text-gray-900'>App</h3>
|
||||||
<ul role='list' className='mt-6 space-y-4'>
|
<ul role='list' className='mt-6 space-y-4'>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { DOCS_URL, BLOG_URL } from '@wasp/shared/constants';
|
import { DOCS_URL, BLOG_URL, GITHUB_URL } from '@wasp/shared/constants';
|
||||||
import daBoiAavatar from '../static/da-boi.png';
|
import daBoiAavatar from '../static/da-boi.png';
|
||||||
|
|
||||||
export const navigation = [
|
export const navigation = [
|
||||||
@ -10,58 +10,68 @@ export const features = [
|
|||||||
{
|
{
|
||||||
name: 'Open-Source Philosophy',
|
name: 'Open-Source Philosophy',
|
||||||
description:
|
description:
|
||||||
"Forever free and open-source. Create an issue, make a PR, and together let's make the best SaaS template ever!",
|
'The repo and framework are 100% open-source, and so are the services wherever possible. Still missing something? Contribute!',
|
||||||
icon: '🤝',
|
icon: '🤝',
|
||||||
|
href: DOCS_URL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Auto-magic Auth',
|
name: 'DIY Auth, Done For You',
|
||||||
description:
|
description: 'Pre-configured full-stack Auth that you own. No 3rd-party services or hidden fees.',
|
||||||
'Not only is full-stack Auth pre-configured, but you can integrate more providers with just a few lines of code.',
|
|
||||||
icon: '🔐',
|
icon: '🔐',
|
||||||
|
href: DOCS_URL + '/guides/authentication/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Full-stack Type Safety',
|
name: 'Full-stack Type Safety',
|
||||||
description:
|
description:
|
||||||
'Because Wasp understands your app, it provides end-to-end type safety out of the box. Nothing to configure!',
|
'Full support for TypeScript with auto-generated types that span the whole stack. Nothing to configure!',
|
||||||
icon: '🥞',
|
icon: '🥞',
|
||||||
|
href: DOCS_URL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Stripe Integration',
|
name: 'Stripe Integration',
|
||||||
description:
|
description:
|
||||||
"No SaaS is complete without payments. That's why subscriptions and the necessary webhooks are built-in.",
|
"No SaaS is complete without payments. That's why subscriptions and the necessary webhooks are built-in.",
|
||||||
icon: '💸',
|
icon: '💸',
|
||||||
|
href: DOCS_URL + '/guides/stripe-integration/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Admin Dashboard',
|
name: 'Admin Dashboard',
|
||||||
description: 'Graphs! Tables! Analytics w/ Plausible or Google! All in one place. Ooooooooooh.',
|
description: 'Graphs! Tables! Analytics w/ Plausible or Google! All in one place. Ooooooooooh.',
|
||||||
icon: '📈',
|
icon: '📈',
|
||||||
|
href: DOCS_URL + '/general/admin-dashboard/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Blog w/ Astro',
|
name: 'Blog w/ Astro',
|
||||||
description: 'Built-in blog with the Astro framework. Write your posts in Markdown, and watch your SEO performance take off.',
|
description:
|
||||||
|
'Built-in blog with the Astro framework. Write your posts in Markdown, and watch your SEO performance take off.',
|
||||||
icon: '📝',
|
icon: '📝',
|
||||||
|
href: DOCS_URL + '/start/guided-tour/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Email Sending',
|
name: 'Email Sending',
|
||||||
description:
|
description:
|
||||||
"Email sending built-in and pre-configured. Combine it with Wasp's cron jobs feature to easily send emails to your customers.",
|
'Email sending built-in. Combine it with the cron jobs feature to easily send emails to your customers.',
|
||||||
icon: '📧',
|
icon: '📧',
|
||||||
|
href: DOCS_URL + '/guides/email-sending/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'OpenAI API Implemented',
|
name: 'OpenAI API Implemented',
|
||||||
description: "Technology is changing rapidly. Ship your new AI-powered app before it's already obsolete!",
|
description: 'Have a sweet AI-powered app concept? Get your idea shipped to potential customers in days!',
|
||||||
icon: '🤖',
|
icon: '🤖',
|
||||||
|
href: DOCS_URL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Deploy Anywhere. Easily.',
|
name: 'Deploy Anywhere. Easily.',
|
||||||
description:
|
description:
|
||||||
'You own all your code, and can deploy wherever & however you want. Or just let Wasp deploy it for you with a single command.',
|
'No vendor lock-in because you own all your code. Deploy yourself, or let Wasp deploy it for you with a single command.',
|
||||||
icon: '🚀 ',
|
icon: '🚀 ',
|
||||||
|
href: DOCS_URL + '/guides/deploying/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Complete Documentation & Support',
|
name: 'Complete Documentation & Support',
|
||||||
description: "We don't leave you hanging. We have tons of docs, and a Discord community to help!",
|
description: "We don't leave you hanging. We have detailed docs and a Discord community to help!",
|
||||||
icon: '🫂',
|
icon: '🫂',
|
||||||
|
href: DOCS_URL,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
export const testimonials = [
|
export const testimonials = [
|
||||||
@ -114,23 +124,25 @@ export const testimonials = [
|
|||||||
export const faqs = [
|
export const faqs = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
question: 'Why is this amazing SaaS Template free and open-source?',
|
question: 'Why is this SaaS Template free and open-source?',
|
||||||
answer: 'Because open-source is cool, and we love you ❤️',
|
answer:
|
||||||
|
'We believe the best product is made when the community puts their heads together. We also believe a quality starting point for a web app should be free and available to everyone. Our hope is that together we can create the best SaaS template out there and bring our ideas to customers quickly.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
question: "What's Wasp?",
|
question: "What's Wasp?",
|
||||||
answer:
|
href: 'https://wasp-lang.dev',
|
||||||
"It's the fastest way to develop full-stack React + NodeJS + Prisma apps. It's what gives this template superpowers.",
|
answer: "It's the fastest way to develop full-stack React + NodeJS + Prisma apps and it's what gives this template superpowers. Wasp relies on React, NodeJS, and Prisma to define web components and server queries and actions. Wasp's secret sauce is its compiler which takes the client, server code, and config file and outputs the client app, server app and deployment code, supercharging the development experience. Combined with this template, you can build a SaaS app in record time.",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
export const footerNavigation = {
|
export const footerNavigation = {
|
||||||
app: [
|
app: [
|
||||||
|
{ name: 'Github', href: GITHUB_URL },
|
||||||
{ name: 'Documentation', href: DOCS_URL },
|
{ name: 'Documentation', href: DOCS_URL },
|
||||||
{ name: 'Blog', href: BLOG_URL },
|
{ name: 'Blog', href: BLOG_URL },
|
||||||
],
|
],
|
||||||
company: [
|
company: [
|
||||||
{ name: 'About', href: '#' },
|
{ name: 'About', href: 'https://wasp-lang.dev' },
|
||||||
{ name: 'Privacy', href: '#' },
|
{ name: 'Privacy', href: '#' },
|
||||||
{ name: 'Terms of Service', href: '#' },
|
{ name: 'Terms of Service', href: '#' },
|
||||||
],
|
],
|
||||||
|
@ -6,6 +6,7 @@ export enum TierIds {
|
|||||||
|
|
||||||
export const DOCS_URL = 'https://docs.opensaas.sh';
|
export const DOCS_URL = 'https://docs.opensaas.sh';
|
||||||
export const BLOG_URL = 'https://docs.opensaas.sh/blog';
|
export const BLOG_URL = 'https://docs.opensaas.sh/blog';
|
||||||
|
export const GITHUB_URL = 'https://github.com/wasp-lang/open-saas';
|
||||||
|
|
||||||
//get this link at https://dashboard.stripe.com/test/settings/billing/portal
|
//get this link at https://dashboard.stripe.com/test/settings/billing/portal
|
||||||
const isDev = process.env.NODE_ENV !== 'production';
|
const isDev = process.env.NODE_ENV !== 'production';
|
||||||
|
@ -63,7 +63,7 @@ export default defineConfig({
|
|||||||
label: 'General',
|
label: 'General',
|
||||||
items: [
|
items: [
|
||||||
{ label: 'Admin Dashboard', link: '/general/admin-dashboard/' },
|
{ label: 'Admin Dashboard', link: '/general/admin-dashboard/' },
|
||||||
{ label: 'User Permissions', link: '/general/user-permissions/' },
|
{ label: 'User Overview', link: '/general/user-overview/' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: User Permissions
|
title: User Overview
|
||||||
---
|
---
|
||||||
|
|
||||||
This reference will help you understand how the user permissions work in this template.
|
This reference will help you understand how the User entity works in this template.
|
||||||
This includes the user roles, subscription tiers and statuses, and how to authorize access to certain pages and components.
|
This includes the user roles, subscription tiers and statuses, and how to authorize access to certain pages and components.
|
||||||
|
|
||||||
## User Entity
|
## User Entity
|
@ -12,9 +12,14 @@ Install Wasp by running this command in your terminal:
|
|||||||
```sh
|
```sh
|
||||||
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
|
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
|
||||||
```
|
```
|
||||||
Also install the [Wasp extension for VSCode](https://marketplace.visualstudio.com/items?itemName=wasp-lang.wasp) to get the best DX (syntax highlighting, code scaffolding, autocomplete, etc.)
|
|
||||||
|
|
||||||
### Clone the repo
|
:::tip
|
||||||
|
Make sure to install the Wasp VSCode extension to get the best DX, e.g. syntax highlighting, code scaffolding, autocomplete, etc:
|
||||||
|
|
||||||
|
🐝 [Wasp VSCode Extension](https://marketplace.visualstudio.com/items?itemName=wasp-lang.wasp) 🧑💻
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Clone the OpenSaaS repo
|
||||||
|
|
||||||
Clone this repo by running this command in your terminal:
|
Clone this repo by running this command in your terminal:
|
||||||
```sh
|
```sh
|
||||||
@ -37,11 +42,10 @@ wasp start db
|
|||||||
```
|
```
|
||||||
This will start and connect your app to a Postgres database for you. No need to do anything else! 🤯
|
This will start and connect your app to a Postgres database for you. No need to do anything else! 🤯
|
||||||
|
|
||||||
Then, in a new terminal window/tab, run:
|
Whenever you make any changes to your schema, you can migrate them with:
|
||||||
```sh
|
```sh
|
||||||
wasp db migrate-dev
|
wasp db migrate-dev
|
||||||
```
|
```
|
||||||
This will run the migrations for you and create the tables in your DB.
|
|
||||||
|
|
||||||
If you want to see or manage your DB via Prisma's DB Studio GUI, run:
|
If you want to see or manage your DB via Prisma's DB Studio GUI, run:
|
||||||
```sh
|
```sh
|
||||||
@ -57,11 +61,11 @@ This will install all dependencies and start the client and server for you :)
|
|||||||
|
|
||||||
Go to `localhost:3000` in your browser to view it (your NodeJS server will be running on port `3001`)
|
Go to `localhost:3000` in your browser to view it (your NodeJS server will be running on port `3001`)
|
||||||
|
|
||||||
### Further info
|
### More Help/Further Info
|
||||||
Check the files for comments containing specific instructions.
|
|
||||||
|
|
||||||
For more info on Wasp as a full-stack React, NodeJS, Prisma framework, check out the [Wasp docs](https://wasp-lang.dev/docs/).
|
For more info on Wasp as a full-stack React, NodeJS, Prisma framework, check out the [Wasp docs](https://wasp-lang.dev/docs/).
|
||||||
|
|
||||||
|
If you get stuck or need help, join the [Wasp Discord](https://discord.gg/aCamt5wCpS).
|
||||||
|
|
||||||
#### Run Blog and Docs
|
#### Run Blog and Docs
|
||||||
|
|
||||||
This SaaS app comes with a docs and blog section built with the [Starlight template on top of the Astro](https://starlight.astro.build) framework. You can use this as a starting point for your own blog and documentation, if necessary.
|
This SaaS app comes with a docs and blog section built with the [Starlight template on top of the Astro](https://starlight.astro.build) framework. You can use this as a starting point for your own blog and documentation, if necessary.
|
||||||
|
@ -17,7 +17,7 @@ At the root of our project, you will see two folders:
|
|||||||
|
|
||||||
`app` contains the Wasp project files, which is your full-stack React + NodeJS + Prisma app along with a Wasp config file, which will be explained in more detail below.
|
`app` contains the Wasp project files, which is your full-stack React + NodeJS + Prisma app along with a Wasp config file, which will be explained in more detail below.
|
||||||
|
|
||||||
`blog` contains the Astro Starlight template for the blog and documentation section.
|
`blog` contains the [Astro Starlight template](https://starlight.astro.build/) for the blog and documentation section.
|
||||||
|
|
||||||
Let's check out what's in the `app` folder in more detail:
|
Let's check out what's in the `app` folder in more detail:
|
||||||
```sh
|
```sh
|
||||||
@ -35,9 +35,11 @@ Let's check out what's in the `app` folder in more detail:
|
|||||||
|
|
||||||
### The Wasp Config file
|
### The Wasp Config file
|
||||||
|
|
||||||
The `main.wasp` file is where you define your app structure.
|
This template at its core is a Wasp template, where [Wasp](https://wasp-lang.dev) is a full-stack web app framework that let’s you write your app in React, NodeJS, and Prisma and will manage the "boilerplatey" work for you, allowing you to just take care of the fun stuff!
|
||||||
|
|
||||||
In this template, we've already defined a number of things in the config file for you, including:
|
[Wasp's secret sauce](https://wasp-lang.dev/docs) is its use of a config file (`main.wasp`) and compiler which takes your code and outputs the client app, server app and deployment code for you.
|
||||||
|
|
||||||
|
In this template, we've already defined a number of things in the `main.wasp` config file, including:
|
||||||
|
|
||||||
- Auth
|
- Auth
|
||||||
- Routes and Pages
|
- Routes and Pages
|
||||||
@ -46,7 +48,7 @@ In this template, we've already defined a number of things in the config file fo
|
|||||||
- Background Jobs
|
- Background Jobs
|
||||||
- Email Sending
|
- Email Sending
|
||||||
|
|
||||||
By defining these things in the config file, Wasp continuously handles the boilerplate necessary with putting all these features together. You just need to focus on the business logic of your app!
|
By defining these things in the config file, Wasp continuously handles the boilerplate necessary with putting all these features together. You just need to focus on the business logic of your app.
|
||||||
|
|
||||||
Wasp abstracts away some things that you would normally be used to doing during development, so don't be surprised if you don't see some of the things you're used to seeing.
|
Wasp abstracts away some things that you would normally be used to doing during development, so don't be surprised if you don't see some of the things you're used to seeing.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user