NotesGPT Documentation

repository·main·Indexed 24 days ago

https://github.com/nutlope/notesgpt

An AI-powered voice note-taking application that generates action items from voice recordings. Built with Next.js, Convex, Together AI (Mixtral and Whisper), and Clerk authentication. Includes guides on deploying the application, configuring backend query and mutation functions in Convex, and utilizing custom React hooks for authenticated queries.

Tokens
2.1K
Snippets
7
Records
11
Agent score
80%

What's inside NotesGPT

  1. Deploy your own instance of NotesGPT

    main

    To deploy NotesGPT, you need to set up Convex, Clerk, and Together AI. Follow these steps:

    1. Install dependencies: Run npm install.
    2. Initialize Convex: Run npm run dev. Follow the terminal prompts to log into Convex and create a new project.
    3. Configure Clerk Authentication:
    4. Configure Together AI:

    Once configured, the frontend and backend will be running, allowing for user login and voice note recording.

    npm install
    npm run dev
  2. Use a Convex mutation function in React

    main

    To trigger a mutation in a React component, use the useMutation hook. This returns a function that you can call to execute the mutation. You can use it as a 'fire and forget' call or await the returned Promise to access the mutation's result.

    const mutation = useMutation(api.functions.myMutationFunction);
    
    function handleButtonPress() {
      // fire and forget, the most common way to use mutations
      mutation({ first: 'Hello!', second: 'me' });
    
      // OR
      // use the result once the mutation has completed
      mutation({ first: 'Hello!', second: 'me' }).then((result) =>
        console.log(result),
      );
    }
  3. Use a Convex query function in React

    main

    To consume a query function in a React component, use the useQuery hook. Pass the function reference from the generated api object and an object containing the required arguments.

    const data = useQuery(api.functions.myQueryFunction, {
      first: 10,
      second: 'hello',
    });
  4. Write a Convex mutation function

    main

    A mutation function is used to modify data in the database (insert, update, or delete). Like queries, mutations require an args object with validators and a handler. Mutations can also read from the database using ctx.db before performing write operations.

    import { mutation } from './_generated/server';
    import { v } from 'convex/values';
    
    export const myMutationFunction = mutation({
      // Validators for arguments.
      args: {
        first: v.string(),
        second: v.string(),
      },
    
      // Function implementation.
      handler: async (ctx, args) => {
        // Insert or modify documents in the database here.
        const message = { body: args.first, author: args.second };
        const id = await ctx.db.insert('messages', message);
    
        // Optionally, return a value from your mutation.
        return await ctx.db.get(id);
      },
    });
  5. Write a Convex query function

    main

    A query function is used to read data from the database. You define it using the query function from your generated server module. You must provide an args object with validators (using v from convex/values) to ensure type safety for incoming arguments, and a handler function that implements the logic. The handler receives ctx (the context) and args (the validated arguments).

    import { query } from './_generated/server';
    import { v } from 'convex/values';
    
    export const myQueryFunction = query({
      // Validators for arguments.
      args: {
        first: v.number(),
        second: v.string(),
      },
    
      // Function implementation.
      handler: async (ctx, args) => {
        // Read the database as many times as you need here.
        const documents = await ctx.db.query('tablename').collect();
    
        // Arguments passed from the client are properties of the args object.
        console.log(args.first, args.second);
    
        return documents;
      },
    });
  6. Configure Clerk authentication for Convex

    main

    To enable Clerk authentication within your Convex backend, you must export a default configuration object containing a providers array. Each provider requires a domain (the Clerk Issuer URL) and an applicationID (which should be set to 'convex').

    Ensure the CLERK_ISSUER_URL environment variable is set in your Convex deployment environment.

    export default {
      providers: [
        {
          domain: process.env.CLERK_ISSUER_URL,
          applicationID: 'convex',
        },
      ],
    };
  7. Format dates and timestamps

    main

    The utility library provides two functions for date formatting in the en-US locale:

    1. getCurrentFormattedDate(): Returns the current date and time formatted as Month Day, Year, Hour:Minute AM/PM (e.g., "July 12, 2026, 10:30 AM").
    2. formatTimestamp(timestamp: number): Takes a Unix timestamp (in milliseconds) and returns a string in the format Month Day, Year at Hour:Minute AM/PM (e.g., "July 12, 2026 at 10:30 AM").
  8. Merge Tailwind classes with cn()

    main
    The cn utility function allows you to conditionally merge CSS class names while ensuring Tailwind CSS class conflicts are resolved correctly. It combines the functionality of clsx (for conditional logic) and tailwind-merge (to handle Tailwind-specific overrides).
  9. Use usePreloadedQueryWithAuth to handle authenticated queries

    main

    When using Convex with Next.js, usePreloadedQueryWithAuth allows you to access the result of a preloaded query on the client immediately, even while the client is still undergoing authentication.

    This hook works by returning the server-side preloaded result if the client-side query hasn't loaded yet. It relies on two assumptions:

    1. The query only returns null when it is waiting for authentication.
    2. The query is always authenticated when called from the server.

    It is a wrapper around usePreloadedQuery that uses preloadedQueryResult as a fallback to prevent the UI from seeing null during the auth transition.