使用Cloudinary和XATA在Next构建博客资料
#javascript #jamstack #hackmamba

先决条件

  1. javascript
  2. 下一步|反应

介绍

使用XATA作为后端构建博客配置文件,并构建用于处理图像的云。
XATA是为与您的前端应用程序连接而创建的无服务器后端。

设置NextJ

在本节中,我们将使用下一个JS构建前端应用的结构。

n:b在本文的那一刻,已实施了12.2.0版,并且版本13可能很快就会发布。

NPM安装。

https://docs.npmjs.com/cli/v6/commands/npm-install

安装nextjs

https://nextjs.org/learn/basics/create-nextjs-app/setup

成功安装了这些工具后,我们的结构为

在我的应用程序夹中,我们需要创建一个组件文件夹,该文件夹将保存我们的Web应用程序的每个组件。
我们将创建文件

  • header.js
  • post.js
  • uploadwidget.js

在我们的Header.js文件中,我们将建立一个导航栏和按钮,该按钮在登录应用程序时处理我们的身份验证以供我们在pages/index.js中渲染。

 import { useSession, signIn, signOut } from "next-auth/react";
    import Link from "next/link";
    export default function Header() {
      const handleSignin = (e) => {
        e.preventDefault();
        signIn();
      };
      const handleSignout = (e) => {
        e.preventDefault();
        signOut();
      };
      const { data: session } = useSession();
      return (
        <div className="header">
          <Link href="/">
            <a className="logo">FlauntSpace</a>
          </Link>
          {session && (
            <a href="#" onClick={handleSignout} className="btn-signin">
              SIGN OUT
            </a>
          )}
          {!session && (
            <a href="#" onClick={handleSignin} className="btn-signin">
              SIGN IN
            </a>
          )}
        </div>
      );
    }

我们导入了下一个链接和下一个实现,以便使用第三方(Github,google)处理身份验证,而我们这样做时,下一个auth库为我们提供了处理签名的功能。

现在,我们打开我们的pages/index.js并清除使我们思想家的默认代码

import { useSession } from "next-auth/react";

   export default function Home() {
     const { data: session, status } = useSession();
     const loading = status === "loading";

     return (
        <>
          <div className={styles.container}>
            <Head>
              <title>FlauntSpace</title>
              <link rel="icon" href="/favicon.ico" />
            </Head>
            <Header />
          </div>
      </>
      )
    }

我们必须设置代码来美化它,以获得更好的界面和体验。下一个软件包给出默认的styles/global.css

html,
body {
 padding: 0;
 margin: 0;
 background-color: #2d3436;
 font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
 }
 a {
  color: inherit;
  ext-decoration: none;
 }
    * {
      box-sizing: border-box;
    }
    .header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      background-color: rgb(110, 90, 90);
      color: #fff;
      padding: 0 2rem;
      width: 100%;
        box-shadow: 0 10px 20px rgba(82, 71, 71, 0.19), 0 6px 6px rgba(0,0,0,0.23);
    }
    .logo {
      font-weight: 800;
      color: #fff;
      font-size: 1.8rem;
      font-style: oblique;
    }
    .btn-signin {
       box-sizing: border-box;
      -webkit-appearance: none;
         -moz-appearance: none;
              appearance: none;
      background-color: #000;;
      outline: none;
      border: 0;
      cursor: pointer;
      display: -webkit-box;
      display: flex;
      align-self: center;
      font-size: 1.2rem;
      line-height: 1;
      margin: 20px;
      font-weight: 700;
      padding: 1.2rem;
        width: 14rem;
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
      text-align: center;
      font-family: inherit;
      user-select: none;
      color: #000;
      background-color: #353430;  
    }
    .btn-signin:hover {
      background-color: #353430;
      color: #000;  
    }

我们使用此CSS代码段。
向前迈进,我们创建了我们的身份验证以进入我们的应用程序配置文件,我们使用GitHub和Google身份验证来绕过此阶段。
创建一个github客户端ID和秘密键

https://www.knowband.com/blog/user-manual/get-github-client-id-client-secret-api-details/

我们对Google身份验证做同样的事情。
https://developers.google.com/adwords/api/docs/guides/authentication

现在我们将在应用程序中创建我们的.env文件,这是为了我们不要向用户揭示我们的安全密钥
遵循
的过程后,我们的.env文件应该看起来像这样 https://next-auth.js.org/providers/github

