Building a Next.js App with DataverseOS, Typescript, and Next.js: A Step-by-Step Guide

Building a Next.js App with DataverseOS, Typescript, and Next.js: A Step-by-Step Guide

In this tutorial, we'll walk through the process of creating a Next.js application using DataverseOS along with Typescript. DataverseOS is a decentralized application platform that leverages blockchain technology to manage and store data securely. We'll use the powerful @dataverse/dataverse-connector package to interact with DataverseOS and handle data models.

Prerequisites:

  • Node.js >=16 version installed

  • Metamask or Dataverse keypair

  • Basic knowledge of Next.js, Typescript, and pnpm

Step 1: Setting up the Next.js App

npx create-next-app@latest demo-app

Step 2: Initializing Dataverse

npm install -g pnpm
pnpm install create-dataverse-app

Step 3: Creating Data Models

Create a model for a social platform post in the 'data-app/models' directory using the provided GraphQL syntax.

dataverseos init data-app
type post @createModel(accountRelation: LIST, description: "post") {
  modelVersion: String! @string(maxLength: 100)
  text: String @string(maxLength: 300000000)
  images: [String] @list(maxLength: 10000000) @string(maxLength: 2000000)
  videos: [String] @list(maxLength: 10000000) @string(maxLength: 2000000)
  options: String @string(maxLength: 300000000)
  createdAt: DateTime!
  updatedAt: DateTime!
}

Step 4: Registering Models

Navigate to 'data-app' and deploy the Dataverse application.

cd data-app
pnpm install
dataverseos deploy

Take note of the generated 'app-id' and 'model-id' for later use.

Step 5: Connecting to Dataverse Wallet

Now, we will navigate back again to our demo-app. Implement the connection to the Dataverse wallet in your Next.js project. Update the page.tsx file with the provided code, replacing 'app-id' with your actual app ID.

"use client";
import { DataverseConnector, SYSTEM_CALL, RESOURCE } from "@dataverse/dataverse-connector";
import React, { useState } from "react";

export default function Home() {
    const [pkh, setPkh] = useState("");

    const dataverseConnector = new DataverseConnector();

    const login = async () => {
        await createCapability();
    };

    const createCapability = async () => {
        await dataverseConnector.connectWallet();
        const pkh = await dataverseConnector.runOS({
            method: SYSTEM_CALL.createCapability,
            params: {
                appId: "app_id",
                resource: RESOURCE.CERAMIC,
            },
        });
        console.log("pkh:", pkh);
        setPkh(pkh);
        return pkh;
    };

    return (
        <div>
            <div className=" mb-4">
                {pkh ? (
                    <p>{pkh}</p>
                ) : (
                    <button onClick={login}>Connect Wallet</button>
                )}
            </div>
        </div>
    );
}

Step 6: Uploading Files

Extend your Next.js app to include file uploads. Implement the code provided for uploading files, replacing 'model-id' with the ID of the deployed post model.

    const [fileId, setFileId] = useState<String | undefined>();
    const [loading, setLoading] = useState(false);
    const [inputs, setInputs] = useState({
        text: "",
        fileId: "",
    });

    const uploadWithDataverse = async () => {
        setLoading(true);
        const encrypted = JSON.stringify({
            text: false,
            images: false,
            videos: false,
        });

        await dataverseConnector.connectWallet();
        const res = await dataverseConnector.runOS({
            method: SYSTEM_CALL.createIndexFile,
            params: {
                modelId: "model-id",
                fileName: "test",
                fileContent: {
                    modelVersion: "0",
                    text: inputs.text,
                    images: [],
                    videos: [],
                    createdAt: new Date().toISOString(),
                    updatedAt: new Date().toISOString(),
                    encrypted,
                },
            },
        })
        setFileId(res.fileContent.file.contentId);
        setLoading(false);
    };

    return (
            <div className=" mb-4">
                <p>Upload File</p>
                <input
                    type="text"
                    className="text-black"
                    onChange={(e) =>
                        setInputs({ ...inputs, text: e.target.value })
                    }
                />
                <button onClick={uploadWithDataverse}>Upload</button>
                {loading ? <p>Loading..</p> : <p>file id: {fileId}</p>}
            </div>
        </div>
    );

Step 7: Loading Files

Further, enhance your application by adding file loading functionality. Use the provided code to load files from DataverseOS, displaying the fetched data.

    const [fetchedData, setFetchedData] = useState<any>();

    const loadWithDataverse = async () => {
        const res = await dataverseConnector.runOS({
            method: SYSTEM_CALL.loadFile,
            params: inputs.fileId,
        });

        console.log(res);
        setFetchedData(res.fileContent.content.text);
    };

    return (
            <div className=" mb-4">
                <p>Load File</p>
                <input
                    type="text"
                    className="text-black"
                    onChange={(e) =>
                        setInputs({ ...inputs, fileId: e.target.value })
                    }
                />
                <button onClick={loadWithDataverse}>Load</button>
                <p>data: {fetchedData}</p>
            </div>
        </div>
    );

Conclusion:

🔥 Congratulations! You've successfully integrated DataverseOS into your Next.js application, allowing for secure and decentralized data storage. This tutorial provides a foundation for building more complex applications with DataverseOS, giving you the tools to create powerful decentralized solutions.

Feel free to explore additional features and functionalities offered by DataverseOS to tailor your application to specific needs. Happy coding!