Contents
01 Prerequisites

What you need before starting

Gesso runs on Next.js 16 with the App Router and uses Supabase for its database, authentication, and file storage. Make sure the following are installed and accessible from your terminal.

02 Clone the Repository

Get the source code

Clone the repository to your machine and move into the project directory.

git clone https://github.com/stockphrase/gesso.git
cd gesso

If you plan to contribute changes, fork the repository on GitHub first and clone your fork instead. You can add the upstream remote afterward with git remote add upstream https://github.com/stockphrase/gesso.git.

03 Install Dependencies

Install the project's packages

From inside the gesso directory, install dependencies. The lockfile pins exact versions, so use a clean install for reproducibility.

npm install

Equivalent commands for other package managers: pnpm install, yarn install, or bun install. The install pulls down Next.js 16, React 19, the Supabase client libraries, Tailwind CSS v4, FontAwesome, JSZip, and Marked, among others.

Note

If you see warnings about peer dependencies for React 19, they are expected and safe to ignore. The project is built against React 19.2 and Next.js 16, which are released and stable.

04 Set Up Supabase

Create your project

Supabase backs every persistent piece of Gesso: user accounts, courses, assignments, submissions, and uploaded files. You will create one project per Gesso instance.

  1. Sign in to supabase.com and click New project.
  2. Pick an organization, give the project a name (for example, gesso-dev), and set a strong database password. Save the password in a password manager.
  3. Choose the region closest to your users. Region cannot be changed later without recreating the project.
  4. Wait for provisioning to finish. It usually takes one to two minutes.
  5. Once the project is ready, go to Project Settings → API. You will need three values from this page in the next step: the Project URL, the anon public key, and the service_role key.
Security

The service_role key bypasses Row Level Security and must never be exposed to the browser or committed to git. It belongs only in server-side code and in your .env.local file.

05 Environment Variables

Configure your local environment

Create a file named .env.local in the project root. This file is git-ignored and stays on your machine. Populate it with the values you copied from the Supabase API settings page.

NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-public-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

Each variable serves a specific purpose:

Variable Used by
NEXT_PUBLIC_SUPABASE_URL The base URL of your Supabase project. Exposed to the browser, used by the client to talk to Supabase.
NEXT_PUBLIC_SUPABASE_ANON_KEY The public-facing API key. Safe to expose; access control is enforced server-side via Row Level Security.
SUPABASE_SERVICE_ROLE_KEY Server-only key for privileged operations such as creating users from the admin panel. Never sent to the browser.

Variables that begin with NEXT_PUBLIC_ are inlined into the client bundle by Next.js. Variables without that prefix are only available in server components, route handlers, and server actions.

06 Database Schema

Set up your tables

Gesso expects a specific set of tables in your Supabase Postgres database. Open SQL Editor in your Supabase dashboard and create the schema. You can either run a migration file from the repository (if one is provided) or apply the schema by hand.

The core tables are:

Each table should have Row Level Security enabled with policies that scope access by course membership. If the repository ships a supabase/ directory with migration files, run them in order; otherwise, refer to the schema documentation in the project README.

Tip

The Supabase CLI makes schema management much easier for iterative development. Install it with npm install -g supabase, then use supabase link to connect your local project to the cloud database.

07 Storage Buckets

Configure file storage

Course materials and student submissions are stored in Supabase Storage. In your Supabase dashboard, go to Storage and create the following buckets:

For each bucket, set it to private (not public), and add Storage policies that mirror your database row-level policies. Files should never be reachable by URL without an authenticated request.

08 Authentication

Configure sign-in

Gesso uses Supabase Auth with email-and-password sign-in. Open Authentication → Providers in your Supabase dashboard and confirm that the Email provider is enabled.

Site URL and redirect URLs

Under Authentication → URL Configuration, set the Site URL to your dev URL (typically http://localhost:3000) and add additional redirect URLs for any environments you deploy to, such as your Vercel preview and production domains.

Email templates

Customize the confirmation and password-reset email templates under Authentication → Email Templates. The defaults will work, but updating the sender name and visual style is recommended for production.

Whitelist enforcement

Gesso only allows registration for email addresses present in the email_whitelist table. New addresses are added by an admin from inside the application; users cannot self-register without being on the list.

09 Run the Dev Server

Start the application

With dependencies installed and your environment file in place, start Next.js in development mode.

npm run dev

The app will be available at http://localhost:3000. Edits to files under app/ and components/ hot-reload automatically. The first page load may take a few seconds while Next.js compiles.

Accessing from another device on your network

The repository's next.config.mjs includes an allowedDevOrigins entry for a specific local IP. If you intend to test from a phone or another machine on your LAN, edit that file to include your own dev machine's IP, then restart the dev server.

// next.config.mjs
const nextConfig = {
  allowedDevOrigins: ['192.168.1.42'],
};
10 Create the First Admin

Bootstrap your account

Gesso has no public sign-up. The first user must be created manually so that they can then add other users from the admin panel.

  1. In Supabase, open Authentication → Users and click Add user → Create new user. Enter your email and a password. Make sure Auto Confirm User is checked.
  2. Open the SQL Editor and insert a matching profile row, setting the role to teacher or admin:
insert into public.profiles (id, email, display_name, role)
values (
  'paste-the-user-id-from-auth-users',
  'you@example.com',
  'Your Name',
  'teacher'
);

You can now sign in at http://localhost:3000 and create your first course. From there, additional users can be invited through the application's UI, which writes to the email_whitelist table on your behalf.

11 Deploy to Vercel

Push to production

Vercel is the recommended host for Next.js applications and the path of least resistance for Gesso.

  1. Push your fork to GitHub if you have not already.
  2. Sign in to vercel.com/new and import the repository. Vercel auto-detects Next.js and fills in the build settings.
  3. Under Environment Variables, add the same three keys from your .env.local: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, and SUPABASE_SERVICE_ROLE_KEY. Apply them to all environments (Production, Preview, Development).
  4. Click Deploy. The first build takes two to four minutes.
  5. Once deployed, copy the production URL and add it to your Supabase project's Authentication → URL Configuration as both the Site URL and an allowed redirect.

Subsequent pushes to your default branch trigger automatic production deploys. Pull requests get their own preview URL, which is handy for review.

12 Troubleshooting

Common issues

Build fails with "Module not found"

Delete node_modules and .next, then run npm install again. Verify you are on Node 20 or later with node --version.

"Invalid API key" from Supabase

Re-copy the keys from Project Settings → API. Keys are scoped to a single project — using a key from the wrong project will fail silently or with cryptic errors. Restart the dev server after editing .env.local; Next.js does not pick up env changes automatically.

Sign-up redirects to localhost in production

Update the Site URL in Authentication → URL Configuration to your production domain, and add it to the allowed redirect URLs.

Files upload but cannot be downloaded

Check your Storage bucket policies. The most common cause is a bucket that is private (correct) but missing a SELECT policy for authenticated users who should have access.

Row Level Security errors

If queries return empty arrays when they should return data, inspect your RLS policies in the Supabase dashboard under Authentication → Policies. A missing policy is functionally identical to "no rows match."

Tailwind classes not applying

Tailwind v4 reads its content paths from the Next.js configuration automatically, but if you add new top-level directories, restart the dev server so the JIT compiler picks them up.

13 Next Steps

Once Gesso is running

With your instance up and your first admin account created, the day-to-day work happens inside the application. The User Manual covers everything from setting up a course and managing your roster to creating multi-stage assignments and returning marked drafts. Share it with the teachers, students, and tutors on your instance.