GOOGLE_ID=<your googleID generated>
GOOGLE_SECRET=<secret key generated by google>
GITHUB_ID=<githubID>
GITHUB_SECRET=<AUTHENTICATION SECRETKEY BY GITHUB USING THE ACTION>
NEXTAUTH_URL=http://localhost:3000

pages/api/auth/…nextauth.js文件中,从Google和GitHub导入生成的身份验证,以使我们的应用程序与API交互。

    import NextAuth from "next-auth";
    import GitHubProvider from "next-auth/providers/github";
    import GoogleProvider from "next-auth/providers/google";
    const options = {
      providers: [
        GitHubProvider({
          clientId: process.env.GITHUB_ID,
          clientSecret: process.env.GITHUB_SECRET,
          authorization: { params: { scope: "notifications" } },
        }),
        GoogleProvider({
          clientId: process.env.GOOGLE_ID,
          clientSecret: process.env.GOOGLE_SECRET,
          authorization: {
            params: {
              scope: "notifications",
            },
          },
        }),
      ],
    };
 export default (req, res) => NextAuth(req, res, options);

我们可以安全地添加我们的身份验证,并应在通过身份验证时显示我们的应用程序
在我们的应用程序中,我们有一个显示屏可以让用户上传个人资料图片,他们也可以发布一个迷你博客。

在我们的组件文件夹中创建一个post.js文件,该文件列出了文本区域和发布按钮,以允许用户发布内容

    import { useState } from "react";
    import styles from "../styles/Home.module.css";
    export function Post() {
      return (
        <form action="api/form" method="post">
          <label htmlFor="body-content" className={styles.flauntText}>
            Flaunt
          </label>
          <textarea rows="4" cols="50" className={styles.bodyText}>
            Enter text here...
          </textarea>
          <br />
          <button type="submit" className={styles.postbut}>
            Post
          </button>
        </form>
      );
    }

另外,我们在组件中创建uploadWidget.js

 import { useState } from "react";
    import styles from "../styles/Home.module.css";
    export function ImageUpload() {
      const [isImageUploaded, setIsImageUploaded] = useState(false);
      async function handleWidgetClick() {
        const widget = window.cloudinary.createUploadWidget(
          {
            cloudName: "dhpp7gaty",
            uploadPreset: "my upload",
            resourceType: "image",
          },
          (error, result) => {
            if (!error && result && result.event === "success") {
              console.log("Done! Here is the image info: ", result.info);
              setIsImageUploaded(true);
            } else if (error) {
              console.log(error);
            }
          }
        );
        widget.open();
      }
      return (
        <div className={styles.container}>
          <div className={styles.vertical}>
            <button
              className={styles.button}
              type="button"
              onClick={handleWidgetClick}
            >
              Upload image
            </button>
          </div>
          {isImageUploaded ? (
            <>
              <div>Successfully uploaded</div>
            </>
          ) : null}
        </div>
      );
    }


我们有我们的上传按钮正在使用Cloudinary上传小部件。
https://cloudinary.com/documentation/upload_widget,现在我们将为我们的应用程序设计。
让我们在样式文件夹中创建Home.module.css文件,我们应该使用此片段。

    @import url('https://fonts.googleapis.com/css2?family=Island+Moments&display=swap');
    .container {
      min-height: 10vh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }
    .main {

    }
    .title {
      border-radius: 50%
    }
    .profile {
      grid-column: 2;
      grid-row: 2;
      background-color: #eef6f8;
    }
    .content {
      display: grid;
      grid-column: 1/3;
      grid-row: 1;
    }
    .uploadsec {
      grid-column: 1;
      grid-row: 2;
      background-color: #ccc;
    }
    .profileimg {
      border-radius: 50%;
    }


    .avatar {
      flex: 1;
      flex-basis: 250px;
    }
    .details {
      flex: 2;
    }
    .button {
      background-color: #449a79; /* Green */
      border-radius: 10px;
      border: none;
      color: white;
      padding: 15px 32px;
      text-align: center;
      cursor: pointer;
      text-decoration: none;
      display: inline-block;
      font-size: 16px;
    }
    .bodyText {
      width: 100%;
      height: 150px;
      padding: 12px 20px;
      box-sizing: border-box;
      border: 2px solid #ccc;
      border-radius: 4px;
      background-color: #f8f8f8;
      resize: none;
    }
    .post {
      align-items: center;
      justify-content: center;
      display: flex;
    }
    .flauntText {
      font-family: 'Island Moments', cursive;
      font-weight: bold;
      font-size: 40px;
    }
    .postbut {
      background-color: #449a79; /* Green */
      border-radius: 10px;
      border: none;
      color: white;
      padding: 15px 30px;
      text-align: center;
      cursor: pointer;
      text-decoration: none;
      display: inline-block;
      font-size: 16px;  
    }
    .imageCloud {
      /*border: 5px solid #555;*/
      border-radius: 50%;
      display: inline-block;
      justify-content: center;
      align-items: center;
      width: 100px;
      border: 3px solid black;
    }

