Next.js Quick Start Guide

In this quickstart, we will show you how to get started with SQLite Cloud and Next.js by building a simple application that connects to and reads from a SQLite Cloud database.


  1. Set up a SQLite Cloud account
    • If you haven’t already, sign up for a SQLite Cloud account and create a new project.
    • In this guide, we will use the sample datasets that come pre-loaded with SQLite Cloud.
  2. Create a Next.js app
    • Create a Next app using create-next-app. The following command creates a very simple app (JS, no Tailwind, uses the latest App Router) to keep the focus on querying the data.
npx create-next-app@latest sqlc-quickstart --js --no-tailwind --eslint --app --src-dir --import-alias "@/*" --use-npm
  1. Install the SQLite Cloud SDK
cd sqlc-quickstart && npm install @sqlitecloud/drivers
  1. Instantiate a connection
  • The Database driver establishes a TLS connection when used in Node.js, and a websocket connection when used in the browser.
  • It is recommended that you use the Database driver in client-side components.
  • To share the connection across pages, you can instantiate the connection in a context provider with the use client directive. Below is a simplified sample implementation.
// src/app/context/DatabaseContext.tsx
'use client';

import { Database } from '@sqlitecloud/drivers';
import { createContext, useContext, useEffect, useRef, useState } from 'react';

interface DatabaseContextType {
  db: Database | null;
  isConnecting: boolean;
  error: Error | null;
}

const DatabaseContext = createContext<DatabaseContextType | undefined>(undefined);

interface DatabaseProviderProps {
  children: React.ReactNode;
  config: { connectionString: string }
}

export function DatabaseProvider({ children, config }: DatabaseProviderProps) {
  const [isConnecting, setIsConnecting] = useState(true);
  const [error, setError] = useState<Error | null>(null);
  const dbRef = useRef<Database | null>(null);

  useEffect(() => {
    if (dbRef.current) return; // Connection already exists

    try {
      dbRef.current = new Database(config.connectionString);

      // Handle connection events
      dbRef.current.on('open', () => {
        console.log('open')
        setIsConnecting(false);
        setError(null);
      });

      dbRef.current.on('error', (err: Error) => {
        console.log('error')
        setError(err);
        setIsConnecting(false);
      });

      dbRef.current.on('close', () => {
        console.log('closing')
        setIsConnecting(false);
        dbRef.current = null;
      });

    } catch (err) {
      setError(err instanceof Error ? err : new Error('Failed to initialize database'));
      setIsConnecting(false);
    }

    // Cleanup function
    return () => {
      if (dbRef.current) {
        dbRef.current.close();
        dbRef.current = null;
      }
    };
  }, [config]);

  return (
    <DatabaseContext.Provider 
      value={{
        db: dbRef.current,
        isConnecting,
        error
      }}
    >
      {children}
    </DatabaseContext.Provider>
  );
}

export function useDatabaseConnection() {
  const context = useContext(DatabaseContext);

  if (context === undefined) {
    throw new Error('useDatabaseConnection must be used within a DatabaseProvider');
  }

  return context;
}
  1. Query data
  • Click the Connect button in your account dashboard and copy the connection string. Replace <your-connection-string> in page.js with your connection string.
  • Replace the code in layout.js and page.js with the following snippets.
// src/app/layout.js
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <DatabaseProvider config={{ connectionString: '<your-connection-string>' }}>
          {children}
        </DatabaseProvider>
      </body>
    </html>
  );
}
// src/app/page.js
import { useDatabaseConnection } from './context/DatabaseContext';
import { useEffect, useState } from "react";
import { useDatabaseConnection } from "./useDatabaseConnection";

export default function Home() {
  const { db } = useDatabaseConnection();
  const [albums, setAlbums] = useState<any[]>([]);

  useEffect(() => {
    const getAlbums = async () => {
      const result = await db.sql`USE DATABASE chinook.sqlite; 
      SELECT albums.AlbumId as id, albums.Title as title, artists.name as artist
      FROM albums 
      INNER JOIN artists 
      WHERE artists.ArtistId = albums.ArtistId
      LIMIT 20;`;
      return result;
    };

    if (db) {
      getAlbums().then((result) => {
        setAlbums(result);
      });
    }
  }, [db]);

  return (
    <div>
      <h1>Albums</h1>
      <ul>
        {albums.map((album) => (
          <div key={album.id}>{album.title}</div>
        ))}
      </ul>
    </div>
  );
}
  1. Run your app
npm run dev
  1. View your app
    • Open your browser and navigate to the localhost link provided by the previous command to see your app data.

And that’s it! You’ve successfully built a Next app that reads data from a SQLite Cloud database.