<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tashyn Wallace</title>
    <description>The latest articles on DEV Community by Tashyn Wallace (@tashynw).</description>
    <link>https://dev.to/tashynw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F831367%2F7a345d7c-5c81-4fbd-87d7-ae481087af73.png</url>
      <title>DEV Community: Tashyn Wallace</title>
      <link>https://dev.to/tashynw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tashynw"/>
    <language>en</language>
    <item>
      <title>Creating a Custom Styled File Input Component with Chakra UI and React Hook Form</title>
      <dc:creator>Tashyn Wallace</dc:creator>
      <pubDate>Mon, 23 Oct 2023 02:24:49 +0000</pubDate>
      <link>https://dev.to/tashynw/creating-a-custom-styled-file-input-component-with-chakra-ui-and-react-hook-form-14g9</link>
      <guid>https://dev.to/tashynw/creating-a-custom-styled-file-input-component-with-chakra-ui-and-react-hook-form-14g9</guid>
      <description>&lt;p&gt;File uploads are a common feature in web applications, but customizing the look and behavior of a file input can be a challenge. In this tutorial, we'll walk you through creating a custom styled file input component using Chakra UI, React Hook Form, and React Dropzone. This component allows users to drag and drop files, ensuring a seamless and intuitive experience. The best part? It's easily adaptable to fit your specific requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Custom File Input Component&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useCallback, useState } from "react";
import { useDropzone } from "react-dropzone";
import {
  Center,
  useColorModeValue,
  Icon,
  VStack,
  Text,
  HStack,
  Spacer,
} from "@chakra-ui/react";
import { FiUploadCloud } from "react-icons/fi";
import { AiOutlineClose } from "react-icons/ai";
import { FieldError, FieldErrorsImpl, Merge } from "react-hook-form";

type Props = {
  onFileAccepted: any;
  formError: FieldError | Merge&amp;lt;FieldError, FieldErrorsImpl&amp;lt;any&amp;gt;&amp;gt; | undefined;
};

