Skip to content

Latest commit

 

History

History
259 lines (199 loc) · 9.1 KB

contributing.md

File metadata and controls

259 lines (199 loc) · 9.1 KB

Contributing to DARIAH-Campus

DARIAH-Campus is a combined discovery layer and hosting platform for DARIAH learning resources. This guide will help you understand the project architecture and how to contribute.

Technology stack

Core technologies

  • Next.js 15: The main framework for building the application
  • TypeScript 5: For type-safety
  • Tailwind CSS 3: For styles with utility classes
  • Node.js 22: Required runtime environment
  • pnpm 10: Package manager

Key Components

Keystatic CMS

  • Used for content management
  • Provides a user-friendly interface for content editing
  • Content is stored in MDX format
  • Authentication is handled via GitHub OAuth, which is configured via this GitHub App
  • Sign-in is available at /admin
  • Configuration can be found in keystatic.config.tsx
  • When developing locally, and no configuration for GitHub OAuth has been provided via environment variables, the CMS will save changes to the local filesystem and not commit to GitHub
  • Official docs: https://keystatic.com/docs

Typesense search

Project structure

.
├── app/                  # Next.js app router components
│   ├── (app)/            # Main application routes
│   └── (cms)/            # Keystatic CMS routes
├── config/               # Configuration
├── components/           # Shared components
├── content/              # Content files in MDX format
│   ├── en/               # English content
├── lib/                  # Shared utilities
│   ├── content/          # Content-related utilities
│   ├── i18n/             # Internationalization
│   ├── keystatic/        # Keystatic configuration and helpers
│   └── typesense/        # Typesense configuration and helpers
├── public/               # Static assets
└── scripts/              # Build and utility scripts

Components and utilities which are needed in more than one route should be saved in the top-level components and lib folders. Components and utilities which are only needed in a single route should instead be co-located with that route in a _components or _lib folder. For example:

.
└── app/
    └── (app)/
        └── search/
            ├── _components/    # Components for search UI
            └── _lib/           # Utilities for search

Naming conventions

The project follows Next.js app router conventions and uses kebab-case for file and folder naming These conventions are enforced with a lint rule:

"check-file/filename-naming-convention": [
  "error",
  {
    "**/*": "KEBAB_CASE",
  },
  { ignoreMiddleExtensions: true },
],
"check-file/folder-naming-convention": [
  "error",
  {
    "**/": "NEXT_JS_APP_ROUTER_CASE",
  },
],

Environment variables

All environment variables should be listed in .env.local.example, and validated at runtime with the schema defined in config/env.config.ts.

  • NEXT_PUBLIC_APP_BASE_URL: base url of deployment domain
  • NEXT_PUBLIC_REDMINE_ID: Redmine id needed for the acdh-ch imprint service
  • NEXT_PUBLIC_BOTS: whether web crawler are allowed to index the site. allowed values are "disabled" and "enabled". defaults to "disabled", but is set to "enabled" for production deployments on Vercel
  • ENV_VALIDATION: whether environment variable validation is enabled. allowed values are "disabled", "public" (which will only validate build-args prefixed with NEXT_PUBLIC_) and "enabled". defaults to "enabled"
  • NEXT_PUBLIC_MATOMO_BASE_URL and NEXT_PUBLIC_MATOMO_ID: configuration for Matomo analytics service
  • NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION: Google Search Console property verification token

Typesense

  • NEXT_PUBLIC_TYPESENSE_COLLECTION: Typesense collection name
  • NEXT_PUBLIC_TYPESENSE_HOST: Typesense server host
  • NEXT_PUBLIC_TYPESENSE_PORT: Typesense server port
  • NEXT_PUBLIC_TYPESENSE_PROTOCOL: Typesense server protocol
  • NEXT_PUBLIC_TYPESENSE_SEARCH_API_KEY: Typesense search-only api key, scoped to specific collection
  • TYPESENSE_ADMIN_API_KEY: Typesense admin secret

Keystatic

  • KEYSTATIC_GITHUB_CLIENT_ID: GitHub client id, necessary for GitHub OAuth
  • KEYSTATIC_GITHUB_CLIENT_SECRET: GitHub client secret, necessary for GitHub OAuth
  • KEYSTATIC_SECRET: Keystatic secret
  • NEXT_PUBLIC_KEYSTATIC_GITHUB_APP_SLUG: Identifier of the GitHub App used for authentication
  • NEXT_PUBLIC_KEYSTATIC_GITHUB_REPO_NAME: GitHub repository
  • NEXT_PUBLIC_KEYSTATIC_GITHUB_REPO_OWNER: GitHub organisation
  • NEXT_PUBLIC_KEYSTATIC_MODE: whether to store changes to the local filesystem, or commit changes to GitHub. defaults to "local", should be set to "github" in production

Content management

Content is managed using Keystatic CMS. The content structure includes:

  • Resources (events, external, hosted, pathfinders)
  • Curricula
  • Tags (Topics)
  • People
  • Sources
  • Documentation pages

Each content type is defined with a Keystatic collection schema in lib/keystatic/collections.ts.

Custom components, which can be used as rich-text editor widgets, are defined in lib/keystatic/collections.ts. To correctly render these custom components in the app, a React component must also be provided to the component mapping in mdx-components.tsx.

MDX content is transformed to React components with the processing pipeline defined in config/mdx.config.ts, which adds plugins to:

  • add support for GitHub flavored markdown (strikethrough, tables, etc.)
  • add support for footnotes
  • transform regular quotes and dashes into their typographic variants
  • add id attributes to headings, so they can be targeted by url-fragment links
  • extracts a table of contents
  • adds support for syntax-highlighting in code blocks

In production, GitHub branch protection rules enforce, that nobody (except repository administrators) are allowed to push changes directly to the main branch, but are required to create a new branch and open a pull request. The Keystatic UI helps doing that.

Search

The search functionality is powered by Typesense. The search schema is defined in lib/typesense/schema.ts.

Development setup for Typesense

  1. Start a local Typesense server

Create an api key and provide it as the TYPESENSE_ADMIN_API_KEY environment variable in .env.local. Then run:

pnpm run dev:typesense:up
  1. Create a search-only api key:
pnpm run typesense:api-key:create

This will print the api key to the console, which you then need to set as NEXT_PUBLIC_TYPESENSE_SEARCH_API_KEY in .env.local:

  1. Create and seed the collection:
pnpm run typesense:collection:create
pnpm run typesense:collection:seed

Metadata API

Metadata for the "resources" ("events", "external", "hosted", "pathfinders") and "curricula" collections is also available via API.

There are legacy API endpoints available at /api/metadata/:(curricula|events|resources), which simply serves a dump of legacy content (in the previous metadata format). New content is currently not added.

New API endpoints serving fresh metadata (in the updated metadata schema) are available at /api/v2/metadata/curricula and /api/v2/metadata/resources.

Development workflow

  1. Install dependencies:
pnpm install
  1. Copy the .env file template and set required environment variables:
cp .env.local.example .env.local
  1. Start development server
pnpm run dev
  1. Formatting, linting, and type-checking
pnpm run format:check
pnpm run lint:check
pnpm run types:check

Auto-fixable formatting and lint errors can be fixed with:

pnpm run format:fix
pnpm run lint:fix

Production deployment

The production app is hosted on Vercel. Every push to GitHub triggers a fresh deployment. Preview deployments from pull-request branches can be viewed publicly by pressing the "View deployment" button in the pull request comments.

The Vercel Dashboard, where environment variables and secrets can be set, is available at https://vercel.com/dariah/dariah-campus (invitation required).