Getting Started: Part 1

This tutorial creates an introductory application that uses Inrupt’s JavaScript client libraries to read your user profile data from your Pod. Alternatively, to create a sample application using Inrupt’s Solid React SDK, refer to Solid React SDK documentation.

The tutorial uses npm and webpack to run the application locally on localhost:8080.

Locally Run Getting Started Application

Prerequisites

Register Your Pod and Create Your Profile

Note

The tutorial assumes that your Pod server is either https://pod.inrupt.com or https://inrupt.net/. If your example Pod is not on either of these servers, you must change the oidcIssuer value in the application’s index.js file.

For more information on these Pod servers, see Inrupt Pod Spaces.

To create a Pod at https://pod.inrupt.com (Currently in Alpha):

  1. Go to https://signup.pod.inrupt.com/.

    1. To login or sign up, you must agree to the Inrupt terms of use.

    2. Click Login/Sign Up. You are shown the Login screen.

  2. Click the Sign up link at the bottom to switch to the Sign up screen.

    1. Fill in your username, email, and password.

    2. Click Sign up. You are sent a verification email.

    3. To verify your email, open the verification email and click on the email verification link in the message.

    4. Once verified, go back to Pod Spaces window and click Continue.

  3. Sign in with your username and password.

  4. Click Approve to allow “Inrupt Pod Space Registration” access to requested information. Once approved, your Pod is created:

    WebID:

    https://pod.inrupt.com/<username>/profile/card#me

    Pod URL:

    https://pod.inrupt.com/<username>/

    Solid Identity Provider:

    https://broker.pod.inrupt.com

  5. Click on the Go to PodBrowser link.

    1. At the Pod Browser login screen, click Sign In.

    2. Sign in with your Username and Password.

    3. The consent screen appears. To continue, Approve PodBrowser.

  6. Once logged into PodBrowser, click on your name at the top-right corner and click Profile.

  7. Edit your public profile.

    Important

    Your profile information is public.

    For this tutorial:

    1. Enter a name in the Name field.

    2. Enter a role in the Role field.

    Your data is saved automatically.

  8. Log out. Click on your name at the top-right corner and click Log out.

Install npm

If you do not already have npm installed, install npm. npm is installed as part of the Node.js installation.

Ensure that you use a version of Node that is supported by webpack. For webpack 5, the minimum Node version is version 10.13.0(LTS).

Build the Application

1. Initialize the Application

  1. Create the directory structure for your Webpack project:

    mkdir -p  my-demo-app my-demo-app/src my-demo-app/dist
    
  2. Go to the newly created my-demo-app directory.

    cd my-demo-app
    
  3. Initialize the application.

    • To accept the default values for the application without prompts:

      npm init -y
      

    - or -

    • To be prompted to enter values for the application:

      npm init
      
      1. You can either hit return to accept the default values (including empty values) or supply your own values.

      2. When prompted Is this OK? (yes), enter to accept yes.

2. Install the Client Libraries

  1. Use npm to install the solid-client, solid-client-authn-browser, and vocab-common-rdf libraries:

    npm install @inrupt/solid-client @inrupt/solid-client-authn-browser @inrupt/vocab-common-rdf
    

3. Install Webpack

  1. Use npm to install Webpack packages:

    npm install webpack webpack-cli webpack-dev-server css-loader style-loader --save-dev
    
  2. In my-demo-app directory, create a webpack.config.js file with the following content:

    const path = require("path");
    module.exports = {
       mode: "development",
       entry: "./src/index.js",
       output: {
         path: path.resolve(__dirname, "public"), 
         filename: "index.js" 
       },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [ { loader: "style-loader" }, { loader: "css-loader" } ],
          },
        ]
      },
      devServer: {
        contentBase: "./dist"
      },
      resolve: {
          fallback: { 
             stream: require.resolve("stream-browserify") ,
             crypto: require.resolve("crypto-browserify")
          }
      }
    };
    
  3. In my-demo-app directory, edit the package.json file to add build and start script fields to scripts:

    Tip

    Be sure to add the comma after the preceding field value before adding the build and start fields.

    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "build": "webpack",
      "start": "webpack serve --open true"
    },
    

