Files
userbase-homepage/src/pages/docs.html
2019-11-02 01:15:54 -07:00

864 lines
31 KiB
HTML

<div class="section">
<h2>Docs</h2>
<ul>
<li><a href="#getting-started" class="font-semibold">Getting started</a></li>
<li><a href="#sdk" class="font-semibold">SDK</a></li>
<li><a href="#tutorial" class="font-semibold">Tutorial</a></li>
</ul>
</div>
<hr>
<div class="section">
<a class="anchor" id="getting-started"></a>
<h2 id=>Getting Started</h2>
<h3>Create a free Userbase account</h3>
<p>First you need a Userbase developer account. You will be able to create a free account when Userbase gets launched. No credit card required.</p>
<h3>Install the SDK</h3>
<p>Then you need to include the Userbase SDK into your web app.</p>
<p>You can either include the SDK with a <code class="language-markup">&lt;script&gt;</code> tag:</p>
<pre>
<code class="language-markup"><!--
<script type="text/javascript" src="https://sdk.userbase.dev/userbase-0.0.5.js"></script>
--></code>
</pre>
<p>Or else you can include the SDK into your build pipeline:</p>
<pre>
<code class="language-bash">
npm --install --save userbase-js
</code>
</pre>
<h3>Set the Application ID</h3>
<p>From your Userbase account, create a new App and get the Application ID. Then you just need to configure the Userbase SDK to use it:</p>
<pre>
<code class="language-javascript"><!--
userbase.configure({ appId: 'a43ae910-fc89-43fe-a7a3-a11a53b49325' })
--></code>
</pre>
<p>And you're all set.</p>
</div>
<hr>
<div class="section">
<a class="anchor" id="sdk"></a>
<h2>SDK</h2>
<p>You can use Userbase through a simple JavaScript SDK in the browser. The following is the complete set of Userbase APIs that let you create user accounts, handle logins, and persist user data.</p>
<h3 id="sdk-users">Users</h3>
<p>Use these APIs to create user accounts, handle logins and logouts, and resume sessions when a user returns to your web app.</p>
<ul>
<li><a href="/docs/sdk/sign-up" class="font-semibold">SignUp</a></li>
<li><a href="/docs/sdk/sign-in" class="font-semibold">SignIn</a></li>
<li><a href="/docs/sdk/sign-in-with-session" class="font-semibold">SignInWithSession</a></li>
<li><a href="/docs/sdk/sign-out" class="font-semibold">SignOut</a></li>
</ul>
<h3 id="sdk-data">Data</h3>
<p>Use these APIs to store and retrieve user data. All data handled by these APIs is highly-durable, immediately consistent, and end-to-end encrypted.</p>
<ul>
<li><a href="/docs/sdk/open-database" class="font-semibold">OpenDatabase</a></li>
<li><a href="/docs/sdk/insert" class="font-semibold">Insert</a></li>
<li><a href="/docs/sdk/update" class="font-semibold">Update</a></li>
<li><a href="/docs/sdk/delete" class="font-semibold">Delete</a></li>
<li><a href="/docs/sdk/transaction" class="font-semibold">Transaction</a></li>
</ul>
</div>
<hr>
<div class="section">
<a class="anchor" id="tutorial"></a>
<h2>Tutorial</h2>
<p>
In this tutorial we will build a simple to-do web app. Even if what you're building has nothing to do with to-dos, the techniques we'll cover here can be applied to many other kinds of web apps.
</p>
<p>
You can think of this tutorial as a demonstration of the core functionality of Userbase in the simplest way possible. We are going to focus solely on building a fully functional web app. Making things pretty is left as an exercise to the reader.
</p>
<p>You can see a live demo of what we'll be building <a href="https://ugliest-todo.netlify.com/" target="_blank">here</a>.</p>
<h3>Prerequisites</h3>
<p>You just need to be familiar with <a href="https://www.w3schools.com/html/html_editors.asp" target="_blank">HTML</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript" target="_blank">JavaScript basics</a>.</p>
<h3>Setting up</h3>
<p>Let's get going. Open up a new file in your favorite code editor:</p>
<pre>
<code class="language-bash">
code ugly-todo.html
</code>
</pre>
<p>And add some boilerplate HTML:</p>
<div>
<pre>
<code class="language-markup">
&#x3C;!DOCTYPE html&#x3E;
&#x3C;html lang=&#x22;en&#x22;&#x3E;
&#x3C;head&#x3E;
&#x3C;meta charset=&#x22;UTF-8&#x22;&#x3E;
&#x3C;title&#x3E;Ugliest To-Do&#x3C;/title&#x3E;
&#x3C;/head&#x3E;
&#x3C;body&#x3E;
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
&#x3C;/script&#x3E;
&#x3C;/body&#x3E;
&#x3C;/html&#x3E;
</code>
</pre>
</div>
<p>
Now open up this file in a web browser of your choosing. At this point all you'll see is a blank page. As we add functionality throughout the tutorial, you can refresh this page to see the changes.
</p>
<a class="anchor" id="creating-a-developer-account"></a>
<h3>Creating a developer account</h3>
<p>To complete this tutorial, you'll need to create a Userbase developer account. Upon creation, a default application named "Preview" will be created. Take note of the App ID, you'll need it in a second.</p>
<p>
We're now ready to start building our web app. We'll start by implementing the sign up and login features, and then in the second part we'll implement the to-do functionality.
</p>
<h3>Installing the SDK</h3>
We're going to load the Userbase SDK from a CDN with a <code class="language-markup">&lt;script&gt;</code> tag in the head of
our page:
<pre data-line="4">
<code class="language-markup"><!--
<head>
<meta charset="UTF-8">
<title>Ugliest To-Do App</title>
<script type="text/javascript" src="https://sdk.userbase.dev/userbase-0.0.5.js"></script>
</head>
--></code>
</pre>
<p>The Userbase SDK will now be accessible via the <code class="language-javascript">userbase</code> variable. This will be our only dependency.</p>
<h3>Configuring the SDK</h3>
<p>
Before doing anything with the Userbase SDK, we need to let it know our Application ID.
Simply replace <code class="language-javascript">'YOUR_APP_ID'</code> with the App ID you received when you <a href="#creating-a-developer-account">created your developer account</a>:
</p>
<pre data-line="4">
<code class="language-markup">
&#x3C;body&#x3E;
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
userbase.configure({ appId: 'YOUR_APP_ID' })
&#x3C;/script&#x3E;
&#x3C;/body&#x3E;
&#x3C;/html&#x3E;
</code>
</pre>
<h3>Letting new users create an account</h3>
<p>
Before a user can start creating to-dos, the user needs to create an account with our app.
</p>
<p>First, we'll add a sign up form:</p>
<div>
<pre data-line="2-11">
<code class="language-markup">
&lt;body&gt;
&lt;!-- Auth View --&gt;
&lt;div id=&quot;auth-view&quot;&gt;
&lt;h1&gt;Create an account&lt;/h1&gt;
&lt;form id=&quot;signup-form&quot;&gt;
&lt;input id=&quot;signup-username&quot; type=&quot;text&quot; required placeholder=&quot;Username&quot;&gt;
&lt;input id=&quot;signup-password&quot; type=&quot;password&quot; required placeholder=&quot;Password&quot;&gt;
&lt;input type=&quot;submit&quot; value=&quot;Create an account&quot;&gt;
&lt;/form&gt;
&lt;div id=&quot;signup-error&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;!-- application code --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
</code>
</pre>
</div>
<p>Then, we'll add the code to handle the form submission:</p>
<div>
<pre data-line="5-16">
<code class="language-markup">
&lt;!-- application code --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
userbase.configure({ appId: 'YOUR_APP_ID' })
function handleSignUp(e) {
e.preventDefault()
const username = document.getElementById('signup-username').value
const password = document.getElementById('signup-password').value
userbase.signUp(username, password)
.then((user) =&gt; alert('You signed up!'))
.catch((e) =&gt; document.getElementById('signup-error').innerHTML = e)
}
document.getElementById('signup-form').addEventListener('submit', handleSignUp)
&lt;/script&gt;
</code>
</pre>
</div>
<p>
Whenever someone submits the form, the <code class="language-javascript">handleSignUp</code> function will be called.
</p>
<p>
The first thing we do in <code class="language-javascript">handleSignUp</code> is call <code class="language-javascript">preventDefault()</code> on the
submit event. This will prevent the page from submitting to the server. We want to handle this form completely on the client-side.
</p>
<p>
Next we get the values of the username and password inputs and call
<code class="language-javascript">userbase.signUp(username, password)</code>. This will request a new account to be created with the Userbase service, and returns a Promise that resolves with a <code class="language-javascript">user</code> object.
</p>
<p>
Go ahead and reload the web app in your browser. Enter a username and password in the form under "Sign Up" and submit. You'll get an alert saying that you signed up. And if go to your Userbase developer account, you should see the new user under your app.
</p>
<p>
Now try signing up for another account using the same username and you'll see an error message displayed under the form.
</p>
<p>
We'll come back to this in a bit to change this function to do something more interesting.
</p>
<h3>Letting users log in</h3>
<p>Now that users can create accounts, let's give them the ability to sign in.</p>
<p>First, we'll add a "Login" form to the page above our "Create Account" form:</p>
<pre data-line="4-10">
<code class="language-markup">
&lt;body&gt;
&lt;!-- Auth View --&gt;
&lt;div id=&quot;auth-view&quot;&gt;
&lt;h1&gt;Login&lt;/h1&gt;
&lt;form id=&quot;login-form&quot;&gt;
&lt;input id=&quot;login-username&quot; type=&quot;text&quot; required placeholder=&quot;Username&quot;&gt;
&lt;input id=&quot;login-password&quot; type=&quot;password&quot; required placeholder=&quot;Password&quot;&gt;
&lt;input type=&quot;submit&quot; value=&quot;Sign in&quot;&gt;
&lt;/form&gt;
&lt;div id=&quot;login-error&quot;&gt;&lt;/div&gt;
&lt;h1&gt;Create an account&lt;/h1&gt;
&lt;form id=&quot;signup-form&quot;&gt;
</code>
</pre>
<p>Then, we'll add code to handle the form submission:</p>
<pre data-line="5-14">
<code class="language-markup">
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
userbase.configure({ appId: 'YOUR_APP_ID' })
function handleLogin(e) {
e.preventDefault()
const username = document.getElementById(&#x27;login-username&#x27;).value
const password = document.getElementById(&#x27;login-password&#x27;).value
userbase.signIn(username, password)
.then((user) =&#x3E; alert(&#x27;You signed in!&#x27;))
.catch((e) =&#x3E; document.getElementById(&#x27;login-error&#x27;).innerHTML = e)
}
function handleSignUp(e) {
e.preventDefault()
&lt;/script&gt;
</code>
</pre>
<p>And finally, let's bind our login form within our login handler:</p>
<pre data-line="9">
<code class="language-markup">
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
.catch((e) => document.getElementById('signup-error').innerHTML = e)
}
document.getElementById('login-form').addEventListener('submit', handleLogin)
document.getElementById('signup-form').addEventListener('submit', handleSignUp)
&#x3C;/script&#x3E;
&#x3C;/body&#x3E;
</code>
</pre>
<p>
You'll notice this looks very similar to the sign up code above. The <code class="language-javascript">handleLogin</code> function prevents the default form behavior, extracts the input values from the DOM, and calls <code class="language-javascript">userbase.signIn(username, password)</code>. This will attempt to sign in the user with the Userbase service, handling a success with an alert and a failure by displaying the error.
</p>
<p>
Reload the app and you should see our new login form. Enter the username and
password you used to create an account in the step above, and submit the form.
You should get an alert saying that you signed in.
</p>
<p>
Try submitting the form again with incorrect credentials and you'll see an error
message displayed under the form.
</p>
<h3>Showing the to-do view</h3>
<p>
After a user signs in, we'll want to hide the authentication forms, indicate
to the user they are logged in, and display their to-do list.
</p>
<p>First, we'll add a new container under the authentication forms:</p>
<pre data-line="8-14">
<code class="language-markup">
&#x3C;!-- Auth View --&#x3E;
&#x3C;div id=&#x22;auth-view&#x22;&#x3E;
&#x3C;/div&#x3E;
&#x3C;!-- To-dos View --&#x3E;
&#x3C;div id=&#x22;todo-view&#x22;&#x3E;
&#x3C;div id=&#x22;username&#x22;&#x3E;&#x3C;/div&#x3E;
&#x3C;h1&#x3E;To-Do List&#x3C;/h1&#x3E;
&lt;div id=&quot;todos&quot;&gt;&lt;/div&gt;
&#x3C;/div&#x3E;
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
userbase.configure({ appId: 'YOUR_APP_ID' })
&#x3C;/script&#x3E;
</code>
</pre>
<p>Then, we'll add a function to display this view and initially make it hidden:</p>
<div>
<pre data-line="9-13,18">
<code class="language-javascript">
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
.catch((e) => document.getElementById('signup-error').innerHTML = e)
}
function showTodos(username) {
document.getElementById('auth-view').style.display = 'none'
document.getElementById('todo-view').style.display = 'block'
document.getElementById('username').innerHTML = username
}
document.getElementById('login-form').addEventListener('submit', handleLogin)
document.getElementById('signup-form').addEventListener('submit', handleSignUp)
document.getElementById('todo-view').style.display = 'none'
&#x3C;/script&#x3E;
</code>
</pre>
</div>
<p>
Now that we have a function to show a view for signed in users, let's change
<code class="language-javascript">handleLogin</code> to call this function when it succeeds:
</p>
<pre data-line="7">
<code class="language-javascript">
function handleLogin(e) {
e.preventDefault()
const password = document.getElementById('login-password').value
userbase.signIn(username, password)
.then((user) => showTodos(user.username))
.catch((e) => document.getElementById('login-error').innerHTML = e)
}
</code>
</pre>
<p>And we do the same thing for <code class="language-javascript">handleSignUp</code>:</p>
<pre data-line="7">
<code class="language-javascript">
function handleSignUp(e) {
e.preventDefault()
const password = document.getElementById('signup-password').value
userbase.signUp(username, password)
.then((user) => showTodos(user.username))
.catch((e) => document.getElementById('signup-error').innerHTML = e)
}
</code>
</pre>
<p>
Reload the app and sign in again using your username and password. You should see the
authentication view disappear and your username show up along with the to-do list heading.
</p>
<h3>Using the database</h3>
<p>
Each time a new session is started when a user signs up or logs in, we need to establish a
connection with the database that will hold that user's to-dos.
</p>
<p>
First, let's add a couple of elements for showing a loading indicator and error
messages:
</p>
<pre data-line="6-7">
<code class="language-markup"><!--
<div id="todo-view">
<span id="username"></span>
<h1>To-Do List</h1>
<div id="todos"></div>
<div id="db-loading">Loading to-dos...</div>
<div id="db-error"></div>
</div>
--></code>
</pre>
<p>Then, we'll change <code class="language-javascript">showTodos</code> to open a new database with the Userbase service:</p>
<pre data-line="5,7-12,15-25">
<code class="language-javascript">
function showTodos(username) {
document.getElementById('auth-view').style.display = 'none'
document.getElementById('todo-view').style.display = 'block'
// reset the todos view
document.getElementById('username').innerHTML = username
document.getElementById('todos').innerText = ''
document.getElementById('db-loading').style.display = 'block'
document.getElementById('db-error').innerText = ''
userbase.openDatabase('todos', handleDatabaseChange)
.catch((e) => document.getElementById('db-error').innerText = e)
}
function handleDatabaseChange(items) {
document.getElementById('db-loading').style.display = 'none'
const todosList = document.getElementById('todos')
if (items.length === 0) {
todosList.innerText = 'Empty'
} else {
// render to-dos, not yet implemented
}
}
document.getElementById('login-form').addEventListener('submit', handleLogin)
document.getElementById('signup-form').addEventListener('submit', handleSignUp)
</code>
</pre>
<p>
We changed <code class="language-javascript">showTodos</code> to make a call to <code class="language-javascript">userbase.openDatabase('todos',
handleDatabaseChange)</code>. The <code class="language-javascript">'todos'</code> parameter is the name of the database we want to open, and <code class="language-javascript">handleDatabaseChange</code> is a callback for receiving changes to data in the database. The Userbase service will attempt to open the user's database by the
name of <code class="language-javascript">'todos'</code> (creating one if it doesn't already exist). After the <code class="language-javascript">'todos'</code>
database is opened, our callback
function <code class="language-javascript">handleDatabaseChanges</code> will be called whenever data changes in the database. When the Promise is resolved, the database is ready for use and we hide the loading indicator.
</p>
<p>
Reload the app and sign in. You'll see the "Loading to-dos..." as a connection
to the database is established followed by "Empty" indicating there are
currently no to-dos.
</p>
<h3>Showing the to-dos</h3>
<p>
If the database has items in it, we'll want to render those under our to-do list.
Let's implement that case in <code class="language-javascript">handleDatabaseChange</code>:
</p>
<pre data-line="9-24">
<code class="language-javascript"><!--
function handleDatabaseChange(items) {
document.getElementById('db-loading').style.display = 'none'
const todosList = document.getElementById('todos')
if (items.length === 0) {
todosList.innerText = 'Empty'
} else {
// clear the list
todosList.innerHTML = ''
// render all the to-do items
for (let i = 0; i < items.length; i++) {
// build the todo label
const todoLabel = document.createElement('label')
todoLabel.innerHTML = items[i].item.todo
todoLabel.style.textDecoration = items[i].item.complete ? 'line-through' : 'none'
// append the todo item to the list
const todoItem = document.createElement('div')
todoItem.appendChild(todoLabel)
todosList.appendChild(todoItem)
}
}
}
--></code>
</pre>
<h3>Adding to-dos</h3>
<p>Let's add a form for creating new to-dos:</p>
<script type="text/plain" data-line="10-14" class="language-markup">
<!-- To-dos View -->
<div id="todo-view">
<span id="username"></span>
<h1>To-Do List</h1>
<div id="todos"></div>
<div id="db-loading">Loading to-dos...</div>
<div id="db-error"></div>
<form id="add-todo-form">
<input id="add-todo" type="text" required placeholder="To-Do">
<input type="submit" value="Add">
</form>
<div id="add-todo-error"></div>
</div>
</script>
<p>Then, add code to handle the form submission:</p>
<pre data-line="5-13,17">
<code class="language-markup">
&lt;!-- application code --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
function addTodoHandler(e) {
e.preventDefault()
const todo = document.getElementById('add-todo').value
userbase.insert('todos', { 'todo': todo })
.then(() =&gt; document.getElementById('add-todo').value = '')
.catch((e) =&gt; document.getElementById('add-todo-error').innerHTML = e)
}
document.getElementById('login-form').addEventListener('submit', handleLogin)
document.getElementById('signup-form').addEventListener('submit', handleSignUp)
document.getElementById('add-todo-form').addEventListener('submit', addTodoHandler)
document.getElementById('todo-view').style.display = 'none'
&lt;/script&gt;
</code>
</pre>
<p>
In <code class="language-javascript">addTodoHandler</code> we first call <code class="language-javascript">preventDefault()</code> to stop the default form
behavior, pull the to-do text from the input, and then call <code class="language-javascript">userbase.insert</code>
with the database name and the object we want the persist. This
will return a Promise that resolves when the data is successfully persisted to
the database.
</p>
<p>
Reload the app and add some to-dos. Then reload the app again and the to-dos should automatically appear after you login.
</p>
<h3>Updating to-dos</h3>
<p>Let's modify how we are rendering the to-do items so we can mark them as completed:</p>
<pre data-line="4-16,26">
<code class="language-javascript">
// render all the to-do items
for (let i = 0; i < items.length; i++) {
// build the todo checkbox
const todoBox = document.createElement('input')
todoBox.type = 'checkbox'
todoBox.id = items[i].itemId
todoBox.checked = items[i].item.complete ? true : false
todoBox.onclick = (e) => {
e.preventDefault()
userbase.update('todos', {
'todo': items[i].item.todo,
'complete': !items[i].item.complete
}, items[i].itemId)
.catch((e) => document.getElementById('add-todo-error').innerHTML = e)
}
// build the todo label
const todoLabel = document.createElement('label')
todoLabel.innerHTML = items[i].item.todo
// append the todo item to the list
const todoItem = document.createElement('div')
todoItem.appendChild(todoBox)
todoItem.appendChild(todoLabel)
todosList.appendChild(todoItem)
}
</code>
</pre>
<p>
Reload the app and complete some to-dos. Their state should presist after you reload the app and login again.
</p>
<h3>Deleting to-dos</h3>
<p>Let's create a button for deleting a to-do:</p>
<pre data-line="4-11">
<code class="language-javascript">
// render all the to-do items
for (let i = 0; i < items.length; i++) {
// build the todo delete button
const todoDelete = document.createElement('button')
todoDelete.innerHTML = 'X'
todoDelete.style.display = 'inline-block'
todoDelete.onclick = () => {
userbase.delete('todos', items[i].itemId)
.catch((e) => document.getElementById('add-todo-error').innerHTML = e)
}
// build the todo checkbox
const todoBox = document.createElement('input')
todoBox.type = 'checkbox'
</code>
</pre>
<p>And append the delete button to the to-do element:</p>
<pre data-line="3">
<code class="language-javascript">
// append the todo item to the list
const todoItem = document.createElement('div')
todoItem.appendChild(todoDelete)
todoItem.appendChild(todoBox)
todoItem.appendChild(todoLabel)
todosList.appendChild(todoItem)
</code>
</pre>
<p>
Reload the app and delete some to-dos. They should no longer show up even after you reload the app and login again.
</p>
<h3>Polishing up</h3>
<p>Before we wrap up, let's add two final pieces of account functionality: user logout and automatic login for returning users.</p>
<h3>Signing out users</h3>
<p>First, let's add a logout button along with a container for displaying error messages:</p>
<script type="text/plain" data-line="4-5" class="language-markup">
<!-- To-dos View -->
<div id="todo-view">
<span id="username"></span>
<input type="button" value="Logout" id="logout-button">
<div id="logout-error"></div>
<h1>To-Do List</h1>
<div id="todos"></div>
</script>
<p>Then, add code to handle click event and log out the user:</p>
<pre data-line="9-13,21-30,40">
<code class="language-markup">
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
.catch((e) => document.getElementById('signup-error').innerHTML = e)
}
function handleLogout() {
userbase.signOut()
.then(() => showAuth())
.catch((e) => document.getElementById('logout-error').innerText = e)
}
function showTodos(username) {
document.getElementById('auth-view').style.display = 'none'
document.getElementById('todo-view').style.display = 'block'
function showAuth() {
document.getElementById('todo-view').style.display = 'none'
document.getElementById('auth-view').style.display = 'block'
document.getElementById('login-username').value = ''
document.getElementById('login-password').value = ''
document.getElementById('login-error').innerText = ''
document.getElementById('signup-username').value = ''
document.getElementById('signup-password').value = ''
document.getElementById('signup-error').innerText = ''
}
function handleDatabaseChange(items) {
const todosList = document.getElementById('todos')
document.getElementById('login-form').addEventListener('submit', handleLogin)
document.getElementById('signup-form').addEventListener('submit', handleSignUp)
document.getElementById('add-todo-form').addEventListener('submit', addTodoHandler)
document.getElementById('logout-button').addEventListener('click', handleLogout)
document.getElementById('todo-view').style.display = 'none'
&lt;/script&gt;
</code>
</pre>
<p>The <code class="language-javascript">handleLogout</code> function calls <code class="language-javascript">userbase.signOut</code> which sends a request to end the user's session to the Userbase service. A Promise is returned that resolves when the user was signed out, in which case we hide the to-do view and show the authentication view.</p>
<h3>Automatically resuming a session</h3>
<p>Whenever a user logs in, the Userbase SDK will store information about the session in browser to allow the session to be resumed when the user returns after having navigating away.</p>
<p>Let's modify our app to automatically sign in a user when the page loads. We'll add a view that indicates we are signing in the user:</p>
<p>Add a view to show when the app is figuring out whether it can resume a previous session:</p>
<pre data-line="4-5">
<code class="language-markup">
&lt;/head&gt;
&lt;body&gt;
&lt;!-- Loading View --&gt;
&lt;div id=&quot;loading-view&quot;&gt;Loading...&lt;/div&gt;
&lt;!-- Auth View --&gt;
&lt;div id=&quot;auth-view&quot;&gt;
&lt;h1&gt;Login&lt;/h1&gt;
</code>
</pre>
<p>In order to automatically resume a session if one is available, we add the following to our application code:</p>
<pre data-line="12-17">
<code class="language-markup">
&#x3C;!-- application code --&#x3E;
&#x3C;script type=&#x22;text/javascript&#x22;&#x3E;
document.getElementById('login-form').addEventListener('submit', handleLogin)
document.getElementById('signup-form').addEventListener('submit', handleSignUp)
document.getElementById('add-todo-form').addEventListener('submit', addTodoHandler)
document.getElementById('logout-button').addEventListener('click', handleLogout)
document.getElementById('todo-view').style.display = 'none'
document.getElementById('auth-view').style.display = 'none'
userbase.signInWithSession()
.then((session) => session.user ? showTodos(session.user.username) : showAuth())
.catch(() => showAuth())
.finally(() => document.getElementById('loading-view').style.display = 'none')
&lt;/script&gt;
</code>
</pre>
<p>
We hide the authentication view initially, as we'll now only show it if an existing session can't be resumed.
</p>
<p>
We make a call to <code class="language-javascript">userbase.signInWithSession</code> to attempt to sign in the user
using an existing session as soon as our app loads.
</p>
<p>
The <code class="language-javascript">userbase.signInWithSession</code> function returns a Promise that resolves when the SDK has determined if it can reuse the previous session. If so, the user gets automatically logged in, and the <code class="language-javascript">session.user</code> object gets set. If there was no previous session, or the session cannot be resumed, the <code class="language-javascript">session.user</code> object will not be set.
</p>
<p>
If <code class="language-javascript">userbase.signInWithSession</code> fails, we'll just send the user
to the sign in page regardless of the reason.
</p>
<h3>What's next?</h3>
<p>
In a real project you'll likely want a more sophisticated approach: for instance, you may use React to control the DOM or a module bundler to package your application from multiple files, and at the very
least you'll want to display better error messages and add some styling.
</p>
<p>
We are working on a collection of tutorials and sample applications that will
show you how to do all these things with Userbase and more. You can <a href="/mailing-list">subscribe to our mailing list</a> to get updates on these and more.
</p>
<p>If you have any questions, or there's anything we can do to help you with your web app, please get in touch via <a href="mailto:daniel@encrypted.dev">email</a> or <a href="https://twitter.com/UserbaseHQ">Twitter</a>. Thank you!</p>
</div>
<hr>