Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Backend

REST API for the Raven scholarly publication platform. Handles publications, versioning, contributors, organizations, comments, notifications, and authentication.

Stack: Node.js 24 · TypeScript · Hono · MySQL (Drizzle ORM) · S3


Getting started

pnpm install

Copy and fill in raven.toml (see Configuration):

pnpm dev          # dev server with watch (port 7001)
pnpm build        # compile to dist/
pnpm start        # run compiled output

Database

pnpm db:migrate   # apply pending migrations
pnpm db:generate  # generate migrations from schema changes
pnpm db:push      # push schema directly (dev only)

db:migrate skips migrations unless MIGRATION_DATABASE_URI is set.


Configuration

The server reads raven.toml (or a path set via RAVEN_CONFIG). Environment variables override TOML values when set.

KeyDefaultDescription
DATABASE_URI—MySQL connection string (required)
MIGRATION_DATABASE_URI—Connection string for migrations (optional)
BASE_URL_WEB—Frontend origin (used in emails, CORS)
BASE_URL_ADMIN—Admin UI origin
BASE_URL_API—API origin
SERVER_HOST0.0.0.0Bind address
SERVER_PORT7001Listen port
JWT_SECRET_KEY—JWT signing secret (required)
BETTER_AUTH_SECRET—BetterAuth secret (required)
AWS_*—S3 credentials, bucket, and endpoint (set AWS_S3_ENDPOINT/AWS_S3_PUBLIC_ENDPOINT for a local (dev) S3-compatible service like MinIO)
MAILGUN_API_KEY—Outbound email
DATACITE_*—DOI registration credentials
DATACITE_PREFIX—DOI prefix for all minted DOIs. DOIs are only minted for organizations with DOI minting enabled.
DATACITE_PUBLISHERThe StacksPublisher name in DOI metadata. When it’s The Stacks, Astera Institute is also added as the hosting institution, so change it for other deployments.
ORCID_*—ORCID OAuth
GOOGLE_*—Google OAuth
Astera Specific Below--
LINEAR_*-Our contact-us form uses the data to crerate a linear task, which requires these keys

API routes

All routes are prefixed with /api.

PrefixPurpose
/authLogin, signup, token refresh, ORCID/Google SSO
/usersUser profiles, search, avatar upload
/publicationsPublications and versioned content
/commentsThreaded comments with text anchors
/orgsOrganization management
/filesServe files from IMG_DIR (local filesystem)
/notificationsIn-app and email notifications
/sitemapXML sitemap
/healthHealth check
Astera Specific Below-
/contact-us[Astera specific] Accepts form data that is submitted to linear, contingent on the above variables

Project structure

src/
├── index.ts          # Entry point — starts the server
├── app.ts            # Hono app, middleware, route wiring
├── config.ts         # Config loading from raven.toml
├── db/
│   ├── index.ts      # DB connection
│   └── schema.ts     # Drizzle schema
├── lib/
│   ├── auth.ts       # BetterAuth setup
│   ├── mail.ts       # Mailgun email
│   ├── media.ts      # S3 image upload
│   └── references.ts # Reference extraction
├── api-v0/           # v0 routes, also served under /api
└── api-v1/           # v1 routes

Testing

pnpm test         # run unit tests (vitest)
pnpm typecheck    # type-check without emitting
DATACITE_NAME="[user]" DATACITE_PASSWORD="[pass]" DATACITE_PREFIX="[prefix]" pnpm exec vitest run datacite-live.test  # Run datacite-live tests

Integration tests use tests/raven.test.toml and a real database. See the integration tests README for the full test environment setup.


Authentication