Conduit API with Reading Time
A social blogging platform API built with Express, TypeScript, and Prisma. This implementation includes a readingTime field on all article responses.
Features
- Reading Time Calculation: Every article response includes a
readingTimefield (integer) calculated asMath.ceil(wordCount / 200) - User authentication (register, login)
- Article CRUD operations
- Article favoriting
- Article feed
- Tag support
Reading Time Implementation
The readingTime field appears on every article in all API responses:
POST /api/articles- Create articleGET /api/articles/:slug- Get single articlePUT /api/articles/:slug- Update articlePOST /api/articles/:slug/favorite- Favorite articleDELETE /api/articles/:slug/favorite- Unfavorite articleGET /api/articles- List articlesGET /api/articles/feed- Get feed
Calculation
function calculateReadingTime(body: string): number {
const words = body.trim().split(/\s+/).length;
return Math.ceil(words / 200);
}
- Splits article body by whitespace to count words
- Divides by 200 words per minute
- Rounds up using
Math.ceil() - Returns an integer
Setup
- Install dependencies:
npm install - Set up environment variables:
cp .env.example .env
Edit .env with your database credentials.
- Run database migrations:
npm run prisma:migrate - Generate Prisma client:
npm run prisma:generate
Development
npm run dev
Testing
npm test
The test suite includes comprehensive tests for the readingTime field across all endpoints.
API Response Examples
Create Article Response
{
"article": {
"slug": "test-article-xyz123",
"title": "Test Article",
"description": "A test article",
"body": "Article body with content...",
"tagList": ["test"],
"createdAt": "2026-09-11T12:00:00.000Z",
"updatedAt": "2026-09-11T12:00:00.000Z",
"favorited": false,
"favoritesCount": 0,
"readingTime": 2,
"author": {
"username": "johndoe",
"bio": null,
"image": null,
"following": false
}
}
}
List Articles Response
{
"articles": [
{
"slug": "article-1",
"title": "Article 1",
"description": "Description",
"body": "Body...",
"tagList": ["tech"],
"createdAt": "2026-09-11T12:00:00.000Z",
"updatedAt": "2026-09-11T12:00:00.000Z",
"favorited": false,
"favoritesCount": 5,
"readingTime": 3,
"author": {...}
}
],
"articlesCount": 1
}
Implementation Details
Key Files
src/utils/readingTime.ts- Reading time calculation functionsrc/utils/formatArticle.ts- Article response formatter (includes readingTime)src/routes/articles.ts- Article endpointssrc/types/article.ts- TypeScript types with readingTime fieldsrc/tests/articles.test.ts- Comprehensive test suite
Architecture
The implementation uses a centralized formatArticle function that:
- Retrieves article data from Prisma
- Calculates reading time from the article body
- Formats the response with all required fields including
readingTime - Returns consistent structure across all endpoints
This ensures the readingTime field is present on every article response without duplication.