4. Create the Application

In the my-demo-app directory, create the files for the application. For an explanation of the JavaScript code used in this tutorial, see Examination of the Code.

  1. In the my-demo-app/dist folder, create a my-demo.css file with the following content:

    h2,h3 {
        margin: 1rem 1.2rem 1rem 1.4rem;
    }
    
    body * {
       margin-left: .5rem;
       margin-right: 1rem;
    }
    
    header {
       border-bottom: #5795b9 solid;
       padding-left: .5rem;
    }
    
    .panel {
       border: 1px solid #005b81;
       border-radius: 4px;
       box-shadow: rgb(184, 196, 194) 0px 4px 10px -4px;
       box-sizing: border-box;
    
       padding: 1rem 1.5rem;
       margin: 1rem 1.2rem 1rem 1.2rem;
    }
    
    #login {
       background: white;
    }
    
    #read {
       background: #e6f4f9;
    }
    
    #labelStatus[role="alert"] {
       padding-left: 1rem;
       color: purple;
    }
    
    .display {
        margin-left: 1rem;
        color: gray;
    }
    
    dl {
      display: grid;
      grid-template-columns:  max-content auto;
    }
    
    dt {
      grid-column-start: 1;
    }
    
    dd {
      grid-column-start: 2;
    }
    
  2. In the my-demo-app/dist, create an index.html file with the following content:

     
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Getting Started: Inrupt JavaScript Client Libraries</title>
        <script defer src="./index.js" ></script>
        <link rel="stylesheet" href="my-demo.css" />
      </head>
      <body>
        
        <header>
            <h2>Getting Started</h2>
            <h3>with Inrupt JavaScript Client Libraries</h3>
        </header>
        <section id="login" class="panel">
            <div class="row">
              <label id="labelLogin" for="btnLogin">1. Click the button to log in: </label>
              <button name="btnLogin" id="btnLogin">Login</button> 
              <p id="labelStatus"></p>
            </div>
        </section>
    
        <div id="read" class="panel" >
          <div class="row">
            <label id="readlabel" for="webID">2. Enter a WebID: </label>
            <input type="url" id="webID" name="webID"  size="50" pattern="https://.*"  value="https://pod.inrupt.com/<username>/profile/card#me">
            <button name="btnRead" id="btnRead" >Read Profile</button>
          </div>
          <dl class="display"> 
              <dt>Profile SolidDataset: </dt>
              <dd id="labelProfile"></dd>
              <dt>Formatted Name (FN): </dt>
              <dd id="labelFN"></dd>
              <dt>Role: </dt>
              <dd id="labelRole"></dd>
          </dl>
        </div>
      </body>
    </html>
    
  3. In the my-demo-app/src, create an index.js file with the following content:

    Note

    If your Pod is not on https://pod.inrupt.com, modify the oidcIssuer value.

    // Import from "@inrupt/solid-client-authn-browser"
    import {
      login,
      handleIncomingRedirect,
      getDefaultSession,
      fetch
    } from "@inrupt/solid-client-authn-browser";
    
    // Import from "@inrupt/solid-client"
    import {
      getSolidDataset,
      getThing,
      getStringNoLocale
    } from "@inrupt/solid-client";
    
    import { VCARD } from "@inrupt/vocab-common-rdf";
    
    const buttonLogin = document.querySelector("#btnLogin");
    const buttonRead = document.querySelector("#btnRead");
    
    // 1a. Start Login Process. Call login() function.
    function loginToInruptDotCom() {
      return login({
        oidcIssuer: "https://broker.pod.inrupt.com",
        redirectUrl: window.location.href,
        clientName: "Getting started app"
      });
    }
    
    // 1b. Login Redirect. Call handleIncomingRedirect() function.
    // When redirected after login, finish the process by retrieving session information.
    async function handleRedirectAfterLogin() {
      await handleIncomingRedirect();
    
      const session = getDefaultSession();
      if (session.info.isLoggedIn) {
        // Update the page with the status.
        document.getElementById("labelStatus").textContent = "Your session is logged in.";
        document.getElementById("labelStatus").setAttribute("role", "alert");
      }
    }
    
    // The example has the login redirect back to the index.html.
    // This calls the function to process login information.
    // If the function is called when not part of the login redirect, the function is a no-op.
    handleRedirectAfterLogin();
    
    // 2. Read profile
    async function readProfile() {
      const webID = document.getElementById("webID").value;
    
      // The example assumes the WebID has the URI <profileDocumentURI>#<fragment> where
      // <profileDocumentURI> is the URI of the SolidDataset
      // that contains profile data.
      
      // Parse ProfileDocument URI from the `webID` value.
      const profileDocumentURI = webID.split('#')[0];
      document.getElementById("labelProfile").textContent = profileDocumentURI;
    
    
      // Use `getSolidDataset` to get the Profile document.
      // Profile document is public and can be read w/o authentication; i.e.: 
      // - You can either omit `fetch` or 
      // - You can pass in `fetch` with or without logging in first. 
      //   If logged in, the `fetch` is authenticated.
      // For illustrative purposes, the `fetch` is passed in.
      const myDataset = await getSolidDataset(profileDocumentURI, { fetch: fetch });
    
      // Get the Profile data from the retrieved SolidDataset
      const profile = getThing(myDataset, webID);
    
      // Get the formatted name using `VCARD.fn` convenience object.
      // `VCARD.fn` includes the identifier string "http://www.w3.org/2006/vcard/ns#fn".
      // As an alternative, you can pass in the "http://www.w3.org/2006/vcard/ns#fn" string instead of `VCARD.fn`.
     
      const fn = getStringNoLocale(profile, VCARD.fn);
    
      // Get the role using `VCARD.role` convenience object.
      // `VCARD.role` includes the identifier string "http://www.w3.org/2006/vcard/ns#role"
      // As an alternative, you can pass in the "http://www.w3.org/2006/vcard/ns#role" string instead of `VCARD.role`.
    
      const role = getStringNoLocale(profile, VCARD.role);
    
      // Update the page with the retrieved values.
      document.getElementById("labelFN").textContent = fn;
      document.getElementById("labelRole").textContent = role;
    }
    
    buttonLogin.onclick = function() {  
      loginToInruptDotCom();
    };
    
    buttonRead.onclick = function() {  
      readProfile();
    };
    

