This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
60s API is a comprehensive API collection providing news, trending topics, and utility services. Built with Deno and Oak framework, it supports multiple runtime environments (Deno, Node.js, Bun) and deployment platforms (Docker, Cloudflare Workers).
# Development mode (port 4398)
pnpm run dev
# Production mode (port 4398)
pnpm run start
# Docker
pnpm run docker:build
pnpm run docker:run# Update all lockfiles
pnpm run update-lockfile
# Release new version (bumps version and creates git tag)
pnpm run release- Entry points:
deno.ts,node.ts,bun.ts,cf-worker.tsfor different runtimes - Main app:
src/app.ts- Oak application with middleware setup - Routing:
src/router.ts- centralized route definitions with/v2prefix - Modules:
src/modules/- individual API service implementations - Middlewares:
src/middlewares/- cross-cutting concerns (CORS, error handling, encoding)
- Common utilities:
src/common.ts- shared functions for JSON building, parameter extraction, date formatting - Configuration:
src/config.ts- environment-based settings - Encoding middleware: Handles
encodingquery parameter for response format transformation
Each API endpoint follows a consistent module pattern:
- Create service class in
src/modules/[name].module.ts - Implement
handle()method returning Oak RouterMiddleware - Handle different encoding formats in the middleware (see Response Formats below)
- Register route in
src/router.ts - Import and add to router configuration
Example structure:
export class MyModule {
async handle(): RouterMiddleware<any> {
return async (ctx) => {
const encoding = ctx.state.encoding
const data = await this.fetchData()
if (encoding === 'text') {
ctx.response.body = this.formatAsText(data)
} else if (encoding === 'markdown') {
ctx.response.body = this.formatAsMarkdown(data)
} else {
ctx.response.body = Common.buildJson(data)
}
}
}
}IMPORTANT: Unless specifically noted otherwise, ALL APIs MUST support these three encoding formats:
json(default) - structured JSON response viaCommon.buildJson()text- plain text format for terminal/script usagemarkdown- markdown formatted text for documentation/display
Special formats (only when explicitly needed):
image- redirect to image URLimage-proxy- proxied image contenthtml- HTML encoded output
ALWAYS use dayjs for time operations:
import { dayjs, TZ_SHANGHAI } from './common.ts'
// Get current time in Shanghai timezone
const now = dayjs().tz(TZ_SHANGHAI)
// Format date
const dateStr = now.format('YYYY-MM-DD')
// Parse and convert timezone
const parsedDate = dayjs(timestamp).tz(TZ_SHANGHAI)Default timezone: Always use TZ_SHANGHAI (Asia/Shanghai) for all time operations unless explicitly specified otherwise.
Response Building:
// Success response
ctx.response.body = Common.buildJson(data)
// Error response with custom message
ctx.response.status = 400
ctx.response.body = Common.buildJson(null, 400, 'Custom error message')
// Require arguments
if (!param) {
Common.requireArguments('paramName', ctx.response)
return
}Parameter Handling:
// Query parameters
const param = ctx.request.url.searchParams.get('param')
// Support both query and POST body (for large params)
const largeParam = await Common.getParam('param', ctx.request, true)Web Scraping:
// Always use Common.chromeUA for User-Agent
const response = await fetch(url, {
headers: { 'User-Agent': Common.chromeUA }
})Caching:
// Implement caching for expensive operations
const cache = new Map<string, { data: any; timestamp: number }>()
const CACHE_TTL = 30 * 60 * 1000 // 30 minutes
// Check cache before fetching
const cached = cache.get(key)
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data
}- Type Safety: Use TypeScript types, avoid
anywhen possible - Error Handling: Always handle fetch errors and invalid responses
- Validation: Validate required parameters using
Common.requireArguments() - Consistency: Follow existing code patterns in
src/modules/ - Documentation: Add JSDoc comments for complex functions
- Testing: Test all three encoding formats (json/text/markdown) when adding new APIs
From src/common.ts:
Common.buildJson()- Standard JSON response builderCommon.requireArguments()- Parameter validationdayjs/TZ_SHANGHAI- Time operations (prefer overCommon.localeDate()/Common.localeTime())Common.randomInt()/Common.randomItem()- Random utilitiesCommon.md5()- MD5 hashingCommon.qs()- Query string builderCommon.tryRepoUrl()- GitHub CDN fallback fetcher
Note: Common.localeDate() and Common.localeTime() are legacy utilities. For new code, always use dayjs with TZ_SHANGHAI timezone as shown in the Time Handling Standards section.