University of Peradeniya crestSCS Documentation
University of Peradeniya crestSCS Documentation
Department website

Start here

Repository handbookRepository overviewDevelopment

System design

ArchitectureAuthentication and authorizationPublic dataAPI contractsSchemas
UI system

Applications

Department Web applicationPeople applicationProjects applicationPortal application
Application internals
Portal internalsPortal routing and accessPortal editor state and mutationsPortal data loading and failures

Services

API serviceGitHub App serviceMailer service

Shared packages

Schemas packageUI packageTypeScript configuration packageESLint configuration package

Development workflow

Testing and verificationDependency managementDocumentation authoringUI quality assurance

Operations

Continuous integrationEnvironment variablesOperationsSecurityTroubleshooting

Reference

Route referenceGlossary
Application internalsPortal internals

Server data aggregation, API request behavior, nullable records, pagination, loading states, and error routing.

Portal data loading and failures

Portal pages prefer server-side loading for identity and initial editor data, then hand bounded initial state to interactive client components. All browser and server requests still go through services/api; Portal does not read D1 or private GitHub automation directly.

Server API client

src/lib/server/api-client.ts is marked server-only. It serializes the incoming request cookies, adds the configured X-Client-Id, disables fetch caching, and centralizes response behavior:

ResponsePortal behavior
2xxparse the expected JSON payload
401redirect through /logout to clear stale cookies
403redirect to /dashboard
404 on optional readreturn null when the loader permits a missing record
other failureparse the API error and throw PortalApiError

The generic type parameter describes the expected payload but does not validate untrusted JSON at runtime. Boundary validation belongs to the API. Client-side editors validate drafts with the owning shared schema before submission.

Parallel page loaders

Editor loaders request independent prerequisites concurrently:

  • public-profile loading combines the applicable profile schema, current or target profile, and pull-request status;
  • project loading combines the current user, field permissions, optional project, courses, and offerings;
  • course loading combines the current user, field permissions, optional course, optional pull request, and offerings.

This avoids request waterfalls. Preserve that shape when adding independent inputs, and do not introduce one API read per list item. Lists use cursor-based page endpoints with explicit limits rather than loading an unbounded collection.

User-visible pending and failure states

Route-level loading.tsx files provide skeletons shaped for the owning page. They should preserve the page's main geometry and must not imply that a record exists before the request finishes. App-level error, global-error, not-found, and global-not-found files cover failures at their corresponding Next.js boundaries.

Keep these states distinct in editor UI:

  • published describes the current public repository record;
  • draft describes local working data;
  • submitting means a request or operation is in progress;
  • succeeded means the durable operation completed successfully;
  • failed means a terminal operation or request failed.

Never label an accepted or queued operation as published. When a nullable read returns no record, render the relevant creation or unavailable state; do not convert unrelated transport failures into null.

Portal editor state and mutations

The shared editor state machine, form and JSON surfaces, validation, submission, and operation polling.

Docs application internals

Runtime map of the Fumadocs handbook, its source pipeline, navigation, search, metadata, and agent-readable outputs.

On this page

Portal data loading and failuresServer API clientParallel page loadersUser-visible pending and failure states