Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Optional for the public site. Copy this file to .env.local when needed.

# Neon PostgreSQL connection string; leave blank until database features are added.
# Example: postgresql://USER:PASSWORD@HOST/DATABASE?sslmode=require
DATABASE_URL=

# Better Auth is installed for future use; no auth routes are configured yet.
# Generate a secret with: openssl rand -base64 32
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=http://localhost:3000

# Resend API key and a sender address on your verified domain.
# Local email previews do not need these values.
RESEND_API_KEY=
RESEND_FROM_EMAIL=
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Next.js checks

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm lint
- run: pnpm build
87 changes: 0 additions & 87 deletions .github/workflows/docker-publish.yml

This file was deleted.

81 changes: 44 additions & 37 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,37 +1,44 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules/
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo

.env
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules/
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*
!.env.example

# React Email preview and exported templates
/.react-email/
/email-out/

# vercel
.vercel

# typescript
*.tsbuildinfo
/next-env.d.ts

/.yarn
/.yarnrc.yml
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- BEGIN:nextjs-agent-rules -->

## This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.

This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.

<!-- END:nextjs-agent-rules -->
111 changes: 96 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,96 @@
# Official Website

## About

This is the official website for the Manipal OSF organisation.

## Contributing

A prerequisite knowledge of [React](https://beta.reactjs.org/), [Next.js](https://nextjs.org/docs/getting-started), [TailwindCSS](https://tailwindcss.com/docs/installation) and basic HTML is required for the frontend and [PayloadCMS](https://payloadcms.com/docs/getting-started/what-is-payload) for the backend along with [docker](https://docs.docker.com/get-started/), [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions) for CI/CD.

Although if you are not familiar with any/all of these, you can still contibute in a particular domain or by finding bugs in the site.

## Additional Information

- If you are a sysadmin, check out [the configuration document](./backend/SERVER_CONFIG.md).
# Manipal OSF website

The official Manipal OSF website is a single Next.js application at the repository root. It uses TypeScript, React, Tailwind CSS, and the App Router. Blog posts live in the repository as Markdown files.

## Development

Use Node.js 24 LTS (minimum 22) and PNPM 11.2.2. Run commands from the repository root:

```sh
pnpm install
pnpm dev
```

Open http://localhost:3000. No environment variables or separate service are required for the existing site.

Development and production builds use Turbopack.

```sh
pnpm typecheck
pnpm lint
pnpm format
```

CI runs the production build with `pnpm build`. A deployed Node.js application starts with `pnpm start`. Configure hosting to use the repository root, with `pnpm install --frozen-lockfile` as the install command and `pnpm build` as the build command.

## Blog posts

See [website configuration](./WEBSITE_CONFIG.md) for the Markdown format, images, and publishing instructions. The blog initially displays “No posts yet.” Add your own content to `content/posts/`; existing hosted content is not copied automatically.

The `@next/mdx` component registry lives in `mdx-components.tsx` at the repository root, beside `app/`, as required by Next.js. Keep it there when adding MDX components. The filesystem blog continues to render Markdown using `MarkdownRenderer`.

## UI components

shadcn/ui is configured with the Base UI Nova style, TypeScript, React Server Components, Lucide icons, and the `@/*` import alias pointing to the repository root. Its CSS variables extend the existing Nord light and Catppuccin dark themes, using the existing `data-theme` switch.

Import the initial Button from `@/components/ui/button` and shared class helpers from `@/lib/utils`. Add more components from the repository root:

```sh
pnpm exec shadcn add input
```

`components.json` points to `styles/globals.css`; Tailwind v4 does not need a separate Tailwind configuration file. Keep the existing palettes and `data-theme` convention when adding theme tokens.

## Environment variables

The public site runs without service credentials. When preparing backend features, copy the example file:

```sh
cp .env.example .env.local
```

`lib/env.ts` uses T3 Env and Zod to validate settings during development and builds. Service settings are optional, and blank values are treated as unset. Values supplied must be valid. Import `env` from `@/lib/env` in server code instead of reading `process.env` directly. All settings below are server variables; do not expose credentials using `NEXT_PUBLIC_`.

| Variable | Purpose |
| -------------------- | -------------------------------------------------------------------------------------- |
| `DATABASE_URL` | Neon PostgreSQL connection string (`postgres://` or `postgresql://`). |
| `BETTER_AUTH_SECRET` | Future auth secret of at least 32 characters; generate with `openssl rand -base64 32`. |
| `BETTER_AUTH_URL` | Future auth server origin, such as `http://localhost:3000`. |
| `RESEND_API_KEY` | API key required when calling `getResend()`. |
| `RESEND_FROM_EMAIL` | Plain sender email address on a Resend-verified domain, for future sending features. |

Real `.env*` files are ignored by Git; `.env.example` contains no credentials and is tracked.

## Database and authentication

Drizzle ORM, Drizzle Kit, the Neon serverless driver, Better Auth, and its Drizzle adapter are installed for later use. Database clients, application/auth schemas, migrations, auth routes, and login pages are deferred. The blog still uses repository Markdown files.

When implementing these features, configure a Neon PostgreSQL database with the validated `DATABASE_URL`, use `drizzle-orm/neon-http` for HTTP queries (or `drizzle-orm/neon-serverless` when interactive transactions are needed), and connect Better Auth through `@better-auth/drizzle-adapter` with PostgreSQL provider `pg`. Generate the auth schema from the final auth configuration before creating Drizzle migrations. Add the auth Route Handler under `app/api/auth/[...all]/route.ts` and keep client auth code separate from server credentials.

Drizzle Kit runs outside the Next.js runtime. Before adding its configuration, use `@next/env` to load the root `.env*` files so CLI commands follow the same environment loading rules as Next.js.

## Email templates

Resend and React Email are ready for future email features. Components and rendering utilities use the current `react-email` package; `@react-email/ui` provides local previews.

```sh
pnpm email:dev
```

Open http://localhost:3001 to preview `emails/example.tsx`. Previews need no API key and send no email.

Server code can import `getResend` from `@/lib/resend` to obtain a lazily initialized Resend client. It throws a clear error if `RESEND_API_KEY` is unset when called. When adding a sending feature, pass a verified sender, recipient, subject, and React Email template to `getResend().emails.send(...)`, and handle the returned `error`. There are no sending endpoints or automatic email triggers yet.

## Server features

Add server endpoints as Route Handlers in `app/**/route.ts`, using the Web `Request` and `Response` APIs or Next.js `NextRequest` and `NextResponse`. Keep private environment variables server-side and put reusable server logic in `lib/`. Async Server Components, post metadata, and `generateStaticParams` call the server-only filesystem blog loader directly; it does not make HTTP calls.

Use a deployment that supports the Next.js Node.js runtime when adding Route Handlers or request-time server rendering.

## Page transitions

Internal site links use `components/TransitionLink` and `next-transition-router` to finish the current page's exit animation before navigating, then reset scroll and animate the new page in. The shared header and footer stay mounted. Browser Back/Forward uses native navigation and scroll restoration without page transitions. Use the transition-aware Link with `scroll={false}` when adding site navigation; external links and Markdown anchors retain normal browser behavior.

## Contributing

React, Next.js, TypeScript, Tailwind CSS, and basic HTML knowledge are useful. Contributions to content and bug reports are welcome too.
38 changes: 38 additions & 0 deletions WEBSITE_CONFIG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Website configuration

All source, public assets, and configuration are at the repository root. Run `pnpm dev` from this directory. No environment variables are needed for the existing site. Future server features can read private values from `.env.local`; never prefix secrets with `NEXT_PUBLIC_`.

## Write a blog post

Create `content/posts/your-post.md`:

```md
---
id: your-post
title: Your post title
authors:
- Your Name
publishDate: '2026-10-08'
status: draft
coverImage: /images/your-post.jpg
---

## Introduction

Write standard Markdown here, including **bold text**, links, fenced code blocks, and GitHub-flavored Markdown tables and task lists.
```

- `id` determines the URL (`/blog/your-post`), independently of the filename. IDs must be unique across drafts and published posts and contain only letters, numbers, underscores, or hyphens. Numeric IDs are supported for preserving existing URLs.
- `title` is a non-empty string; `authors` is a non-empty array of names.
- `publishDate` is a quoted, valid `YYYY-MM-DD` date. Published posts sort newest first. This date is display metadata, not a publishing schedule.
- `status` must be `draft` or `published`. Only published posts appear in the list or have public detail pages. There is no draft preview.
- `coverImage` is optional. Place the example image in `public/images/your-post.jpg`; omit this field to display the existing placeholder. Images must use local public paths beginning with a single `/`.
- The body supports Markdown rather than JSX or raw HTML. Start headings at `##`, since the page already renders the title as an `h1`.

The directory initially contains only `.gitkeep`, so the blog shows “No posts yet.” Invalid metadata and duplicate IDs produce errors identifying the offending post or ID.

## Publish

Change `status` to `published`, commit the Markdown and any images, and deploy. App Router Server Components and `generateStaticParams` generate blog pages during the production build; additions, edits, and removals require a rebuild and deployment. During development, the content loader reads files on each page request. Reload the page to see content changes; new published IDs work without restarting the dev server.

Unknown or draft post URLs return 404. Historical hosted posts must be exported and converted to this format separately, preserving their IDs if their existing URLs need to keep working.
Loading
Loading