Lexiverse
Lexiverse - AI contextual reading engine for English learners. Your next article is your next review.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A comprehensive digital publishing platform for academic and scientific journals by DigitoPub, built with Next.js, Prisma, and MySQL.
Clone the repository
git clone <repository-url>
cd scientific-journals-website
Install dependencies
npm install
# or
bun install
Set up environment variables
cp .env.example .env
Edit .env and configure your database credentials:
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_NAME=scientific_journals
DATABASE_USER=app_user
DATABASE_PASSWORD=your_password
# Optional: OJS Integration
OJS_DATABASE_HOST=localhost
OJS_DATABASE_NAME=ojs_db
OJS_DATABASE_USER=ojs_readonly
OJS_DATABASE_PASSWORD=readonly_password
Start MySQL with Docker (Optional)
docker-compose up -d
This will start MySQL 8.0 with automatic schema initialization.
Run database migrations (if not using Docker)
mysql -u app_user -p scientific_journals < scripts/001_create_tables.sql
mysql -u app_user -p scientific_journals < scripts/002_insert_sample_data.sql
Generate Prisma Client
npx prisma generate
# or
bunx prisma generate
Start the development server
npm run dev
Visit http://localhost:3000 to see your application.
This project uses MySQL (migrated from PostgreSQL) with the following key features:
# Verify MySQL connection
npm run db:verify
# or
bun run db:verify
# Run migrations manually
npm run db:migrate
# or
bun run db:migrate
# Seed with sample data
npm run db:seed
# or
bun run db:seed
The system operates across two strict boundaries:
The primary content flow is author → DigitoPub → SubmitManager/OJS → canonical OJS data → DigitoPub sync → public reader. The read mirror is refreshed by scheduled full syncs and drift detection. Approved admin writes, such as specialization changes, use a separate audited user-bridge path with queued retries; specialization remains digitopub-owned and is not read back.
Download the interactive architecture diagram (self-contained HTML with light/dark themes and export) · PNG preview
digitopub now holds TWO independent identity systems:
auth_token cookie, JWT via jose): unchanged. Used for /admin/* routes only. Helpers live in src/lib/db/auth.ts.digitopub_identity cookie, HMAC-signed): added by UIET-P1. Used to gate non-OA PDF actions and attribute engagement events. ORCID is the SOLE identity provider — digitopub never sees passwords, never validates credentials, never stores email/password tuples. Helpers live in src/lib/identity-cookie.ts.The two cookies are wholly separate code paths and MUST NOT cross-pollinate.
/account/stats (their own engagement breakdown) and /account/data (right-to-erasure). The OAuth flow round-trips through orcid.org and returns the user to the page they came from.digitopub_identity is HMAC-signed (IDENTITY_COOKIE_SECRET), 30 min sliding expiry, 8 h absolute expiry, ±2 min skew tolerance. Host-only on digitopub.com, httpOnly; Secure; SameSite=Lax./api/pdf-proxy serves any galley to any visitor. The proxy may inspect the cookie for attribution but never blocks. An earlier draft of UIET-P1 gated non-OA PDFs; that gate was dropped before launch on open-access principle.ENABLE_ORCID_OJS_BACKFILL=true, we write the ORCID iD back into OJS user_settings. Every such write is audited in audit_ojs_writes. Default OFF in production.user_event rows are written for every view, download, and citation export. The digitopub_consent cookie controls what is recorded:
all — orcid (when signed in), daily-rotating IP hash, daily-rotating UA hash.essential_only — orcid only; no IP/UA.pre_consent (no choice yet) — fully anonymous: source='pre_consent', no orcid, no IP/UA.Aggregation crons live in scripts/aggregate-daily-metrics.ts, aggregate-monthly-metrics.ts, update-user-metrics.ts, and retention-cleanup.ts.
Single Sign-On (SSO) for the registration path is still a one-way token-based bootstrap used exclusively after a new user registers on digitopub. The registration API provisions the user in OJS and redirects them with a 5-minute expiry HMAC token to log them securely into OJS the very first time. SSO is not used for returning users.
getSession() or jose.jwtVerify in any public route (under app/ excluding app/admin/**, or under src/server/routes/). The ESLint rule no-restricted-imports enforces this; CI greps as a backup.getIdentity(request) from src/lib/identity-cookie.ts for public-user identity. It is sibling to admin auth, never invokes it.src/lib/ojs-write-guard.ts (writeOrcidToOjsWithAudit() and setJournalSpecializationInOjsWithAudit()). Every write produces an audit row.UIET_P1_ENABLED until the rollout finishes.getSession() in a public route: that is the admin pathway. Use getIdentity().src/lib/ojs-write-guard.ts so it lands in audit_ojs_writes.The system enforces a strict Dual Authentication Model where public users are isolated from the admin gateway.
When a new user registers on digitopub, a secure backend-to-backend provisioning process occurs:
ojs-user-bridge.php on the OJS server via a Bearer-authenticated POST request.base64(payload).signature) valid for 5 minutes.sso_login.php?token=... on the OJS domain.sso_login.php validates the token via digitopub's GET /api/ojs/sso/validate and initializes a native OJS session.sequenceDiagram
participant U as User (Browser)
participant DP as Digitopub (Next.js)
participant Bridge as ojs-user-bridge.php (OJS)
participant DB as OJS MySQL
participant SSO as sso_login.php (OJS)
U->>DP: Submit Registration Wizard
DP->>Bridge: POST /ojs-user-bridge.php (API Key)
Bridge->>DB: INSERT INTO users/user_settings
Bridge-->>DP: HTTP 201 Created
DP->>DP: Sign Stateless HMAC Token
DP-->>U: Redirect to sso_login.php?token=...
U->>SSO: GET /sso_login.php?token=...
SSO->>DP: GET /api/ojs/sso/validate?token=...
DP-->>SSO: { valid: true, email: "..." }
SSO->>SSO: Bootstrap native OJS Session
SSO-->>U: 302 Redirect to Submission Wizard
digitopub acts as a purely stateless gateway for returning users.
<Link> to the OJS submission wizard.POST /api/ojs/sso) that generates tokens based on client-provided emails.Create read-only MySQL user
CREATE USER 'ojs_readonly'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT ON ojs_db.* TO 'ojs_readonly'@'localhost';
FLUSH PRIVILEGES;
Test OJS connection
npm run ojs:verify
# or
bun run ojs:verify
Run initial sync
npm run ojs:sync
# or
bun run ojs:sync
Set up automated sync (optional)
# Add to crontab (runs every 6 hours)
0 */6 * * * cd /path/to/app && bun run scripts/ojs-sync-cron.ts >> /var/log/ojs-sync.log 2>&1
# Development
npm run dev # Start dev server (or bun run dev)
npm run build # Build for production (or bun run build)
npm run start # Start production server (or bun run start)
# Database
npm run db:migrate # Run MySQL migrations (or bun run db:migrate)
npm run db:seed # Seed database (or bun run db:seed)
npm run db:verify # Test database connection (or bun run db:verify)
# OJS Integration
npm run ojs:verify # Test OJS connection (or bun run ojs:verify)
npm run ojs:sync # Sync data from OJS (or bun run ojs:sync)
# Prisma
npx prisma generate # Generate Prisma client (or bunx prisma generate)
npx prisma studio # Open Prisma Studio GUI (or bunx prisma studio)
scientific-journals-website/
├── app/ # Next.js app directory
│ ├── admin/ # Admin dashboard pages
│ └── api/ # API routes
├── components/ # React components
├── lib/ # Utility libraries
│ ├── ojs-client.ts # OJS database client
│ ├── ojs-models.ts # OJS TypeScript types
│ └── ojs-service.ts # OJS business logic
├── prisma/
│ └── schema.prisma # Prisma schema (MySQL)
├── scripts/
│ ├── 001_create_tables.sql # Database schema
│ ├── 002_insert_sample_data.sql # Sample data
│ ├── ojs-sync-cron.ts # OJS sync script
│ ├── verify-mysql-connection.ts # MySQL test
│ └── verify-ojs-connection.ts # OJS test
└── docker-compose.yml # MySQL Docker setup
This project was migrated from PostgreSQL to MySQL. Key changes:
| Feature | PostgreSQL | MySQL |
|---|---|---|
| Primary Keys | UUID | BIGINT AUTO_INCREMENT |
| Arrays | TEXT[] | JSON |
| JSON | JSONB | JSON |
| Timestamps | TIMESTAMPTZ | DATETIME |
| Auth | Row Level Security | Application-level |
# Test MySQL connection
npm run db:verify
# Check MySQL is running
docker-compose ps
# or
systemctl status mysql
# Test OJS connection
npm run ojs:verify
# Check OJS credentials in .env
echo $OJS_DATABASE_HOST
# Regenerate Prisma client
bunx prisma generate
# Reset database (⚠️ deletes all data)
bunx prisma migrate reset
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)This project is private and proprietary.
Built with ❤️ by DigitoPub using Next.js, Prisma, and MySQL