Merge branch 'release'

This commit is contained in:
Mihovil Ilakovac 2024-10-04 17:44:12 +02:00
commit 8207e6d981
22 changed files with 384 additions and 1 deletions

View File

@ -136,7 +136,7 @@ The folder that I have opened is
\\wsl.localhost\Ubuntu\home\boris\Projects \\wsl.localhost\Ubuntu\home\boris\Projects
``` ```
That is the “Projects” folder inside my home folder in WSL. There are 2 ways for us to know that we are in WSL: The top bar and in the bottom left corner of VS Code. In both places, we have WSL: Ubuntu written, as is shown on screenshots. That is the “Projects” folder inside my home folder in WSL. There are 2 ways for us to know that we are in WSL: The top bar and in the bottom left corner of VS Code. In both places, we should see the text _WSL: Ubuntu_, as shown on screenshots.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzhu765415sravn3vypu.png) ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzhu765415sravn3vypu.png)

View File

@ -0,0 +1,130 @@
---
title: "Built in Days, Acquired for $20K: The NuloApp Story"
authors: [milica]
image: /img/nuloapp/wasp-friends.webp
tags: [webdev, wasp, saas, builders, showcase]
---
import ReactPlayer from 'react-player'
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
Meet [**Kaloyan Stoyanov**](https://www.linkedin.com/in/kaloyan-stoyanov-466a54196/), a tech lead who turned his passion project into a full-fledged SaaS product, and sold it within days of launching it.
A year before officially launching [NuloApp](https://nuloapp.com/), Kaloyan realized that many creators in the "faceless YouTube channels" niche were using tools like [Opus.pro](http://opus.pro/) to generate short-form content from long-form videos, but these tools were very expensive. Without yet earning revenue from YouTube or TikTok, Kaloyan decided to take matters into his own hands, building his own tool in just a month.
Initially, his tool automatically created and uploaded shorts, but after some time, when his channel didnt pick up, he stopped the project. Fast forward to a year later, and YouTube's algorithm brought similar content back into his feed, reigniting his passion. This time, Kaloyan took it further by transforming his tool into a SaaS product: NuloApp.
### **The Problem NuloApp Solves**
NuloApp is an AI tool designed to make video content creation simpler by converting long-form videos into short clips that have the highest chance to capture audiences attention. It resizes content from horizontal (landscape) to vertical (portrait) for platforms like YouTube Shorts, Instagram Reels, and TikTok, helping creators push content faster.
<ReactPlayer playing controls muted={true} url='/img/nuloapp/vid.mp4' />
### **Tech Stack Overview**
- **Framework:** Wasp
- **Payment integration:** Stripe
- **Other tools:** OpenCV, FastAPI, Meta's llama, OpenAI's Whisper, LangChain
- **Database:** PostgreSQL
### **Programatically Editing Videos**
The real genius behind NuloApp is the way that Kaloyan combined a number of tools to programatically edit the longer form videos and podcasts, into short, engaging clips for social media.
First of all, [OpenCV](https://opencv.org/), an open-source computer vision library, was used as the main editing tool. This is how NuloApp is able to get the correct aspect ratio for smartphone content, and do other cool things like centering the video on the speaker so that they aren't out of frame when the aspect ratio is changed.
In order to programtically get the correct clips to extract, AI tools like Meta's [llama-3-70b LLM](https://github.com/meta-llama/llama3) and OpenAI's [Whisper](https://github.com/openai/whisper) were also used. Whisper allowed for fast speech-to-text transcription, which could then be passed on the llama in order to find segments worth extracting.
Putting these tools together and accessible via a standalone API was the final step in this process. But this really clever combination of tools was just one part of puzzle. The next problem to solve was how to deliver it all as a SaaS app that users could pay for?
### **Why Wasp?**
When Kaloyan decided to relaunch his tool as a SaaS product, he didnt have time to spare. He needed a framework that would allow him to build and deploy quickly. Thats where **Wasp** came in.
“I was looking for a quick and easy-to-use boilerplate with most SaaS app features already pre-built so I could deploy faster,” says Kaloyan. [Wasps SaaS boilerplate starter](https://opensaas.sh/), with well-structured documentation, alongside its responsive Discord support, made it the ideal choice.
### **The Impact of Wasp on Development**
Kaloyan was particularly impressed with how Wasp simplified complex tasks that would normally take much longer to implement. From setting up Google logins and dark mode switches to creating hourly jobs, the development process was smoother than expected. “Everything—from enabling Google logins to creating hourly jobs I badly needed—was way too easy to set up.”.
### **Auth and Stripe Integration Made Easy**
One of Kaloyans least favorite tasks as a developer is building out authentication systems, and he found that even implementing third-party libraries could be frustrating. Fortunately, Wasps boilerplate made the process of setting up authentication and pre-configuring Stripe for payments seamless.
Here's what `wasp.config` file looks like, through which you can define full-stack auth in a Wasp app.
```jsx
app myApp {
wasp: {
version: "^0.14.0"
},
title: "My App",
auth: {
// 1. Specify the User entity
userEntity: User,
methods: {
// 2. Enable Github Auth
gitHub: {},
email: {
// 3. Specify the email from field
fromField: {
name: "My App Postman",
email: "hello@itsme.com"
},
// 4. Specify the email verification and password reset options
emailVerification: {
clientRoute: EmailVerificationRoute, //this route/page should be created
},
passwordReset: {
clientRoute: PasswordResetRoute, //this route/page should be created
},
// Add an emailSender -- Dummy just logs to console for dev purposes
// but there are a ton of supported providers :D
emailSender: {
provider: Dummy,
},
},
},
onAuthFailedRedirectTo: "/login"
},
}
```
And here's a 1 minute demo:
<div className='flex justify-center'>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/Qiro77q-ulI?si=ALZU_PdeKRlq_-Ac" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div>
<br/>
Additionally, the framework's job scheduling features helped Kaloyan avoid the headache of configuring cron jobs on Docker containers.
### **Fast Acquisition: From Launch to Sale in 24 Hours**
Upon launching NuloApp, Kaloyan listed the product on [Acquire](http://acquire.com/) with the primary goal of gathering feedback from potential buyers about what features or metrics they value most in a SaaS product. To his surprise, within the first day of listing, he received multiple offers. After a brief meeting with one interested buyer, they quickly agreed on a $20k deal, validating the product's value and market potential.
![NuloApp Homepage](/img/nuloapp/app.png)
### **Advice for Builders Considering Wasp**
If you're considering Wasp, Kaloyans advice is clear: Wasp is easy to get started with and flexible enough to build what you need without adding unnecessary complexity. For Kaloyan, Wasp was ideal because it handled the boilerplate while still giving him the freedom to customize as required. "The documentation is also solid, which definitely helps when you're moving quickly.”
### Next Steps
If youd like to follow in Kaloyans footsteps, this is how to get started with the boilerplate he used.
Open your terminal and install Wasp:
``` shell
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
```
From there you only need to run:
``` shell
wasp new -t saas
```
Thats it, youre one step closer to building your first SaaS!
Feel free to join our [Discord](https://discord.gg/rzdnErX) to connect with other builders and get support from the Wasp community. See you!

View File

@ -0,0 +1,71 @@
---
title: "Why Your SaaS Emails Arent Being Delivered and How to Fix This Issue"
authors: [milica]
image: /img/email/email-cover.jpg
tags: [webdev, tips, emails]
---
import ReactPlayer from 'react-player'
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import ImgWithCaption from './components/ImgWithCaption'
If youve just built your SaaS web app and deployed it on a production server, you might be running into email deliverability issues. Transactional or marketing emails might not be landing in your users' inboxes. Dont panic! This is a pretty common problem, especially for apps that run on newly registered domains.
We have seen a lot of [Wasp](https://wasp-lang.dev/) users facing similar challenges, thinking their toolkit was to blame. In our Discord community, we regularly help users whove just launched their first app with Wasp, and we've seen this issue pop up frequently. The bad news: your users and their email servers pulled a Gandalf move on you. The good news: no worries, this is something you can fix!
![Gandalf saying you shall not pass](https://media2.giphy.com/media/WpD30tFjzosDn7amXq/giphy.gif?cid=7941fdc68jh5kd0zboo37lcp48knhd8bewokjgz7kc9juwov&ep=v1_gifs_search&rid=giphy.gif&ct=g)
## 1. **Build up your domain reputation**
A new domain is often flagged as suspicious by email providers, causing your emails to land in spam or not be delivered at all. Googles filtering is really heavy, especially if youre trying to reach people with business addresses (user@theircompany.com). Even the basic signup confirmations have a high chance of bouncing when youre sending them from a freshly registered domain.
To improve your domain reputation, do the following:
- **Use a custom domain for your emails**: If youre still using a generic email service like Gmail, switch to a custom domain. This makes you more trustworthy and looks more professional.
- **Warm-up your domain**: You need to do this before you start onboarding your users. Any type of sudden bursts of emails from a new domain can be flagged as spam. For example, if you decide to launch on Product Hunt, youll get a spike in signups which increases the amount of sent emails. Its possible that this spike triggers the alarms, and people stop receiving your emails. [There are numerous tools out there](https://letmegooglethat.com/?q=Email+warmup+tools) that can help you with this process. Dont skip this step, its mandatory.
- **Keep the sending volume consistent**: Regular email sending patterns are seen as trustworthy. Inconsistent or high-volume bursts from a new domain can trigger spam filters.
## 2. **Authenticate your domain**
Authentication adds a layer of security to your emails, proving to email providers that youre a legitimate sender and not the next prince of spam from the land of Spamlia. Here are the key records you need to set up with your DNS provider:
- **SPF**: This allows email servers to verify that emails sent from your domain are really coming from you.
- **DKIM**: This attaches a digital signature to your emails that enables email servers to confirm the email wasnt tampered with in transit.
- **DMARC**: this one helps you control how your email domain handles unauthenticated emails.
Read more about these records and how to add them to your DNS servers [here](https://www.cloudflare.com/en-gb/learning/email-security/dmarc-dkim-spf/).
![A girl saying and you're going to fix it](https://media4.giphy.com/media/ZdrDsXfFz1ZRhZQpLZ/giphy.gif?cid=7941fdc6zjvsa5atns4qklo6odlg3zjir92fy34lvymyfmx1&ep=v1_gifs_search&rid=giphy.gif&ct=g)
## 3. **Use professional email sending tools**
Instead of sending emails directly from your own server, consider using a third-party email service that specializes in this area. Tools like **SendGrid** or **Mailgun** have built-in features to help ensure your emails make it to the inbox. Wasp helps you to [add them to your stack](https://wasp-lang.dev/docs/advanced/email) with minimal configuration needed on your end.
They monitor and improve your domain reputation, manage bounces, and handle email authentication out-of-the-box. Wed recommend you to offload sending emails to them, so that you can focus on the core aspects of your business.
## 4. **Monitor your deliverability**
Its important to keep an eye on how your emails are performing. Look for key metrics like bounce rate, open rate, and spam complaints. Most email sending services provide insights into your email deliverability, allowing you to make adjustments before your reputation gets damaged.
- **Bounce rate**: High bounce rates suggest youre sending to invalid or outdated email addresses. Regularly clean your list to avoid this. If more than 3% of your emails bounce, your domain can get blocked by your email provider.
- **Spam complaints**: High spam reports and complaints can also lead to email providers blocking your domain. If users are marking your emails as spam, reconsider the content and frequency of your emails. Also, please dont buy email lists off of Internet, those will do you more harm than good.
![meme saying are you looking into buying email lists](/img/email/meme.jpg)
## 5. **Create high-quality content**
What you write matters too. Emails are poorly written are more likely to be marked as spam.
- **Use a clear subject line**: Avoid clickbait or overly promotional language. Keep your subject lines clear and aligned with the content of your email. If your subject line is off, your email can directly land in spam or in the promotional inbox.
- **Personalize your emails**: Address your users by their name and offer content that is relevant to their needs. Personalized emails tend to have higher open and click-through rates.
- **Avoid spammy-looking keywords**: Words like “FREE,” “LIMITED OFFER,” and excessive use of exclamation marks can trigger spam filters. Keep your language professional and to the point. DONT USE CAPS LOCK EVERYWHERE!
## Inbox access granted
![you can do this gif](https://media1.giphy.com/media/ACJuukdjBl65FwUFzT/giphy.gif?cid=7941fdc6u3cbcux0bo255tvvoxfhq9cuep0g28vcdk1cbryt&ep=v1_gifs_search&rid=giphy.gif&ct=g)
We know that email delivery issues are frustrating, but they are solvable. Start small - implement one or two changes. First, authenticate your domain and then [set up professional email sending tools](https://wasp-lang.dev/docs/advanced/email#using-the-mailgun-provider), Wasp supports some out of the box.
You can monitor the performance over time, and improve your approach with every batch of emails. Its not about getting everything perfect from the start, but about making the right decisions before you start onboarding your users.

View File

@ -0,0 +1,130 @@
---
title: 'Wasp Launch Week #7: Modern Times ⚙️'
authors: [matijasos]
image: /img/lw7/lw7-banner.png
tags: [launch-week, update]
---
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import InBlogCta from './components/InBlogCta';
import WaspIntro from './_wasp-intro.md';
import ImgWithCaption from './components/ImgWithCaption'
<ImgWithCaption
alt="Launch Week 7 is here"
source="img/lw7/lw7-banner.png"
/>
Hey Wasp lovers 🐝 💛,
as Charlie Chaplin would say - I'll be back! So are we - despite the vacation season and all the sunshine that kept distracting us, we kept ourselves busy. We closed the curtains and cranked those A/C's on, and brought to you a whole new release of Wasp, as fresh as a cucumber!
<ImgWithCaption
alt="Charnold"
source="img/lw7/charnold.png"
caption="You see? I wasn't lying!"
/>
As always, well present the fruits of our labour in a community call that will happen in exactly three days, on Monday, October 7th, 10.30 AM EDT / 4.30 PM CET! To reserve your spot, [visit the event in our Discord server](https://discord.gg/K4dEEvyR?event=1291419619948626040) and mark yourself as interested.
<ImgWithCaption
alt="Join the kick-off event"
source="img/lw7/lw7-discord-event.png"
/>
Do it now, so we have the whole weekend of looking forward to seeing you there! 🐝
With a mandatory admin stuff and a bad joke (Charnold mashup above ICYMI) out of the way, lets get to the “meaty” stuff and see what is this launch really all about!
## Why Modern Times?
Wasp couldnt do its magic as well as it does without all the brilliant parts of the stack it uses under the hood - Prisma, React Router, TanStack Query, and many others. That means we also have to keep track of how these tools evolve and update their versions in Wasp (aka make them modern) - and that's exactly what we did for this release!
This launch week isn't so much about introducing new, flashy features (although we have some, and yes, it's TypeScript SDK, and yes, you can try it out), but rather about making what we have better and more up-to-date.
Let's take a look together at the nice things that v0.15 brings us:
## #1: Level up ⬆️: Prisma 5, React Router 6, Express.js
<ImgWithCaption
alt="level up"
source="img/lw7/level-up.webp"
caption="What you will feel like wielding the latest Wasp release (just imagine the flames are yellow)."
/>
As mentioned above, we got to keep up with the trends! Here's what's new:
- **Upgraded Prisma to v5** - no major interface changes, but brings a lot of performance improvements which also make Wasp faster by default 🏎️
- **React Router is now at v6** - v6 has been around for a while (you can see the the main changes from v5 [here](https://blog.saeloun.com/2021/12/02/new-features-in-react-router-6/)) and it made the code even more compact and elegant.
- **We cleaned up and bumped a lot of other dependencies** - including Express.js on which we base Wasps API layer and our type-safe RPC.
## #2: TS SDK early preview 🤩 - give it a spin and let us know what you think!
During the last launch week we gave you a hint of how the TS SDK for Wasp might look like, and the response we got from you was amazing! This is probably a single feature that has caused the most excitement in the community so far.
<ImgWithCaption
alt="excited"
source="img/lw7/excited.webp"
caption="Yep, that's right"
/>
Motived by your response, we decided to keep the train going. We took your feedback and implemented the first version of TS SDK for you to actually try out!
<ImgWithCaption
alt="ts sdk code example"
source="img/lw7/ts-sdk.png"
/>
This is still work in progress but things seem to be coming together quite nicely! We'd also be grateful to hear your thoughts on it once it is out.
## #3: MAGE now uses GPT-4o 🧠 🤖
<ImgWithCaption
alt="upgrading me"
source="img/lw7/upgrading-me.webp"
/>
Your favorite [AI-powered SaaS boilerplate starter, MAGE](https://usemage.ai/), has also received an update and now uses OpenAIs latest model, GPT-4o.
A quick refresher - we released MAGE about a year ago as a convenient way to kickstart your SaaS powered by React, Node.js, Tailwind, and of course Wasp. Its been used to generate over 40,000 codebases and is still used daily by developers.
Read [more about it](https://dev.to/wasp/gpt-web-app-generator-let-ai-create-a-full-stack-react-nodejs-codebase-based-on-your-description-2g39) or go ahead and [give it a spin](https://usemage.ai/) - it's 100% free!
## #4: Hackathon incoming 💻 🍪
Its been a while since we had our last hackathon, and we decided its about time we fixed that! For this one, we prepared a special treat for you - I dont want to spoil too much in advance, but lets just say its going to do something with cookie banners and how to make them as annoying as possible (whoops 🫢).
Heres a quick teaser for yall:
<ImgWithCaption
alt="hackathon incoming"
source="img/lw7/cookie-wheel.gif"
caption="This one at least gives you a chance"
/>
## #5: See you there! 🫵
<ImgWithCaption
alt="Not if I see you first"
source="img/lw7/see-you-first.gif"
/>
And thats a wrap! I hope this got you excited as much as it got me and that you will join us for the Launch Week kick-off event on Monday! Youll get to hear about all these features and more first hand from working on them, ask questions, and learn more about whats coming next.
Register for the event [here](https://discord.gg/K4dEEvyR?event=1291419619948626040), and make sure to mark yourself as interested 👇
<ImgWithCaption
alt="Join the kick-off event"
source="img/lw7/lw7-discord-event.png"
/>
## Stay in the loop
<ImgWithCaption
alt="dont leave"
source="img/lw7/dont-go.gif"
/>
Every day, we'll update this page with the latest announcement of the day - to stay in the loop, [follow us on Twitter/X](https://twitter.com/WaspLang) and [join our Discord](https://discord.gg/rzdnErX) - see you there!

51
web/package-lock.json generated
View File

@ -26,6 +26,7 @@
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-feather": "^2.0.10", "react-feather": "^2.0.10",
"react-modal": "^3.14.3", "react-modal": "^3.14.3",
"react-player": "^2.16.0",
"react-tooltip": "^4.5.1", "react-tooltip": "^4.5.1",
"react-transition-group": "^4.4.5", "react-transition-group": "^4.4.5",
"tailwindcss": "^3.2.4" "tailwindcss": "^3.2.4"
@ -7856,6 +7857,12 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/load-script": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
"integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==",
"license": "MIT"
},
"node_modules/loader-runner": { "node_modules/loader-runner": {
"version": "4.3.0", "version": "4.3.0",
"license": "MIT", "license": "MIT",
@ -8225,6 +8232,12 @@
"node": ">= 4.0.0" "node": ">= 4.0.0"
} }
}, },
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
"license": "MIT"
},
"node_modules/merge-descriptors": { "node_modules/merge-descriptors": {
"version": "1.0.1", "version": "1.0.1",
"license": "MIT" "license": "MIT"
@ -10648,6 +10661,22 @@
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18"
} }
}, },
"node_modules/react-player": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.16.0.tgz",
"integrity": "sha512-mAIPHfioD7yxO0GNYVFD1303QFtI3lyyQZLY229UEAp/a10cSW+hPcakg0Keq8uWJxT2OiT/4Gt+Lc9bD6bJmQ==",
"license": "MIT",
"dependencies": {
"deepmerge": "^4.0.0",
"load-script": "^1.0.0",
"memoize-one": "^5.1.1",
"prop-types": "^15.7.2",
"react-fast-compare": "^3.0.1"
},
"peerDependencies": {
"react": ">=16.6.0"
}
},
"node_modules/react-router": { "node_modules/react-router": {
"version": "5.3.4", "version": "5.3.4",
"license": "MIT", "license": "MIT",
@ -19597,6 +19626,11 @@
"import-meta-resolve": "^2.0.0" "import-meta-resolve": "^2.0.0"
} }
}, },
"load-script": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
"integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA=="
},
"loader-runner": { "loader-runner": {
"version": "4.3.0" "version": "4.3.0"
}, },
@ -19853,6 +19887,11 @@
"fs-monkey": "^1.0.3" "fs-monkey": "^1.0.3"
} }
}, },
"memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
"merge-descriptors": { "merge-descriptors": {
"version": "1.0.1" "version": "1.0.1"
}, },
@ -21154,6 +21193,18 @@
"warning": "^4.0.3" "warning": "^4.0.3"
} }
}, },
"react-player": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.16.0.tgz",
"integrity": "sha512-mAIPHfioD7yxO0GNYVFD1303QFtI3lyyQZLY229UEAp/a10cSW+hPcakg0Keq8uWJxT2OiT/4Gt+Lc9bD6bJmQ==",
"requires": {
"deepmerge": "^4.0.0",
"load-script": "^1.0.0",
"memoize-one": "^5.1.1",
"prop-types": "^15.7.2",
"react-fast-compare": "^3.0.1"
}
},
"react-router": { "react-router": {
"version": "5.3.4", "version": "5.3.4",
"requires": { "requires": {

View File

@ -36,6 +36,7 @@
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-feather": "^2.0.10", "react-feather": "^2.0.10",
"react-modal": "^3.14.3", "react-modal": "^3.14.3",
"react-player": "^2.16.0",
"react-tooltip": "^4.5.1", "react-tooltip": "^4.5.1",
"react-transition-group": "^4.4.5", "react-transition-group": "^4.4.5",
"tailwindcss": "^3.2.4" "tailwindcss": "^3.2.4"

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 KiB