export default function FileUploadInput({ onFileAccepted, formError }: Props) {
  const [selectedFile, setSelectedFile] = useState&amp;lt;File&amp;gt;();
  const onDrop = useCallback(
    (acceptedFiles: any) =&amp;gt; {
      setSelectedFile(acceptedFiles[0]);
      onFileAccepted(acceptedFiles[0]);
    },
    [onFileAccepted, selectedFile]
  );

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: {
      "application/pdf": [`.pdf`],
    },
    maxFiles: 1,
    multiple: false,
  });

  const activeBg = useColorModeValue("red.50", "red.100");
  const borderColor = useColorModeValue(
    isDragActive ? "red.300" : "gray.300",
    isDragActive ? "red.500" : "gray.500"
  );

  return (
    &amp;lt;Center
      p={10}
      cursor={!selectedFile ? "pointer" : "inherit"}
      w="100%"
      bg={isDragActive ? activeBg : "transparent"}
      _hover={{ bg: activeBg }}
      transition="background-color 0.2s ease"
      borderRadius={4}
      border={formError ? "2px" : "1px"}
      borderColor={formError ? "red.500" : borderColor}
      {...(!selectedFile ? getRootProps() : {})}
    &amp;gt;
      {!selectedFile ? (
        &amp;lt;&amp;gt;
          &amp;lt;input {...getInputProps()} /&amp;gt;
          &amp;lt;VStack&amp;gt;
            &amp;lt;Icon as={FiUploadCloud} color="red.600" mr={2} boxSize={6} /&amp;gt;
            &amp;lt;Text&amp;gt;
              {!isDragActive ? (
                &amp;lt;&amp;gt;
                  &amp;lt;Text as="span" fontWeight="semibold" color="pink.600"&amp;gt;
                    Click to upload
                  &amp;lt;/Text&amp;gt;
                  {` `}
                  or drag and drop
                &amp;lt;/&amp;gt;
              ) : (
                `Drop the files here ...`
              )}
            &amp;lt;/Text&amp;gt;
            &amp;lt;Text fontSize="sm"&amp;gt;PDF Only&amp;lt;/Text&amp;gt;
          &amp;lt;/VStack&amp;gt;
        &amp;lt;/&amp;gt;
      ) : (
        &amp;lt;&amp;gt;
          &amp;lt;HStack w="100%" p={5} borderRadius="md" bg="white"&amp;gt;
            &amp;lt;Text&amp;gt;{selectedFile?.name}&amp;lt;/Text&amp;gt;
            &amp;lt;Spacer /&amp;gt;
            &amp;lt;Icon
              as={AiOutlineClose}
              onClick={() =&amp;gt; {
                setSelectedFile(undefined);
                onFileAccepted(undefined);
              }}
              cursor="pointer"
            /&amp;gt;
          &amp;lt;/HStack&amp;gt;
        &amp;lt;/&amp;gt;
      )}
    &amp;lt;/Center&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;FileUploadInput&lt;/strong&gt; component is the heart of this implementation. It utilizes React Dropzone for drag-and-drop functionality and Chakra UI for styling. This component also seamlessly integrates with React Hook Form, providing perfect type safety for your forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File Input in Action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sM9lYhD8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuwgfanqwkr3th9vy5gn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sM9lYhD8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuwgfanqwkr3th9vy5gn.png" alt="Image description" width="437" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DhpbO_Mm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1i30bdcrrcg27owaz0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DhpbO_Mm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1i30bdcrrcg27owaz0m.png" alt="Image description" width="440" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZSTb0iSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zsqo5x4h80ikns0b00m0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZSTb0iSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zsqo5x4h80ikns0b00m0.png" alt="Image description" width="439" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using the Custom Component in Your Form:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Controller } from "react-hook-form";
const {
  register,
  control,
  handleSubmit,
  reset,
  formState: { errors },
} = useForm&amp;lt;ImportDocumentType&amp;gt;({
  resolver: zodResolver(importDocumentSchema),
});

&amp;lt;FormControl isInvalid={Boolean(errors?.documentName)}&amp;gt;
  &amp;lt;FormLabel&amp;gt;Document Name&amp;lt;/FormLabel&amp;gt;
  &amp;lt;Input {...register(`documentName`)} /&amp;gt;
  &amp;lt;FormErrorMessage&amp;gt;
    {errors?.documentName &amp;amp;&amp;amp; errors?.documentName?.message}
  &amp;lt;/FormErrorMessage&amp;gt;
&amp;lt;/FormControl&amp;gt;

&amp;lt;Divider /&amp;gt;

&amp;lt;Controller
  name="file"
  control={control}
  render={({ field: { onChange } }) =&amp;gt; (
    &amp;lt;FileUploadInput
      onFileAccepted={(file: any) =&amp;gt; onChange(file)}
      formError={errors?.file}
    /&amp;gt;
  )}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we demonstrate how to incorporate the custom file input component into your form. It's as simple as using the Controller component from React Hook Form and passing in the FileUploadInput component as the render function. This allows you to manage file uploads with ease.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customization and Adaptability:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the strengths of this approach is its flexibility. You can easily modify the styles, add animations, or tweak functionality to meet your specific project needs. The combination of Chakra UI and React Hook Form provides a powerful foundation for customization.&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Creating Scrollable Horizontal Tabs in Chakra UI: A Quick Fix for Responsive Design</title>
      <dc:creator>Tashyn Wallace</dc:creator>
      <pubDate>Wed, 27 Sep 2023 18:32:06 +0000</pubDate>
      <link>https://dev.to/tashynw/creating-scrollable-horizontal-tabs-in-chakra-ui-a-quick-fix-for-responsive-design-1dbi</link>
      <guid>https://dev.to/tashynw/creating-scrollable-horizontal-tabs-in-chakra-ui-a-quick-fix-for-responsive-design-1dbi</guid>
      <description>&lt;p&gt;When working with Chakra UI, you may have noticed that by default, tabs are not horizontally scrollable. This can pose a challenge, especially when dealing with a high number of tabs, potentially disrupting your responsive designs.&lt;/p&gt;

&lt;p&gt;There's a straightforward solution to this problem that I discovered that involves a little Chakra UI styling. By wrapping the TabList component in a Box and applying some styles, you can easily achieve horizontally scrollable tabs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Box overflow="auto" maxWidth="inherit"&amp;gt;
        &amp;lt;TabList w={[`max-content`, `100%`, `100%`]}&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
          &amp;lt;Tab&amp;gt;Lorem ipsum&amp;lt;/Tab&amp;gt;
        &amp;lt;/TabList&amp;gt;
&amp;lt;/Box&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Screenshot Results (mobile view):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ODP37Qke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ver68nx7b3uds78n9qm3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ODP37Qke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ver68nx7b3uds78n9qm3.png" alt="Image description" width="346" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V-Obg1IH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ves7deal4mydih64wxyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V-Obg1IH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ves7deal4mydih64wxyw.png" alt="Image description" width="397" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's break down what's happening here:&lt;/p&gt;

&lt;p&gt; Component: This is a versatile container component in Chakra UI. We're using it to wrap our TabList. The overflow property is set to auto for responsive behavior. It means that if the content overflows the box, it will be scrollable.&lt;/p&gt;

&lt;p&gt;overflow Property: This controls what happens when content overflows the box. In this case, it's set to auto, allowing the content to be scrollable.&lt;/p&gt;

&lt;p&gt;maxWidth Property: We're setting the maxWidth to "inherit", ensuring that the box takes the maximum width available.&lt;/p&gt;

&lt;p&gt; Component: This is the component responsible for rendering the list of tabs.&lt;/p&gt;

&lt;p&gt;w Property: This is the width property. We're setting it to different values based on screen size using Chakra UI's responsive array.&lt;/p&gt;

&lt;p&gt;Implementing this code will give you the desired effect of horizontally scrollable tabs, making it much easier to manage a large number of tabs on your website.&lt;/p&gt;

&lt;p&gt;Give it a try and see how it elevates your design and user interaction!&lt;/p&gt;

&lt;p&gt;Author&lt;br&gt;
&lt;a href="https://tashyn.com/"&gt;Tashyn Wallace&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
      <category>ui</category>
    </item>
    <item>
      <title>Including Files in Next.js API on Vercel: A Guide for Email Templates</title>
      <dc:creator>Tashyn Wallace</dc:creator>
      <pubDate>Tue, 12 Sep 2023 05:22:09 +0000</pubDate>
      <link>https://dev.to/tashynw/including-files-in-nextjs-api-on-vercel-a-guide-for-email-templates-2ppl</link>
      <guid>https://dev.to/tashynw/including-files-in-nextjs-api-on-vercel-a-guide-for-email-templates-2ppl</guid>
      <description>&lt;p&gt;Quick Guide:&lt;/p&gt;

&lt;p&gt;If you're looking to include static files in your Next.js API on Vercel for use with Nodemailer (or any other purpose) similar to using included files in Netlify's &lt;code&gt;.toml&lt;/code&gt; file, you can achieve this by using a combination of &lt;code&gt;readFileSync&lt;/code&gt; from the fs package and &lt;code&gt;path.resolve&lt;/code&gt; from the path package. For instance, if you have an &lt;code&gt;emails&lt;/code&gt; folder in the &lt;strong&gt;root&lt;/strong&gt; directory, with a subfolder named &lt;code&gt;reset_password_email&lt;/code&gt; containing both an HTML and a TXT file, you can call these files like so:&lt;/p&gt;

&lt;p&gt;Directory example:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9DMcDdGb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfqsc7hspsoytyvxp7us.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9DMcDdGb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfqsc7hspsoytyvxp7us.png" alt="Image description" width="304" height="735"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require("fs");
const path = require("path");

const emailHTML = fs.readFileSync(
  path.resolve("./emails", "reset_password_email", "email.html"),
  "utf-8"
);

const emailTXT = fs.readFileSync(
  path.resolve("./emails", "reset_password_email", "email.txt"),
  "utf-8"
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can use these variables in your code as needed, for example in Handlebars:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const compiledHTML = Handlebars.compile(emailHTML);
const compiledTXT = Handlebars.compile(emailTXT);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;p&gt;When working with Next.js and serverless functions on Vercel, it's important to note that static files in the root directory aren't automatically bundled with your serverless function. To access these files, you'll need to use Node.js's built-in fs module to read them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;path.resolve&lt;/code&gt; is used to generate the correct file path, ensuring it works both locally during development and when deployed on Vercel. It's a more robust way to construct file paths compared to manually concatenating strings.&lt;/p&gt;

&lt;p&gt;By following this approach, you can seamlessly integrate static files like email templates into your Next.js API, enabling you to send personalized emails with ease.&lt;/p&gt;

&lt;p&gt;Remember, always handle sensitive information like email templates with care, ensuring they are securely stored and accessed. With this technique, you have the flexibility to incorporate various types of files into your Next.js projects.&lt;/p&gt;

&lt;p&gt;Author:&lt;br&gt;
&lt;a href="https://tashyn.com/"&gt;Tashyn Wallace&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building Your Own Patient Appointment App: A Comprehensive Tutorial</title>
      <dc:creator>Tashyn Wallace</dc:creator>
      <pubDate>Sun, 10 Sep 2023 05:55:48 +0000</pubDate>
      <link>https://dev.to/tashynw/building-your-own-patient-appointment-app-a-comprehensive-tutorial-bkd</link>
      <guid>https://dev.to/tashynw/building-your-own-patient-appointment-app-a-comprehensive-tutorial-bkd</guid>
      <description>&lt;p&gt;Introduction:&lt;br&gt;
Embark on a journey to create a powerful Patient Appointment App from scratch. In this tutorial, we'll be using Next.js, NextAuth, Chakra UI, React Query, React Hook Form, and MongoDB to craft a seamless booking experience. And the best part? The entire project is open-source and available for free.&lt;/p&gt;

&lt;p&gt;Why This Tutorial?&lt;br&gt;
Learn by doing. Dive deep into the world of Next.js, harnessing the power of Chakra UI for stunning design, and leverage React Query and React Hook Form for smooth data management. By the end of this tutorial, you'll have a fully functional Patient Appointment App at your fingertips.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;p&gt;Seamlessly book appointments with registered doctors.&lt;br&gt;
User authentication and doctor sign-up functionality.&lt;br&gt;
Utilize MongoDB for robust data management.&lt;br&gt;
Getting Started:&lt;br&gt;
Ready to roll up your sleeves? Access the complete source code on the &lt;a href="https://github.com/tashynw/patient-management-app"&gt;GitHub repository&lt;/a&gt;, and find additional resources in the about section.&lt;/p&gt;

&lt;p&gt;Exploring the App:&lt;br&gt;
See the Patient Appointment App in action by visiting the &lt;a href="https://patient-appointment-app.netlify.app/"&gt;live demo&lt;/a&gt;. Test out the features, from booking appointments to managing your doctor profile.&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;br&gt;
Building a Patient Appointment App has never been more accessible. With this tutorial, you not only acquire valuable technical skills but also have a fully functional app as a result. Embrace the freedom of open-source development and create your own appointment booking platform today!&lt;/p&gt;

&lt;p&gt;Images:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4bl1W2r7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vyasupcsqr9m53nxhwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4bl1W2r7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vyasupcsqr9m53nxhwl.png" alt="Image description" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Aq7Ov3cf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6b45h3yo0k286js28b7l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Aq7Ov3cf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6b45h3yo0k286js28b7l.png" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y8Y3O_oZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uf8osc6eifyjhq85vyw3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y8Y3O_oZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uf8osc6eifyjhq85vyw3.png" alt="Image description" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oz7YfOtT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7j8x9sp00y38irrr2dm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oz7YfOtT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7j8x9sp00y38irrr2dm7.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5PSB_MuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x63oh5ky609ewos59tiq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5PSB_MuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x63oh5ky609ewos59tiq.png" alt="Image description" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JXLqqX6e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4cfitka3pg4jacdcosz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JXLqqX6e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4cfitka3pg4jacdcosz.png" alt="Image description" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VHCfSgMb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qjjbu46fitac8fyhpori.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VHCfSgMb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qjjbu46fitac8fyhpori.png" alt="Image description" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NVm6iRLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31mu4xz2x2kjmd2hzy38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NVm6iRLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31mu4xz2x2kjmd2hzy38.png" alt="Image description" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Navigating Waves of Information: The Caribbean Violence Web Crawler</title>
      <dc:creator>Tashyn Wallace</dc:creator>
      <pubDate>Sun, 10 Sep 2023 05:48:34 +0000</pubDate>
      <link>https://dev.to/tashynw/navigating-waves-of-information-the-caribbean-violence-web-crawler-4i2e</link>
      <guid>https://dev.to/tashynw/navigating-waves-of-information-the-caribbean-violence-web-crawler-4i2e</guid>
      <description>&lt;p&gt;Introduction:&lt;br&gt;
Dive into the heart of Caribbean safety with the Caribbean Violence Tracker. Crafted with TypeScript, Node.js, and Next.js, this innovative tool scours trusted sources across the islands, delivering real-time updates on gun and violent crimes.&lt;/p&gt;

&lt;p&gt;Empowered Insights, Informed Action:&lt;br&gt;
Unleashing the potential of web crawling, our app provides instant access to vital safety data. Stay in the loop, making informed choices for your well-being.&lt;/p&gt;

&lt;p&gt;Uniting Communities, Fostering Safety:&lt;br&gt;
In times of challenge, unity is our anchor. The Caribbean Violence Tracker serves as a digital lighthouse, illuminating pathways to safety. Share insights, raise awareness, and strengthen your community.&lt;/p&gt;

&lt;p&gt;Accessing the Caribbean Violence Tracker:&lt;br&gt;
Ready to take control of your safety? Set sail with the &lt;a href="https://caribbean-violence-tracker.vercel.app/"&gt;Caribbean Violence Tracker&lt;/a&gt; and chart a course to real-time incident updates.&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;br&gt;
More than code, this is a commitment to Caribbean security. Join us on this technological voyage toward safer, more connected communities. Embrace the Caribbean Violence Web Crawler today!&lt;/p&gt;

&lt;p&gt;Images:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UUTNForo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7wmanzry6wfcwwb70q2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UUTNForo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7wmanzry6wfcwwb70q2e.png" alt="Image description" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1W5JKMCH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xoovhcv1wc6agi6k0pzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1W5JKMCH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xoovhcv1wc6agi6k0pzj.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XlQxOIys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eeqcd48go6clhmxust45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XlQxOIys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eeqcd48go6clhmxust45.png" alt="Image description" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aBokyMEp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26o2xith00kq4reg6vwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aBokyMEp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26o2xith00kq4reg6vwz.png" alt="Image description" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yolNBeI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6wsd5mn0fesv6cye3h4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yolNBeI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6wsd5mn0fesv6cye3h4.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d7p7BLyw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptv60919o37darhvzp5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d7p7BLyw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptv60919o37darhvzp5q.png" alt="Image description" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>AI-Powered Quiz Generation: Introducing QwizLab with NextJS</title>
      <dc:creator>Tashyn Wallace</dc:creator>
      <pubDate>Sun, 10 Sep 2023 05:39:20 +0000</pubDate>
      <link>https://dev.to/tashynw/ai-powered-quiz-generation-introducing-qwizlab-with-nextjs-i13</link>
      <guid>https://dev.to/tashynw/ai-powered-quiz-generation-introducing-qwizlab-with-nextjs-i13</guid>
      <description>&lt;p&gt;Discover QwizLab, a NextJS app that leverages the power of AI to transform your notes into quizzes. Say goodbye to manual quiz creation and hello to a smarter, more efficient learning experience.&lt;/p&gt;

&lt;p&gt;Unleashing the AI Advantage:&lt;br&gt;
QwizLab harnesses OpenAI's capabilities to automatically generate quizzes from your notes. Dive into your studies without the hassle of crafting questions.&lt;/p&gt;

&lt;p&gt;Total Control, Effortless Editing:&lt;br&gt;
Take charge of your quizzes. With QwizLab, you can create, edit, and delete questions with ease, ensuring your quizzes are perfectly tailored.&lt;/p&gt;

&lt;p&gt;Export and Share:&lt;br&gt;
Need to collaborate or study offline? QwizLab lets you export quizzes effortlessly, making sharing and studying with peers a breeze.&lt;/p&gt;

&lt;p&gt;Get Started:&lt;br&gt;
Join the future of learning. Visit QwizLab &lt;a href="https://qwizlab.com/"&gt;here&lt;/a&gt; and sign up!&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;br&gt;
QwizLab is your shortcut to smarter studying. Embrace the power of AI for a more effective learning journey. Try QwizLab today!&lt;/p&gt;

&lt;p&gt;Images:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8v-JYitw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vgads79mrcgkuc7yu1t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8v-JYitw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vgads79mrcgkuc7yu1t.png" alt="Image description" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sCDspZJF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okubulc9iizrlvr11fh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sCDspZJF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okubulc9iizrlvr11fh3.png" alt="Image description" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DJuXS7yk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fg1z7tmvzybd1ln80rir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DJuXS7yk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fg1z7tmvzybd1ln80rir.png" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fAGOcTg6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtr292snibmjmfpy2lfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fAGOcTg6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtr292snibmjmfpy2lfo.png" alt="Image description" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oIv1FWLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pupw9m282ahty7umxf50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oIv1FWLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pupw9m282ahty7umxf50.png" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C6sXZV3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rguihdq4q1w67tc3ip83.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C6sXZV3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rguihdq4q1w67tc3ip83.png" alt="Image description" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D6XGD8xu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yyepips05wirzpyyue49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D6XGD8xu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yyepips05wirzpyyue49.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eh8om8R5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20lrbyj2zzb79wpxro01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eh8om8R5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20lrbyj2zzb79wpxro01.png" alt="Image description" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>chatgpt</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
