Get started · Features · Update & back up · Configure · Website · Releases
Private accounts · Light & dark mode · Desktop & mobile
Your overview, from upcoming exams to the latest results. Screenshots use example data.
|
Use simple grades, fixed percentage shares or grouped assessments. Choose a grading scale per list, with optional school-year halves or four upper-secondary semesters. |
Plan upcoming exams, add results later and see which grades are still missing. |
|
Keep notes and attachments with each entry. Export your data as a ZIP or a readable PDF report. |
Follow selected lists in Apple Calendar, Outlook or another ICS-compatible calendar. |
|
Share an instance with separate accounts, admin-managed roles and optional two-factor authentication. |
Connect existing accounts to an OpenID Connect provider. Local sign-in remains available. |
Normal grade lists keep their existing calculation. Upper-secondary lists track calculated averages and received final grades separately. Different scales are never combined. The optional target calculator shows what one additional grade would need to achieve. See the releases for release notes.
Requires Docker with Compose v2, curl and OpenSSL. Docker images are available for amd64 and arm64; no Node.js installation is needed on the host.
Run the installer in a new directory:
mkdir -p gradeshelf
cd gradeshelf
curl -fSL --proto '=https' --proto-redir '=https' \
https://raw.githubusercontent.com/14flavius/GradeShelf/main/scripts/install.sh \
-o install.sh &&
sh install.shFollow the prompts for the instance name, browser URL, port and listen address.
Use the exact URL you will open in your browser, including https:// behind a
reverse proxy. The installer creates the configuration and starts GradeShelf.
For an existing installation, follow Updates and backups.
Open the URL you configured during installation.
| Username | Initial password |
|---|---|
gradeshelf |
gradeshelf0000 |
Important
Change the initial password when prompted, before making the instance public.
Create accounts and manage roles in Admin. There is no public registration; administrators cannot view another user's grades or files. Personal settings, including two-factor authentication, are under Settings.
Customized installations with subject categories and course half-years must use the import procedure below before starting the new version.
For regular installations, back up and update from your installation directory:
sh scripts/backup.sh && docker compose pull && docker compose up -d --waitKeep your existing .env and data/ directory. Regular installations keep their
accounts, grades and attachments; database migrations run automatically on startup.
If you pin an image version, update GRADESHELF_IMAGE
first. New images are available once the release build finishes.
To create a backup without updating:
sh scripts/backup.shThe backup briefly stops a running instance, saves its data and configuration to
backups/, then starts it again. Keep a protected copy outside the server.
The database and uploads live in ./data; preserve this directory when replacing containers.
Restore a backup
Stop the app and restore a backup marked COMPLETE into a separate recovery directory:
copy .env, the full data/ directory and the saved Compose file. Restore
docker-compose.yml.backup as docker-compose.yml.
Use the matching image version and ensure data/ is writable by UID/GID 1000.
Verify the restored installation before replacing the original. Downgrading the
Docker image alone does not undo database migrations.
The importer supports the customized v1.2.0 schema with subject categories, grade groups and four course half-years. Stop the old instance and back up its data and configuration. From a v1.3.0 development checkout, preview the import:
npm run import:legacy -- --source /path/to/source-data --target /path/to/new-dataAdd --apply to import into a new, nonexistent directory. The source stays unchanged;
accounts and attachments are retained. Use the standard Compose configuration with the
imported directory mounted at /data and keep the existing BETTER_AUTH_SECRET. Remove
old app-custom mounts that replace application files, then start v1.3.0.
Review any unassigned periods or types; final grades are not inferred from averages.
Invalid weights or relationships stop the import. The source database and uploads are
required; SQL migration scripts alone do not contain your data.
Edit .env in your installation directory, then apply changes:
docker compose up -d --pull never --wait| Setting | Purpose |
|---|---|
BETTER_AUTH_URL |
Full browser URL, such as https://grades.example.com. Subpaths are not supported. |
PORT |
Published HTTP port on the host, usually 3000. |
BIND_ADDRESS |
127.0.0.1 for local access or a proxy on the same host; 0.0.0.0 for LAN access. |
GRADESHELF_IMAGE |
Optional fixed image, e.g. ghcr.io/14flavius/gradeshelf:1.3.0. Defaults to latest. |
Keep the generated BETTER_AUTH_SECRET and COMPOSE_PROJECT_NAME unchanged.
For HTTPS, terminate TLS at your reverse proxy and forward to GradeShelf's HTTP
port. A proxy in another container needs network access to the app; its localhost
is separate from the host's.
Change the display name, legal notice and administrator contact in
Admin → Instance settings. See .env.example and
docker-compose.yml for all deployment options.
- Register a confidential OIDC client with your provider using Authorization
Code with PKCE (S256) and scopes
openid profile email. Useclient_secret_basicorclient_secret_postand ensure an email address is supplied. - In Admin → Advanced features → SSO login, enter the exact issuer URL, client ID and client secret. Register the displayed callback URL with your provider, check the configuration, then enable SSO and save.
- Sign in locally and connect your account under Settings → Security → SSO login. Use Confirm local sign-in if prompted. Future visits can use the SSO login button.
Use HTTPS and make sure the provider is reachable from both GradeShelf and your browser. SSO connects existing accounts; it does not create users or synchronize roles. Keep a local administrator login available and configure SSO two-factor authentication at the provider.
Saving SSO settings ends existing SSO sessions. If the issuer or client ID changes, users must reconnect their accounts. Signing out of GradeShelf does not sign out of the provider. To block access immediately, deactivate the account in GradeShelf; a provider-only suspension does not end existing GradeShelf sessions.
Upload limits
Add these optional settings to .env and ensure they are passed through in your
docker-compose.yml:
| Setting | Default | Allowed values |
|---|---|---|
UPLOAD_MAX_FILE_MB |
10 |
1–100 MiB per file |
UPLOAD_MAX_FILES_PER_ENTRY |
10 |
1–100 files per entry |
UPLOAD_MAX_USER_GB |
0 (unlimited) |
0–1024 GiB of attachments per user; decimals allowed |
Lowering a limit does not delete existing files.
Multiple instances
Use a separate directory, Compose project name and host port for each instance. Use separate hostnames for independent browser logins; cookies are shared across ports on the same hostname. Run one app instance per database on local disk.
Questions or problems? Open an issue.
For startup problems, check docker compose logs --tail=100 and
docker compose ps. Remove secrets and personal information before sharing logs.
To create an additional administrator from the terminal:
docker compose exec gradeshelf npm run admin:createRun locally and check your changes
Use Node.js 24.11+ within the Node 24 release line. The app uses Next.js, TypeScript, Tailwind, Better Auth and Prisma.
git clone https://github.com/14flavius/GradeShelf.git gradeshelf
cd gradeshelf
sh scripts/setup.sh
npm ci
npm run db:generate
npm run db:init
npm run dev -- --hostname 127.0.0.1Checks: npm run lint, npm run format:check, npm run typecheck,
npm run db:validate, npm run build. On existing databases, apply migrations
with npm run db:deploy; never reset them.
Install GradeShelf · Get help · Visit the website
By Flavius Hager · MIT License
Most of the original GradeShelf foundation was vibe-coded with AI assistance.