- Node.js 18+
- pnpm 8+
- Docker (for local services)
pnpm installCopy the example environment file:
cp docs/env.example .envEdit .env with your settings. Minimum required:
NEXT_PUBLIC_API_BASE=http://localhost:4000
PORT=4000
REDIS_URL=redis://localhost:6379# Start Redis, Typesense, Meilisearch
docker-compose up -d# Start both API and web
pnpm dev
# Or separately
pnpm dev:api # API on :4000
pnpm dev:web # Web on :3000apps/
├── web/ # Next.js frontend
│ ├── app/ # App Router pages
│ │ ├── page.tsx # Home page
│ │ ├── results/ # Search results
│ │ └── paper/[id]/ # Paper detail page
│ ├── components/ # React components
│ └── lib/ # Utilities
│
└── api/ # Fastify API
├── src/
│ ├── index.ts # Main server
│ ├── sources/ # Data source connectors
│ └── lib/ # Core libraries
│ ├── search-pipeline.ts
│ ├── enhanced-search-pipeline.ts
│ ├── cache.ts
│ └── ...
└── seed.ts # Data seeding script
packages/
├── shared/ # Shared TypeScript types
└── search/ # Search backend adapters
- Create Connector
Create apps/api/src/sources/newsource.ts:
import { SourceConnector, OARecord } from '@open-access-explorer/shared';
export class NewSourceConnector implements SourceConnector {
constructor(private baseUrl: string) {}
async search(params: {
doi?: string;
titleOrKeywords?: string;
yearFrom?: number;
yearTo?: number;
}): Promise<OARecord[]> {
// Implement search logic
return [];
}
}- Add to Aggregator
Update apps/api/src/lib/aggregators.ts to include the new source.
- Update Types
Add source identifier to packages/shared/src/types.ts if needed.
- Create Adapter
Create packages/search/src/newsource.ts:
import { SearchAdapter, OARecord } from '@open-access-explorer/shared';
export class NewSearchAdapter implements SearchAdapter {
async ensureIndex(): Promise<void> {}
async upsertMany(records: OARecord[]): Promise<void> {}
async search(params: any): Promise<any> {
return { hits: [], total: 0, facets: {} };
}
}- Export
Add to packages/search/src/index.ts.
- Configure
Update API server to support the new backend.
# Run linting
pnpm lint
# Type checking
pnpm buildThe API server uses structured logging. Set log level:
NODE_ENV=development # Debug logs
NODE_ENV=production # Info logs only# Check Redis
redis-cli
> KEYS *
> GET cache:search:...
# Clear cache via API
curl -X POST http://localhost:4000/api/cache/clear# Get performance stats
curl http://localhost:4000/api/performance/monitor
# Run performance test
curl -X POST http://localhost:4000/api/performance/test \
-H "Content-Type: application/json" \
-d '{"service": "openalex", "baseUrl": "https://api.openalex.org", "endpoint": "/works"}'pnpm seedpnpm cleanpnpm build- TypeScript: Strict mode enabled
- Formatting: Prettier (if configured)
- Linting: ESLint with Next.js config
- Imports: Absolute paths preferred
# Find process using port
lsof -i :4000
lsof -i :3000
# Kill process
kill -9 <PID># Check Redis is running
redis-cli ping
# Restart Redis
docker-compose restart redis- Verify Redis connection
- Check cache configuration in
.env - Review cache manager logs
- Clear cache and retry