Compare commits
10 Commits
fcb8071cec
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 916fefb10b | |||
| 785ffac993 | |||
|
|
460c859ab3 | ||
|
|
0abc4ec624 | ||
|
|
786665e84e | ||
|
|
d3391c21a6 | ||
|
|
0219723a07 | ||
|
|
e7d1f35777 | ||
|
|
463cf7f194 | ||
|
|
9daea204e5 |
@@ -1,5 +1,5 @@
|
||||
SUPABASE_URL=https://xxxxxxxxxxxxxxxxxxxx.supabase.co
|
||||
SUPABASE_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxx.xxxxxx-xxxxx
|
||||
SUPABASE_URL=http://localhost:8843
|
||||
SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
|
||||
|
||||
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
STRIPE_ENDPOINT_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ node_modules
|
||||
.env
|
||||
dist
|
||||
junk
|
||||
.DS_Store
|
||||
|
||||
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,5 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
## Version 1.4.3
|
||||
### Update All Dependencies to latest
|
||||
- openai (3.3.0 -> 4.28.0)
|
||||
- superjson (1.12.2 -> 2.2.1)
|
||||
- node types (18.15.11 -> 20.11.19)
|
||||
- stripe lib (11.12.0 -> 14.17.0)
|
||||
- stripe api version (2022-11-15 -> 2023-10-16)
|
||||
- cookie consent (2.9.2 -> 3.0.0)
|
||||
- daisyui (2.51.5 -> 4.7.2)
|
||||
- vitest (0.33.0 -> 1.3.0)
|
||||
- other minor and patch versions
|
||||
|
||||
|
||||
## Version 1.4.2
|
||||
- Added Favicons and web manifest and referenced in nuxt.config (I used https://favicon.io/favicon-converter/ to generate the icon assets, seems to work well)
|
||||
- Added patch folder to hold patch files, should make it easier to update repos based on earlier versions
|
||||
|
||||
10
app.vue
10
app.vue
@@ -1,12 +1,16 @@
|
||||
<template>
|
||||
<div class="flex flex-col min-h-screen bg-base-100">
|
||||
<AppHeader />
|
||||
<!-- <div class="flex flex-col min-h-screen bg-base-100"> -->
|
||||
<div class="flex flex-col min-h-screen bg-gray-800">
|
||||
<Entete />
|
||||
<!-- <AppHeader /> -->
|
||||
|
||||
<div class="flex-grow">
|
||||
<main>
|
||||
<NuxtPage />
|
||||
</main>
|
||||
</div>
|
||||
<AppFooter />
|
||||
<!-- <AppFooter /> -->
|
||||
<PiedPage />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
<span class="px-2">|</span>
|
||||
<NuxtLink to="/privacy">Privacy</NuxtLink>
|
||||
<span class="px-2">|</span>
|
||||
<button type="button" data-cc="c-settings">Cookie settings</button>
|
||||
<NuxtLink to="/contact">Contact Us</NuxtLink>
|
||||
<span class="px-2">|</span>
|
||||
<button type="button" data-cc="show-preferencesModal">Cookie settings</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
98
components/Entete.vue
Normal file
98
components/Entete.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { Dialog, DialogPanel } from '@headlessui/vue';
|
||||
import { Bars3Icon, XMarkIcon } from '@heroicons/vue/24/outline';
|
||||
|
||||
const user = useSupabaseUser();
|
||||
|
||||
const navigation = [
|
||||
{ name: 'Product', href: '#' },
|
||||
{ name: 'Features', href: '#' },
|
||||
{ name: 'Company', href: '#' }
|
||||
];
|
||||
|
||||
const mobileMenuOpen = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="bg-primary">
|
||||
<nav
|
||||
class="mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8"
|
||||
aria-label="Global">
|
||||
<div class="flex flex-1">
|
||||
<div class="hidden lg:flex lg:gap-x-12">
|
||||
<a
|
||||
v-for="item in navigation"
|
||||
:key="item.name"
|
||||
:href="item.href"
|
||||
class="text-sm font-semibold leading-6 text-gray-200 hover:text-white"
|
||||
>{{ item.name }}</a
|
||||
>
|
||||
</div>
|
||||
<div class="flex lg:hidden">
|
||||
<button
|
||||
type="button"
|
||||
class="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-200"
|
||||
@click="mobileMenuOpen = true">
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<Bars3Icon class="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="-m-1.5 p-1.5">
|
||||
<span class="sr-only">Your Company</span>
|
||||
<img
|
||||
class="h-8 w-auto"
|
||||
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
|
||||
alt="" />
|
||||
</a>
|
||||
<div class="flex flex-1 justify-end">
|
||||
<a href="#" class="text-sm font-semibold leading-6 text-gray-200"
|
||||
>Log in <span aria-hidden="true">→</span></a
|
||||
>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<Dialog
|
||||
class="lg:hidden"
|
||||
@close="mobileMenuOpen = false"
|
||||
:open="mobileMenuOpen">
|
||||
<div class="fixed inset-0 z-10" />
|
||||
<DialogPanel
|
||||
class="fixed inset-y-0 left-0 z-10 w-full overflow-y-auto bg-white px-6 py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex flex-1">
|
||||
<button
|
||||
type="button"
|
||||
class="-m-2.5 rounded-md p-2.5 text-gray-700"
|
||||
@click="mobileMenuOpen = false">
|
||||
<span class="sr-only">Close menu</span>
|
||||
<XMarkIcon class="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<a href="#" class="-m-1.5 p-1.5">
|
||||
<span class="sr-only">Your Company</span>
|
||||
<img
|
||||
class="h-8 w-auto"
|
||||
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
|
||||
alt="" />
|
||||
</a>
|
||||
<div class="flex flex-1 justify-end">
|
||||
<a href="#" class="text-sm font-semibold leading-6 text-gray-200"
|
||||
>Log in <span aria-hidden="true">→</span></a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6 space-y-2">
|
||||
<a
|
||||
v-for="item in navigation"
|
||||
:key="item.name"
|
||||
:href="item.href"
|
||||
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
|
||||
>{{ item.name }}</a
|
||||
>
|
||||
</div>
|
||||
</DialogPanel>
|
||||
</Dialog>
|
||||
</header>
|
||||
</template>
|
||||
119
components/Entrepreneur.vue
Normal file
119
components/Entrepreneur.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="bg-gray-900 py-24 sm:py-32">
|
||||
<div class="mx-auto max-w-7xl px-6 text-center lg:px-8">
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<h2 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">
|
||||
Meet our team
|
||||
</h2>
|
||||
<p class="mt-4 text-lg leading-8 text-gray-400">
|
||||
We’re a dynamic group of individuals who are passionate about what we
|
||||
do.
|
||||
</p>
|
||||
</div>
|
||||
<ul
|
||||
role="list"
|
||||
class="mx-auto mt-20 grid max-w-2xl grid-cols-1 gap-6 sm:grid-cols-2 lg:mx-0 lg:max-w-none lg:grid-cols-3 lg:gap-8">
|
||||
<li
|
||||
v-for="person in people"
|
||||
:key="person.name"
|
||||
class="rounded-2xl bg-gray-800 px-8 py-10">
|
||||
<img
|
||||
class="mx-auto h-48 w-48 rounded-full md:h-56 md:w-56"
|
||||
:src="person.imageUrl"
|
||||
alt="" />
|
||||
<h3
|
||||
class="mt-6 text-base font-semibold leading-7 tracking-tight text-white">
|
||||
{{ person.name }}
|
||||
</h3>
|
||||
<p class="text-sm leading-6 text-gray-400">{{ person.role }}</p>
|
||||
<ul role="list" class="mt-6 flex justify-center gap-x-6">
|
||||
<li>
|
||||
<a :href="person.xUrl" class="text-gray-400 hover:text-gray-300">
|
||||
<span class="sr-only">X</span>
|
||||
<svg
|
||||
class="h-5 w-5"
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20">
|
||||
<path
|
||||
d="M11.4678 8.77491L17.2961 2H15.915L10.8543 7.88256L6.81232 2H2.15039L8.26263 10.8955L2.15039 18H3.53159L8.87581 11.7878L13.1444 18H17.8063L11.4675 8.77491H11.4678ZM9.57608 10.9738L8.95678 10.0881L4.02925 3.03974H6.15068L10.1273 8.72795L10.7466 9.61374L15.9156 17.0075H13.7942L9.57608 10.9742V10.9738Z" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
:href="person.linkedinUrl"
|
||||
class="text-gray-400 hover:text-gray-300">
|
||||
<span class="sr-only">LinkedIn</span>
|
||||
<svg
|
||||
class="h-5 w-5"
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M16.338 16.338H13.67V12.16c0-.995-.017-2.277-1.387-2.277-1.39 0-1.601 1.086-1.601 2.207v4.248H8.014v-8.59h2.559v1.174h.037c.356-.675 1.227-1.387 2.526-1.387 2.703 0 3.203 1.778 3.203 4.092v4.711zM5.005 6.575a1.548 1.548 0 11-.003-3.096 1.548 1.548 0 01.003 3.096zm-1.337 9.763H6.34v-8.59H3.667v8.59zM17.668 1H2.328C1.595 1 1 1.581 1 2.298v15.403C1 18.418 1.595 19 2.328 19h15.34c.734 0 1.332-.582 1.332-1.299V2.298C19 1.581 18.402 1 17.668 1z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const people = [
|
||||
{
|
||||
name: 'Leonard Krasner',
|
||||
role: 'Senior Designer',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80',
|
||||
xUrl: '#',
|
||||
linkedinUrl: '#'
|
||||
},
|
||||
{
|
||||
name: 'Leonard Krasner',
|
||||
role: 'Senior Designer',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80',
|
||||
xUrl: '#',
|
||||
linkedinUrl: '#'
|
||||
},
|
||||
{
|
||||
name: 'Leonard Krasner',
|
||||
role: 'Senior Designer',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80',
|
||||
xUrl: '#',
|
||||
linkedinUrl: '#'
|
||||
},
|
||||
{
|
||||
name: 'Leonard Krasner',
|
||||
role: 'Senior Designer',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80',
|
||||
xUrl: '#',
|
||||
linkedinUrl: '#'
|
||||
},
|
||||
{
|
||||
name: 'Leonard Krasner',
|
||||
role: 'Senior Designer',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80',
|
||||
xUrl: '#',
|
||||
linkedinUrl: '#'
|
||||
},
|
||||
{
|
||||
name: 'Leonard Krasner',
|
||||
role: 'Senior Designer',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80',
|
||||
xUrl: '#',
|
||||
linkedinUrl: '#'
|
||||
}
|
||||
// More people...
|
||||
];
|
||||
</script>
|
||||
53
components/Highlight.vue
Normal file
53
components/Highlight.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="bg-gray">
|
||||
<main class="isolate">
|
||||
<!-- Hero section -->
|
||||
<div
|
||||
class="relative isolate -z-10 overflow-hidden bg-gradient-to-b from-indigo-100/20 pt-14">
|
||||
<!-- <div
|
||||
class="absolute inset-y-0 right-1/2 -z-10 -mr-96 w-[200%] origin-top-right skew-x-[-30deg] bg-white shadow-xl shadow-indigo-600/10 ring-1 ring-indigo-50 sm:-mr-80 lg:-mr-96"
|
||||
aria-hidden="true" /> -->
|
||||
<div
|
||||
class="absolute inset-y-0 right-1/2 -z-10 -mr-96 w-[200%] origin-top-right skew-x-[-30deg] bg-gray-900 shadow-xl shadow-indigo-600/10 ring-1 ring-indigo-50 sm:-mr-80 lg:-mr-96"
|
||||
aria-hidden="true" />
|
||||
<div class="mx-auto max-w-7xl px-6 py-32 sm:py-40 lg:px-8">
|
||||
<div
|
||||
class="mx-auto max-w-2xl lg:mx-0 lg:grid lg:max-w-none lg:grid-cols-2 lg:gap-x-16 lg:gap-y-6 xl:grid-cols-1 xl:grid-rows-1 xl:gap-x-8">
|
||||
<h1
|
||||
class="max-w-2xl text-4xl font-bold tracking-tight text-gray-100 sm:text-6xl lg:col-span-2 xl:col-auto">
|
||||
We’re a passionate group of people working from around the world
|
||||
to build the future of ecommerce.
|
||||
</h1>
|
||||
<div class="mt-6 max-w-xl lg:mt-0 xl:col-end-1 xl:row-start-1">
|
||||
<p class="text-lg leading-8 text-gray-400">
|
||||
Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui
|
||||
lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat
|
||||
fugiat aliqua. Anim aute id magna aliqua ad ad non deserunt
|
||||
sunt. Qui irure qui lorem cupidatat commodo.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<video
|
||||
class="mt-10 aspect-[6/5] w-full max-w-lg rounded-2xl object-cover sm:mt-16 lg:mt-0 lg:max-w-none xl:row-span-2 xl:row-end-2 xl:mt-36"
|
||||
controls>
|
||||
<source
|
||||
src="https://docs.material-tailwind.com/demo.mp4"
|
||||
type="video/mp4" />
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="absolute inset-x-0 bottom-0 -z-10 h-24 bg-gradient-to-t from-grey-100 sm:h-32" />
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineComponent, h, ref } from 'vue';
|
||||
import { Dialog, DialogPanel } from '@headlessui/vue';
|
||||
import { Bars3Icon, XMarkIcon } from '@heroicons/vue/24/outline';
|
||||
|
||||
const mobileMenuOpen = ref(false);
|
||||
</script>
|
||||
226
components/PiedPage.vue
Normal file
226
components/PiedPage.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div class="bg-gray-900">
|
||||
<!-- Footer -->
|
||||
<footer class="mt-32 sm:mt-40" aria-labelledby="footer-heading">
|
||||
<h2 id="footer-heading" class="sr-only">Footer</h2>
|
||||
<div class="mx-auto max-w-7xl px-6 pb-8 lg:px-8">
|
||||
<div
|
||||
class="border-t border-gray-900/10 pt-20 xl:grid xl:grid-cols-3 xl:gap-8">
|
||||
<div class="grid grid-cols-2 gap-8 xl:col-span-2">
|
||||
<div class="md:grid md:grid-cols-2 md:gap-8">
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold leading-6 text-white">
|
||||
Solutions
|
||||
</h3>
|
||||
<ul role="list" class="mt-6 space-y-4">
|
||||
<li
|
||||
v-for="item in footerNavigation.solutions"
|
||||
:key="item.name">
|
||||
<a
|
||||
:href="item.href"
|
||||
class="text-sm leading-6 text-gray-400 hover:text-white"
|
||||
>{{ item.name }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mt-10 md:mt-0">
|
||||
<h3 class="text-sm font-semibold leading-6 text-white">
|
||||
Support
|
||||
</h3>
|
||||
<ul role="list" class="mt-6 space-y-4">
|
||||
<li v-for="item in footerNavigation.support" :key="item.name">
|
||||
<a
|
||||
:href="item.href"
|
||||
class="text-sm leading-6 text-gray-400 hover:text-white"
|
||||
>{{ item.name }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md:grid md:grid-cols-2 md:gap-8">
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold leading-6 text-white">
|
||||
Company
|
||||
</h3>
|
||||
<ul role="list" class="mt-6 space-y-4">
|
||||
<li v-for="item in footerNavigation.company" :key="item.name">
|
||||
<a
|
||||
:href="item.href"
|
||||
class="text-sm leading-6 text-gray-400 hover:text-white"
|
||||
>{{ item.name }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mt-10 md:mt-0">
|
||||
<h3 class="text-sm font-semibold leading-6 text-white">
|
||||
Legal
|
||||
</h3>
|
||||
<ul role="list" class="mt-6 space-y-4">
|
||||
<li v-for="item in footerNavigation.legal" :key="item.name">
|
||||
<a
|
||||
:href="item.href"
|
||||
class="text-sm leading-6 text-gray-400 hover:text-white"
|
||||
>{{ item.name }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-10 xl:mt-0">
|
||||
<h3 class="text-sm font-semibold leading-6 text-gray-900">
|
||||
Subscribe to our newsletter
|
||||
</h3>
|
||||
<p class="mt-2 text-sm leading-6 text-gray-600">
|
||||
The latest news, articles, and resources, sent to your inbox
|
||||
weekly.
|
||||
</p>
|
||||
<form class="mt-6 sm:flex sm:max-w-md">
|
||||
<label for="email-address" class="sr-only">Email address</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email-address"
|
||||
id="email-address"
|
||||
autocomplete="email"
|
||||
:required="inputrequired"
|
||||
class="w-full min-w-0 appearance-none rounded-md border-0 bg-white px-3 py-1.5 text-base text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:w-64 sm:text-sm sm:leading-6 xl:w-full"
|
||||
placeholder="Enter your email" />
|
||||
<div class="mt-4 sm:ml-4 sm:mt-0 sm:flex-shrink-0">
|
||||
<button
|
||||
type="submit"
|
||||
class="flex w-full items-center justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
|
||||
Subscribe
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mt-16 border-t border-gray-900/10 pt-8 sm:mt-20 md:flex md:items-center md:justify-between lg:mt-24">
|
||||
<div class="flex space-x-6 md:order-2">
|
||||
<a
|
||||
v-for="item in footerNavigation.social"
|
||||
:key="item.name"
|
||||
:href="item.href"
|
||||
class="text-gray-200 hover:text-white">
|
||||
<span class="sr-only">{{ item.name }}</span>
|
||||
<component :is="item.icon" class="h-6 w-6" aria-hidden="true" />
|
||||
</a>
|
||||
</div>
|
||||
<p class="mt-8 text-xs leading-5 text-gray-500 md:order-1 md:mt-0">
|
||||
© 2020 Your Company, Inc. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent, h, ref } from 'vue';
|
||||
import { Dialog, DialogPanel } from '@headlessui/vue';
|
||||
import { Bars3Icon, XMarkIcon } from '@heroicons/vue/24/outline';
|
||||
|
||||
const inputrequired = ref(false);
|
||||
const footerNavigation = {
|
||||
solutions: [
|
||||
{ name: 'Marketing', href: '#' },
|
||||
{ name: 'Analytics', href: '#' },
|
||||
{ name: 'Commerce', href: '#' },
|
||||
{ name: 'Insights', href: '#' }
|
||||
],
|
||||
support: [
|
||||
{ name: 'Pricing', href: '#' },
|
||||
{ name: 'Documentation', href: '#' },
|
||||
{ name: 'Guides', href: '#' },
|
||||
{ name: 'API Status', href: '#' }
|
||||
],
|
||||
company: [
|
||||
{ name: 'About', href: '#' },
|
||||
{ name: 'Blog', href: '#' },
|
||||
{ name: 'Jobs', href: '#' },
|
||||
{ name: 'Press', href: '#' },
|
||||
{ name: 'Partners', href: '#' }
|
||||
],
|
||||
legal: [
|
||||
{ name: 'Claim', href: '#' },
|
||||
{ name: 'Privacy', href: '#' },
|
||||
{ name: 'Terms', href: '#' }
|
||||
],
|
||||
social: [
|
||||
{
|
||||
name: 'Facebook',
|
||||
href: '#',
|
||||
icon: defineComponent({
|
||||
render: () =>
|
||||
h('svg', { fill: 'currentColor', viewBox: '0 0 24 24' }, [
|
||||
h('path', {
|
||||
'fill-rule': 'evenodd',
|
||||
d: 'M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z',
|
||||
'clip-rule': 'evenodd'
|
||||
})
|
||||
])
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'Instagram',
|
||||
href: '#',
|
||||
icon: defineComponent({
|
||||
render: () =>
|
||||
h('svg', { fill: 'currentColor', viewBox: '0 0 24 24' }, [
|
||||
h('path', {
|
||||
'fill-rule': 'evenodd',
|
||||
d: 'M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z',
|
||||
'clip-rule': 'evenodd'
|
||||
})
|
||||
])
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
href: '#',
|
||||
icon: defineComponent({
|
||||
render: () =>
|
||||
h('svg', { fill: 'currentColor', viewBox: '0 0 24 24' }, [
|
||||
h('path', {
|
||||
d: 'M13.6823 10.6218L20.2391 3H18.6854L12.9921 9.61788L8.44486 3H3.2002L10.0765 13.0074L3.2002 21H4.75404L10.7663 14.0113L15.5685 21H20.8131L13.6819 10.6218H13.6823ZM11.5541 13.0956L10.8574 12.0991L5.31391 4.16971H7.70053L12.1742 10.5689L12.8709 11.5655L18.6861 19.8835H16.2995L11.5541 13.096V13.0956Z'
|
||||
})
|
||||
])
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'GitHub',
|
||||
href: '#',
|
||||
icon: defineComponent({
|
||||
render: () =>
|
||||
h('svg', { fill: 'currentColor', viewBox: '0 0 24 24' }, [
|
||||
h('path', {
|
||||
'fill-rule': 'evenodd',
|
||||
d: 'M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z',
|
||||
'clip-rule': 'evenodd'
|
||||
})
|
||||
])
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'YouTube',
|
||||
href: '#',
|
||||
icon: defineComponent({
|
||||
render: () =>
|
||||
h('svg', { fill: 'currentColor', viewBox: '0 0 24 24' }, [
|
||||
h('path', {
|
||||
'fill-rule': 'evenodd',
|
||||
d: 'M19.812 5.418c.861.23 1.538.907 1.768 1.768C21.998 8.746 22 12 22 12s0 3.255-.418 4.814a2.504 2.504 0 0 1-1.768 1.768c-1.56.419-7.814.419-7.814.419s-6.255 0-7.814-.419a2.505 2.505 0 0 1-1.768-1.768C2 15.255 2 12 2 12s0-3.255.417-4.814a2.507 2.507 0 0 1 1.768-1.768C5.744 5 11.998 5 11.998 5s6.255 0 7.814.418ZM15.194 12 10 15V9l5.194 3Z',
|
||||
'clip-rule': 'evenodd'
|
||||
})
|
||||
])
|
||||
})
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const mobileMenuOpen = ref(false);
|
||||
</script>
|
||||
@@ -101,13 +101,13 @@ export namespace AccountService {
|
||||
account_id: number,
|
||||
membership_id: number
|
||||
): Promise<MembershipWithAccount> {
|
||||
const membership = prisma_client.membership.findFirstOrThrow({
|
||||
const membership = await prisma_client.membership.findFirstOrThrow({
|
||||
where: {
|
||||
id: membership_id
|
||||
}
|
||||
});
|
||||
|
||||
if ((await membership).account_id != account_id) {
|
||||
if (membership.account_id != account_id) {
|
||||
throw new Error(`Membership does not belong to current account`);
|
||||
}
|
||||
|
||||
@@ -126,13 +126,13 @@ export namespace AccountService {
|
||||
account_id: number,
|
||||
membership_id: number
|
||||
): Promise<MembershipWithAccount> {
|
||||
const membership = prisma_client.membership.findFirstOrThrow({
|
||||
const membership = await prisma_client.membership.findFirstOrThrow({
|
||||
where: {
|
||||
id: membership_id
|
||||
}
|
||||
});
|
||||
|
||||
if ((await membership).account_id != account_id) {
|
||||
if (membership.account_id != account_id) {
|
||||
throw new Error(`Membership does not belong to current account`);
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ export namespace AccountService {
|
||||
length: 10,
|
||||
numbers: true
|
||||
});
|
||||
return prisma_client.account.update({
|
||||
return await prisma_client.account.update({
|
||||
where: { id: account_id },
|
||||
data: { join_password }
|
||||
});
|
||||
|
||||
@@ -4,10 +4,6 @@ import { AccountLimitError } from './errors';
|
||||
import { AccountService } from './account.service';
|
||||
|
||||
export namespace NotesService {
|
||||
export async function getAllNotes() {
|
||||
return prisma_client.note.findMany();
|
||||
}
|
||||
|
||||
export async function getNoteById(id: number) {
|
||||
return prisma_client.note.findUniqueOrThrow({ where: { id } });
|
||||
}
|
||||
|
||||
12132
package-lock.json
generated
12132
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "supanuxt-saas",
|
||||
"version": "1.4.2",
|
||||
"version": "1.4.3",
|
||||
"author": {
|
||||
"name": "Michael Dausmann",
|
||||
"email": "mdausmann@gmail.com",
|
||||
@@ -9,7 +9,7 @@
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"prisma": {
|
||||
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
|
||||
"seed": "pnpx tsx prisma/seed.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
@@ -20,31 +20,33 @@
|
||||
"test": "vitest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@heroicons/vue": "^2.1.3",
|
||||
"@nuxt/test-utils": "^3.11.0",
|
||||
"@nuxtjs/supabase": "^1.1.6",
|
||||
"@nuxtjs/tailwindcss": "^6.11.4",
|
||||
"@prisma/client": "^5.9.1",
|
||||
"@prisma/client": "^5.13.0",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@types/node": "^18.19.17",
|
||||
"@types/node": "^20.12.7",
|
||||
"nuxt": "^3.10.2",
|
||||
"nuxt-headlessui": "^1.2.0",
|
||||
"nuxt-icon": "^0.6.8",
|
||||
"prisma": "^5.9.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3",
|
||||
"typescript": "^5.4.5",
|
||||
"vitest": "^1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pinia/nuxt": "^0.5.1",
|
||||
"@trpc/client": "^10.45.1",
|
||||
"@trpc/server": "^10.45.1",
|
||||
"daisyui": "^2.52.0",
|
||||
"daisyui": "^4.7.2",
|
||||
"generate-password-ts": "^1.6.5",
|
||||
"openai": "^4.28.0",
|
||||
"pinia": "^2.1.7",
|
||||
"stripe": "^11.18.0",
|
||||
"superjson": "^1.13.3",
|
||||
"stripe": "^14.17.0",
|
||||
"superjson": "^2.2.1",
|
||||
"trpc-nuxt": "^0.10.19",
|
||||
"vanilla-cookieconsent": "^2.9.2",
|
||||
"vanilla-cookieconsent": "^3.0.0",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"overrides": {
|
||||
|
||||
10
pages/contact.vue
Normal file
10
pages/contact.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<div class="prose lg:prose-xl m-5">
|
||||
<h1>Contact Us</h1>
|
||||
|
||||
<p>
|
||||
Contact SupaNuxt SaaS on <a href="https://github.com/JavascriptMick/supanuxt-saas">github</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
230
pages/index.vue
230
pages/index.vue
@@ -6,233 +6,13 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container mx-auto m-5">
|
||||
<!-- Hero section -->
|
||||
<section class="bg-gray-100 py-20">
|
||||
<div class="container mx-auto">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-16">
|
||||
<div class="m-5">
|
||||
<h1 class="text-5xl font-bold mb-4">Build Your Next SaaS Faster</h1>
|
||||
<p class="text-gray-700 text-lg mb-8">
|
||||
With SupaNuxt SaaS, you can easily get started building your next
|
||||
web application. Our pre-configured tech stack and industry
|
||||
leading features make it easy to get up and running in no time.
|
||||
Look! this guy is working so fast, his hands are just a blur.. you
|
||||
could be this fast.
|
||||
</p>
|
||||
<NuxtLink
|
||||
to="/signup"
|
||||
class="inline-block py-3 px-6 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
||||
>Get Started</NuxtLink
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<img
|
||||
src="~/assets/images/supanuxt_logo_200.png"
|
||||
alt="SupaNuxt SaaS Logo" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Hightlight Section -->
|
||||
<Highlight />
|
||||
|
||||
<section class="py-12">
|
||||
<div class="container px-4 mx-auto">
|
||||
<div
|
||||
class="flex flex-col md:flex-row items-center justify-center md:justify-between mb-8">
|
||||
<h2 class="text-3xl font-bold mb-4 md:mb-0">Tech Stack</h2>
|
||||
</div>
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-full">
|
||||
<ul class="grid grid-cols-3 gap-10 list-none">
|
||||
<li>
|
||||
<Icon name="skill-icons:nuxtjs-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Nuxt 3</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
The Progressive Vue.js Framework
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="skill-icons:supabase-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Supabase</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Auth including OAuth + Postgresql instance
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon
|
||||
name="skill-icons:postgresql-dark"
|
||||
class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">PostgreSQL</h3>
|
||||
<p class="mt-2 text-base text-gray-500">Relational Database</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos:prisma" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Prisma</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Schema management + Strongly typed client
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="simple-icons:trpc" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">TRPC</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Server/Client communication with Strong types, SSR compatible
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="skill-icons:vuejs-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Pinia</h3>
|
||||
<p class="mt-2 text-base text-gray-500">State Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos:stripe" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Stripe</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Payments including Webhook integration
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon
|
||||
name="skill-icons:tailwindcss-dark"
|
||||
class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Tailwind</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
A utility-first CSS framework
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="skill-icons:vuejs-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Vue.js</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
The Progressive JavaScript Framework
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos:openai-icon" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">OpenAI</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
AI Completions including Note generation from prompt
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-col md:flex-row items-center justify-center md:justify-between mb-8">
|
||||
<h2 class="text-3xl font-bold mb-4 md:mb-0">Features</h2>
|
||||
</div>
|
||||
<!-- User Management (text left) -->
|
||||
<div class="flex flex-col md:flex-row-reverse items-center mb-16">
|
||||
<div class="md:w-1/2 md:ml-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_user_management.jpeg"
|
||||
alt="User Management"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:ml-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">User Management</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes robust user management features, including
|
||||
authentication with social login (oauth) or email/password,
|
||||
management of user roles and permissions, and multi-user/team
|
||||
accounts that permit multiple users to share plan features
|
||||
including a team administration facility and user roles within
|
||||
team. This is a great feature for businesses or community groups
|
||||
who want to share the cost of the plan.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- DB Schema (text right)-->
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-1/2 md:mr-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_db_schema_management.jpeg"
|
||||
alt="DB Schema Management"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:mr-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">DB Schema Management</h3>
|
||||
<p class="mb-4">
|
||||
We use Prisma for schema management to make sure you can easily
|
||||
manage and keep track of your database schema. We also utilise
|
||||
Prisma based strong types which, with some help from TRPC,
|
||||
penetrate the entire stack all the way to the web front end. This
|
||||
ensures that you can move fast with your feature development,
|
||||
alter schema and have those type changes instantly available and
|
||||
validated everywhere.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Config (text left) -->
|
||||
<div class="flex flex-col md:flex-row-reverse items-center mb-16">
|
||||
<div class="md:w-1/2 md:ml-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_config_environment.jpeg"
|
||||
alt="Config and Environment"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:ml-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">Config and Environment</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes an approach to config and environment
|
||||
management that enables customisation and management of api keys.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- State Management (text right)-->
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-1/2 md:mr-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_state_management.jpeg"
|
||||
alt="State Management"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:mr-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">State Management</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes multi modal state management that supports
|
||||
both Single Page Application (SPA) pages such as dashboards and
|
||||
Server Side Rendered (SSR) style pages for public content that are
|
||||
crawlable by Search engines like google and facilitate excellent
|
||||
Search Engine Optimisation (SEO).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Stripe (text left) -->
|
||||
<div class="flex flex-col md:flex-row-reverse items-center mb-16">
|
||||
<div class="md:w-1/2 md:ml-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_stripe_integration.jpeg"
|
||||
alt="Stripe Integration"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:ml-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">Stripe Integration</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes Stripe integration for subscription
|
||||
payments including Subscription based support for multi pricing
|
||||
and multiple plans.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Tailwind (text right)-->
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-1/2 md:mr-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_style_system.jpeg"
|
||||
alt="Style System"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:mr-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">Style System</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes Tailwind integration for site styling
|
||||
including a themable UI components with daisyUI
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Entrepreneur Section -->
|
||||
<Entrepreneur />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
238
pages/indexsave.vue
Normal file
238
pages/indexsave.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<script setup lang="ts">
|
||||
const user = useSupabaseUser();
|
||||
watchEffect(() => {
|
||||
if (user.value) {
|
||||
navigateTo('/dashboard', { replace: true });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="container mx-auto m-5">
|
||||
<!-- Hero section -->
|
||||
<section class="bg-gray-100 py-20">
|
||||
<div class="container mx-auto">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-16">
|
||||
<div class="m-5">
|
||||
<h1 class="text-5xl font-bold mb-4">Build Your Next SaaS Faster</h1>
|
||||
<p class="text-gray-700 text-lg mb-8">
|
||||
With SupaNuxt SaaS, you can easily get started building your next
|
||||
web application. Our pre-configured tech stack and industry
|
||||
leading features make it easy to get up and running in no time.
|
||||
Look! this guy is working so fast, his hands are just a blur.. you
|
||||
could be this fast.
|
||||
</p>
|
||||
<NuxtLink
|
||||
to="/signup"
|
||||
class="inline-block py-3 px-6 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
||||
>Get Started</NuxtLink
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<img
|
||||
src="~/assets/images/supanuxt_logo_200.png"
|
||||
alt="SupaNuxt SaaS Logo" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="py-12">
|
||||
<div class="container px-4 mx-auto">
|
||||
<div
|
||||
class="flex flex-col md:flex-row items-center justify-center md:justify-between mb-8">
|
||||
<h2 class="text-3xl font-bold mb-4 md:mb-0">Tech Stack</h2>
|
||||
</div>
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-full">
|
||||
<ul class="grid grid-cols-3 gap-10 list-none">
|
||||
<li>
|
||||
<Icon name="skill-icons:nuxtjs-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Nuxt 3</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
The Progressive Vue.js Framework
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="skill-icons:supabase-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Supabase</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Auth including OAuth + Postgresql instance
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon
|
||||
name="skill-icons:postgresql-dark"
|
||||
class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">PostgreSQL</h3>
|
||||
<p class="mt-2 text-base text-gray-500">Relational Database</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos:prisma" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Prisma</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Schema management + Strongly typed client
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="simple-icons:trpc" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">TRPC</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Server/Client communication with Strong types, SSR compatible
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="skill-icons:vuejs-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Pinia</h3>
|
||||
<p class="mt-2 text-base text-gray-500">State Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos:stripe" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Stripe</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
Payments including Webhook integration
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon
|
||||
name="skill-icons:tailwindcss-dark"
|
||||
class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Tailwind</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
A utility-first CSS framework
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="skill-icons:vuejs-dark" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">Vue.js</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
The Progressive JavaScript Framework
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos:openai-icon" class="h-12 w-12 mb-2" />
|
||||
<h3 class="text-xl font-medium text-gray-900">OpenAI</h3>
|
||||
<p class="mt-2 text-base text-gray-500">
|
||||
AI Completions including Note generation from prompt
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-col md:flex-row items-center justify-center md:justify-between mb-8">
|
||||
<h2 class="text-3xl font-bold mb-4 md:mb-0">Features</h2>
|
||||
</div>
|
||||
<!-- User Management (text left) -->
|
||||
<div class="flex flex-col md:flex-row-reverse items-center mb-16">
|
||||
<div class="md:w-1/2 md:ml-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_user_management.jpeg"
|
||||
alt="User Management"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:ml-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">User Management</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes robust user management features, including
|
||||
authentication with social login (oauth) or email/password,
|
||||
management of user roles and permissions, and multi-user/team
|
||||
accounts that permit multiple users to share plan features
|
||||
including a team administration facility and user roles within
|
||||
team. This is a great feature for businesses or community groups
|
||||
who want to share the cost of the plan.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- DB Schema (text right)-->
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-1/2 md:mr-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_db_schema_management.jpeg"
|
||||
alt="DB Schema Management"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:mr-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">DB Schema Management</h3>
|
||||
<p class="mb-4">
|
||||
We use Prisma for schema management to make sure you can easily
|
||||
manage and keep track of your database schema. We also utilise
|
||||
Prisma based strong types which, with some help from TRPC,
|
||||
penetrate the entire stack all the way to the web front end. This
|
||||
ensures that you can move fast with your feature development,
|
||||
alter schema and have those type changes instantly available and
|
||||
validated everywhere.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Config (text left) -->
|
||||
<div class="flex flex-col md:flex-row-reverse items-center mb-16">
|
||||
<div class="md:w-1/2 md:ml-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_config_environment.jpeg"
|
||||
alt="Config and Environment"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:ml-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">Config and Environment</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes an approach to config and environment
|
||||
management that enables customisation and management of api keys.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- State Management (text right)-->
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-1/2 md:mr-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_state_management.jpeg"
|
||||
alt="State Management"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:mr-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">State Management</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes multi modal state management that supports
|
||||
both Single Page Application (SPA) pages such as dashboards and
|
||||
Server Side Rendered (SSR) style pages for public content that are
|
||||
crawlable by Search engines like google and facilitate excellent
|
||||
Search Engine Optimisation (SEO).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Stripe (text left) -->
|
||||
<div class="flex flex-col md:flex-row-reverse items-center mb-16">
|
||||
<div class="md:w-1/2 md:ml-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_stripe_integration.jpeg"
|
||||
alt="Stripe Integration"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:ml-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">Stripe Integration</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes Stripe integration for subscription
|
||||
payments including Subscription based support for multi pricing
|
||||
and multiple plans.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Tailwind (text right)-->
|
||||
<div class="flex flex-col md:flex-row items-center mb-16">
|
||||
<div class="md:w-1/2 md:mr-8 mb-8 md:mb-0">
|
||||
<img
|
||||
src="~/assets/images/landing_style_system.jpeg"
|
||||
alt="Style System"
|
||||
class="w-full rounded-lg shadow-lg mb-4 md:mb-0 md:mr-4" />
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h3 class="text-xl font-bold mb-4">Style System</h3>
|
||||
<p class="mb-4">
|
||||
SupaNuxt SaaS includes Tailwind integration for site styling
|
||||
including a themable UI components with daisyUI
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { AccountWithMembers } from '~~/lib/services/service.types';
|
||||
import { type AccountWithMembers } from '~~/lib/services/service.types';
|
||||
|
||||
const route = useRoute();
|
||||
const { join_password }: { join_password?: string } = route.params;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import Stripe from 'stripe';
|
||||
const config = useRuntimeConfig();
|
||||
const stripe = new Stripe(config.stripeSecretKey, {
|
||||
apiVersion: '2022-11-15'
|
||||
apiVersion: '2023-10-16'
|
||||
});
|
||||
const route = useRoute();
|
||||
let customer: Stripe.Response<Stripe.Customer | Stripe.DeletedCustomer>;
|
||||
|
||||
@@ -1,131 +1,65 @@
|
||||
import 'vanilla-cookieconsent/dist/cookieconsent.css';
|
||||
import 'vanilla-cookieconsent/src/cookieconsent.js';
|
||||
import * as CookieConsent from 'vanilla-cookieconsent';
|
||||
|
||||
export default defineNuxtPlugin(nuxtApp => {
|
||||
// @ts-ignore
|
||||
const cookieConsent = window.initCookieConsent();
|
||||
/**
|
||||
* All config. options available here:
|
||||
* https://cookieconsent.orestbida.com/reference/configuration-reference.html
|
||||
*/
|
||||
CookieConsent.run({
|
||||
categories: {
|
||||
necessary: {
|
||||
enabled: true, // this category is enabled by default
|
||||
readOnly: true // this category cannot be disabled
|
||||
},
|
||||
analytics: {}
|
||||
},
|
||||
|
||||
cookieConsent.run({
|
||||
current_lang: 'en',
|
||||
autoclear_cookies: true, // default: false
|
||||
page_scripts: true, // default: false
|
||||
|
||||
// mode: 'opt-in' // default: 'opt-in'; value: 'opt-in' or 'opt-out'
|
||||
// delay: 0, // default: 0
|
||||
// auto_language: '', // default: null; could also be 'browser' or 'document'
|
||||
// autorun: true, // default: true
|
||||
// force_consent: false, // default: false
|
||||
// hide_from_bots: true, // default: true
|
||||
// remove_cookie_tables: false // default: false
|
||||
// cookie_name: 'cc_cookie', // default: 'cc_cookie'
|
||||
// cookie_expiration: 182, // default: 182 (days)
|
||||
// cookie_necessary_only_expiration: 182 // default: disabled
|
||||
// cookie_domain: location.hostname, // default: current domain
|
||||
// cookie_path: '/', // default: root
|
||||
// cookie_same_site: 'Lax', // default: 'Lax'
|
||||
// use_rfc_cookie: false, // default: false
|
||||
// revision: 0, // default: 0
|
||||
|
||||
// onFirstAction: function(user_preferences, cookie){
|
||||
// // callback triggered only once on the first accept/reject action
|
||||
// },
|
||||
|
||||
// onAccept: function (cookie) {
|
||||
// // callback triggered on the first accept/reject action, and after each page load
|
||||
// },
|
||||
|
||||
// onChange: function (cookie, changed_categories) {
|
||||
// // callback triggered when user changes preferences after consent has already been given
|
||||
// },
|
||||
|
||||
languages: {
|
||||
language: {
|
||||
default: 'en',
|
||||
translations: {
|
||||
en: {
|
||||
consent_modal: {
|
||||
title: 'We use cookies!',
|
||||
consentModal: {
|
||||
title: 'We use cookies',
|
||||
description: 'Cookie modal description',
|
||||
acceptAllBtn: 'Accept all',
|
||||
acceptNecessaryBtn: 'Reject all',
|
||||
showPreferencesBtn: 'Manage Individual preferences'
|
||||
},
|
||||
preferencesModal: {
|
||||
title: 'Manage cookie preferences',
|
||||
acceptAllBtn: 'Accept all',
|
||||
acceptNecessaryBtn: 'Reject all',
|
||||
savePreferencesBtn: 'Accept current selection',
|
||||
closeIconLabel: 'Close modal',
|
||||
sections: [
|
||||
{
|
||||
title: 'Somebody said ... cookies?',
|
||||
description: 'I want one!'
|
||||
},
|
||||
{
|
||||
title: 'Strictly Necessary cookies',
|
||||
description:
|
||||
'Hi, this website uses essential cookies to ensure its proper operation and tracking cookies to understand how you interact with it. The latter will be set only after consent. <button type="button" data-cc="c-settings" class="cc-link">Let me choose</button>',
|
||||
primary_btn: {
|
||||
text: 'Accept all',
|
||||
role: 'accept_all' // 'accept_selected' or 'accept_all'
|
||||
'These cookies are essential for the proper functioning of the website and cannot be disabled.',
|
||||
|
||||
//this field will generate a toggle linked to the 'necessary' category
|
||||
linkedCategory: 'necessary'
|
||||
},
|
||||
secondary_btn: {
|
||||
text: 'Reject all',
|
||||
role: 'accept_necessary' // 'settings' or 'accept_necessary'
|
||||
}
|
||||
},
|
||||
settings_modal: {
|
||||
title: 'Cookie preferences',
|
||||
save_settings_btn: 'Save settings',
|
||||
accept_all_btn: 'Accept all',
|
||||
reject_all_btn: 'Reject all',
|
||||
close_btn_label: 'Close',
|
||||
// cookie_table_caption: 'Cookie list',
|
||||
cookie_table_headers: [
|
||||
{ col1: 'Name' },
|
||||
{ col2: 'Domain' },
|
||||
{ col3: 'Expiration' },
|
||||
{ col4: 'Description' }
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
title: 'Cookie usage 📢',
|
||||
title: 'Performance and Analytics',
|
||||
description:
|
||||
'I use cookies to ensure the basic functionalities of the website and to enhance your online experience. You can choose for each category to opt-in/out whenever you want. For more details relative to cookies and other sensitive data, please read the full <a href="#" class="cc-link">privacy policy</a>.'
|
||||
},
|
||||
{
|
||||
title: 'Strictly necessary cookies',
|
||||
description:
|
||||
'These cookies are essential for the proper functioning of my website. Without these cookies, the website would not work properly',
|
||||
toggle: {
|
||||
value: 'necessary',
|
||||
enabled: true,
|
||||
readonly: true // cookie categories with readonly=true are all treated as "necessary cookies"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Performance and Analytics cookies',
|
||||
description:
|
||||
'These cookies allow the website to remember the choices you have made in the past',
|
||||
toggle: {
|
||||
value: 'analytics', // your cookie category
|
||||
enabled: false,
|
||||
readonly: false
|
||||
},
|
||||
cookie_table: [
|
||||
// list of all expected cookies
|
||||
{
|
||||
col1: '^_ga', // match all cookies starting with "_ga"
|
||||
col2: 'google.com',
|
||||
col3: '2 years',
|
||||
col4: 'description ...',
|
||||
is_regex: true
|
||||
},
|
||||
{
|
||||
col1: '_gid',
|
||||
col2: 'google.com',
|
||||
col3: '1 day',
|
||||
col4: 'description ...'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Advertisement and Targeting cookies',
|
||||
description:
|
||||
'These cookies collect information about how you use the website, which pages you visited and which links you clicked on. All of the data is anonymized and cannot be used to identify you',
|
||||
toggle: {
|
||||
value: 'targeting',
|
||||
enabled: false,
|
||||
readonly: false
|
||||
}
|
||||
'These cookies collect information about how you use our website. All of the data is anonymized and cannot be used to identify you.',
|
||||
linkedCategory: 'analytics'
|
||||
},
|
||||
{
|
||||
title: 'More information',
|
||||
description:
|
||||
'For any queries in relation to our policy on cookies and your choices, please <a class="cc-link" href="#yourcontactpage">contact us</a>.'
|
||||
'For any queries in relation to my policy on cookies and your choices, please <a href="/contact">contact us</a>'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const freeTrial = await prisma.plan.upsert({
|
||||
where: { name: 'Free Trial' },
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { EventHandler, EventHandlerRequest, H3Event, eventHandler } from 'h3';
|
||||
import {
|
||||
type EventHandler,
|
||||
type EventHandlerRequest,
|
||||
H3Event,
|
||||
eventHandler
|
||||
} from 'h3';
|
||||
|
||||
export const defineProtectedEventHandler = <T extends EventHandlerRequest>(
|
||||
handler: EventHandler<T>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AccountService } from '~~/lib/services/account.service';
|
||||
import type { AccountWithMembers } from '~~/lib/services/service.types';
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
const stripe = new Stripe(config.stripeSecretKey, { apiVersion: '2022-11-15' });
|
||||
const stripe = new Stripe(config.stripeSecretKey, { apiVersion: '2023-10-16' });
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
const body = await readBody(event);
|
||||
|
||||
@@ -2,7 +2,7 @@ import Stripe from 'stripe';
|
||||
import { AccountService } from '~~/lib/services/account.service';
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
const stripe = new Stripe(config.stripeSecretKey, { apiVersion: '2022-11-15' });
|
||||
const stripe = new Stripe(config.stripeSecretKey, { apiVersion: '2023-10-16' });
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
const stripeSignature = getRequestHeader(event, 'stripe-signature');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { inferAsyncReturnType } from '@trpc/server';
|
||||
import type { inferAsyncReturnType } from '@trpc/server';
|
||||
import { H3Event } from 'h3';
|
||||
|
||||
export async function createContext(event: H3Event) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { setCookie } from 'h3';
|
||||
import {
|
||||
router,
|
||||
adminProcedure,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @see https://trpc.io/docs/v10/procedures
|
||||
*/
|
||||
import { initTRPC, TRPCError } from '@trpc/server';
|
||||
import { Context } from './context';
|
||||
import type { Context } from './context';
|
||||
import { ACCOUNT_ACCESS } from '~~/prisma/account-access-enum';
|
||||
import superjson from 'superjson';
|
||||
import { AccountLimitError } from '~~/lib/services/errors';
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { ACCOUNT_ACCESS } from '~~/prisma/account-access-enum';
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref, computed } from 'vue';
|
||||
import { FullDBUser, MembershipWithUser } from '~~/lib/services/service.types';
|
||||
import type {
|
||||
FullDBUser,
|
||||
MembershipWithUser
|
||||
} from '~~/lib/services/service.types';
|
||||
|
||||
/*
|
||||
This store manages User and Account state including the ActiveAccount
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Note } from '.prisma/client';
|
||||
import type { Note } from '.prisma/client';
|
||||
import { defineStore, storeToRefs } from 'pinia';
|
||||
import { Ref } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
export const useNotesStore = defineStore('notes', () => {
|
||||
const accountStore = useAccountStore();
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
export default {
|
||||
plugins: [require("@tailwindcss/typography"), require("daisyui")],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#1a202c',
|
||||
secondary: '#2d3748'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [require('@tailwindcss/typography'), require('daisyui')],
|
||||
daisyui: {
|
||||
styled: true,
|
||||
themes: ["acid", "night"],
|
||||
themes: ['acid', 'night'],
|
||||
base: true,
|
||||
utils: true,
|
||||
logs: true,
|
||||
rtl: false,
|
||||
prefix: "",
|
||||
darkTheme: "night",
|
||||
},
|
||||
prefix: '',
|
||||
darkTheme: 'night'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
"extends": "./.nuxt/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user