现在,我们必须在pages/index.js文件上渲染所有这些组件

import Head from "next/head";
import Header from "../components/Header";
import styles from "../styles/Home.module.css";
import { useSession } from "next-auth/react";
import { ImageUpload } from "../components/uploadWidget";
import { Post } from "../components/post";
import { getXataClient, XataClient } from "../src/xata";

export default function Home() {
  const { data: session, status } = useSession();
  const loading = status === "loading";
  // const [url, updateUrl] = useState();
  // const [error, updateError] = useState();

  return (
    <>
      <div className={styles.container}>
        <Head>
          <title>FlauntSpace</title>
          <link rel="icon" href="/favicon.ico" />
        </Head>
        <Header />
      </div>
      <main className={styles.main}>
        <div className={styles.user}>
          {loading && <div className={styles.title}>Loading...</div>}{" "}
          {/*authentication process */}
          {/**Renders the home page after authentication passed of third-party */}
          {session && (
            <div className={styles.content}>
              <div className={styles.profile}>
                <>
                  <p>
                    You're logged in as
                    {/**Get's the name and mail from the third-party nextauth and display it as the user name on the home page */}
                    {session.user.name ?? session.user.email}
                  </p>
                  {/**SPLIT spage to two section where one is for the upload preset and the other is for posting blog post */}
                  <form className={styles.post}>
                    <Post />
                  </form>
                </>
              </div>
              <div className={styles.uploadsec}>
                <img
                  src="https://res.cloudinary.com/dhpp7gaty/image/upload/v1667560004/Profile-uploads/jnbkgndxzlnhapxv8eed.jpg"
                  alt="upload here"
                  className={styles.imageCloud}
                />
                <ImageUpload />
              </div>
            </div>
          )}
        </div>
      </main>
    </>
  );
}

用XATA建立后端

快速参观XATA在视频中的工作方式。

https://www.youtube.com/watch?v=-KNRS2fIWdA&

https://youtu.be/-KNRS2fIWdA

初始化XATA我们的项目,使其在JavaScript或Typescript中自动生成代码。

 xata init

现在,让我们将XATA导入我们的pages/index.js

import Head from "next/head";
import Header from "../components/Header";
import styles from "../styles/Home.module.css";
import { useSession } from "next-auth/react";
import { ImageUpload } from "../components/uploadWidget";
import { Post } from "../components/post";
import { getXataClient, XataClient } from "../src/xata";

export default function Home() {
  const { data: session, status } = useSession();
  const loading = status === "loading";

  return (
    <>
      <div className={styles.container}>
        <Head>
          <title>FlauntSpace</title>
          <link rel="icon" href="/favicon.ico" />
        </Head>
        <Header />
      </div>
      <main className={styles.main}>
        <div className={styles.user}>
          {loading && <div className={styles.title}>Loading...</div>}{" "}
          {/*authentication process */}
          {/**Renders the home page after authentication passed of third-party */}
          {session && (
            <div className={styles.content}>
              <div className={styles.profile}>
                <>
                  <p>
                    You're logged in as
                    {/**Get's the name and mail from the third-party nextauth and display it as the user name on the home page */}
                    {session.user.name ?? session.user.email}
                  </p>
                  {/**SPLIT spage to two section where one is for the upload preset and the other is for posting blog post */}
                  <form className={styles.post}>
                    <Post />
                  </form>
                </>
              </div>
              <div className={styles.uploadsec}>
                <img
                  src="https://res.cloudinary.com/dhpp7gaty/image/upload/v1667560004/Profile-uploads/jnbkgndxzlnhapxv8eed.jpg"
                  alt="upload here"
                  className={styles.imageCloud}
                />
                <ImageUpload />
              </div>
            </div>
          )}
        </div>
      </main>
    </>
  );
}
{
  /**Connecting the xata to our app */
}
const xata = new XataClient();
export const getServerSideProps = async () => {
  const FlauntSpace = await xata.db.items.getAll();
  return {
    props: {
      FlauntSpace,
    },
  };
};

我们成功地将XATA数据库连接到了前端应用程序,更多功能是从数据库中查询数据以在前端渲染。

n:b本文打算添加更多功能,并在更改后立即进行编辑。