For details about the JavaScript code, see Examination of the Code.

5. Run the Application

  1. In the my-demo-app directory, run:

    npm run build && npm run start
    

    The output resembles the following:

    ℹ 「wds」: Project is running at http://localhost:8080/
    ...
    ℹ 「wdm」: Compiled successfully.
    
  2. Open localhost:8080 in a browser.

  3. Login.

    1. Click Login to login.

    2. If you have logged out of your Pod, you are prompted to log in. Enter your username and password and log in.

      For pod.inrupt.com, you will be prompted to approve this application’s access to the requested information. To continue, click Approve.

      For inrupt.net, you will be prompted to authorize applications from http://localhost:8080 to access your Pod.

    3. You are redirected back to your page.

  4. Read public profile data.

    Note

    Because the profile data is public, you do not need to log in to read the data. The application does so to show how to make authenticated read requests.

    1. Enter your WebID. The application assumes WebID of the form <profileDocumentURI>#<fragment> and parses the profileDocumentURI from the entered WebID. 1

    2. Click Read Profile.

    3. The page should display your formatted name and role.

    You can read public profiles of others by entering in their WebID; e.g., https://pod.inrupt.com/docsteam/profile/card#me.

6. Exit the Application

To exit the application, stop the npm run start process; e.g., Ctrl-C.

Explanation of the Code

See Examination of the Code for an explanation of the Inrupt’s JavaScript client libraries usage in this tutorial.

Additional Information

React SDK Availability

To create a sample application using Inrupt’s Solid React SDK, refer to the Solid React SDK documentation.

1

Although the example assumes that the WebID has the URI <profileDocumentURI>#<fragment>, a WebID can also have a URL without the hash fragment. For details, see https://www.w3.org/2005/Incubator/webid/spec/identity/#dfn-webid.