So let's now do a server component where a user can read their own individual notes. This will look a lot like what we did with the no framework version!

Make a folder inside the app directory called my. Inside that directory, put page.js. This will make the route /my where this page will show up.

import { AsyncDatabase } from "promised-sqlite3";

// this page assumes that you are logged in as user 1
export default async function MyNotes() {
  async function fetchNotes() {
    const db = await AsyncDatabase.open("./notes.db");
    const fromPromise = db.all(
      "SELECT n.id as id, n.note as note, f.name as from_user, t.name as to_user FROM notes n JOIN users f ON f.id = n.from_user JOIN users t ON t.id = n.to_user WHERE from_user = ?",
      ["1"]
    );
    const toPromise = db.all(
      "SELECT n.id as id, n.note as note, f.name as from_user, t.name as to_user FROM notes n JOIN users f ON f.id = n.from_user JOIN users t ON t.id = n.to_user WHERE to_user = ?",
      ["1"]
    );
    const [from, to] = await Promise.all([fromPromise, toPromise]);
    return {
      from,
      to,
    };
  }

  const notes = await fetchNotes();

  return (
    <div>
      <h1>My Notes</h1>
      <fieldset>
        <legend>Notes To You</legend>
        <table>
          <thead>
            <tr>
              <th>From</th>
              <th>To</th>
              <th>Note</th>
            </tr>
          </thead>
          <tbody>
            {notes.to.map(({ id, note, from_user, to_user }) => (
              <tr key={id}>
                <td>{from_user}</td>
                <td>{to_user}</td>
                <td>{note}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </fieldset>
      <fieldset>
        <legend>Notes From You</legend>
        <table>
          <thead>
            <tr>
              <th>From</th>
              <th>To</th>
              <th>Note</th>
            </tr>
          </thead>
          <tbody>
            {notes.from.map(({ id, note, from_user, to_user }) => (
              <tr key={id}>
                <td>{from_user}</td>
                <td>{to_user}</td>
                <td>{note}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </fieldset>
    </div>
  );
}
  • We've built this to essentially the user is always logged in as user 1, brian. Feel free afterwards to add your own auth and make it a full-fledged app. Neon Auth (which I helped build!) and Clerk are two great options here.
  • It's an async function
  • We're able to use the SQLite driver which is server-only normally
  • Again, we don't have to say "use server"; because it's assumed that any component without "use client" is a server component
  • Make sure to check out the network traffic! It's cool to see all the React Flight protocol stuff in action!