Add README for Quote Generator API with usage examples and features
This commit is contained in:
236
README.md
Normal file
236
README.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# Quote Generator API
|
||||
|
||||
Generate Twitter-style quote images programmatically. Perfect for creating social media content, screenshots, or fake tweets.
|
||||
|
||||
**Base URL:** `https://quotes.imbenji.net`
|
||||
|
||||
## Features
|
||||
|
||||
- 🎨 Twitter-authentic styling
|
||||
- 🖼️ Support for images and text-only tweets
|
||||
- 📸 High-resolution output (3240x3240)
|
||||
- ⚡ Built-in caching (24-hour TTL)
|
||||
- 🔒 Base64 image support
|
||||
- 🐳 Docker-ready
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### POST /generate
|
||||
|
||||
Generate a quote image using JSON request body.
|
||||
|
||||
**Request:**
|
||||
```bash
|
||||
curl -X POST https://quotes.imbenji.net/generate \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"displayName": "Geoff Marshall",
|
||||
"username": "@geofftech",
|
||||
"avatarUrl": "https://example.com/avatar.jpg",
|
||||
"text": "Does anyone else find it immensely satisfying when you turn a pocket inside out and get rid of the crumbs and fluff stuck in the bottom.",
|
||||
"imageUrl": null,
|
||||
"timestamp": 1499766270
|
||||
}' --output quote.png
|
||||
```
|
||||
|
||||
### GET /generate
|
||||
|
||||
Generate a quote image using query parameters.
|
||||
|
||||
**Request:**
|
||||
```bash
|
||||
curl "https://quotes.imbenji.net/generate?displayName=John%20Doe&username=@johndoe&text=Hello%20World×tamp=1735574400" --output quote.png
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `displayName` | string | No | Display name (defaults to "Anonymous") |
|
||||
| `username` | string | No | Twitter handle with @ (defaults to "@anonymous") |
|
||||
| `avatarUrl` | string | No | Avatar image URL or base64 data URI |
|
||||
| `text` | string | No | Tweet text content |
|
||||
| `imageUrl` | string | No | Tweet image URL, base64 data URI, or `null` |
|
||||
| `timestamp` | integer | No | Unix epoch timestamp in seconds |
|
||||
|
||||
## Response
|
||||
|
||||
- **Content-Type:** `image/png`
|
||||
- **Headers:**
|
||||
- `X-Cache`: `HIT` (served from cache) or `MISS` (newly generated)
|
||||
|
||||
## Examples
|
||||
|
||||
### Text-only tweet
|
||||
|
||||
```javascript
|
||||
fetch('https://quotes.imbenji.net/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
displayName: 'John Doe',
|
||||
username: '@johndoe',
|
||||
text: 'Just deployed my new API!',
|
||||
timestamp: Math.floor(Date.now() / 1000)
|
||||
})
|
||||
})
|
||||
.then(res => res.blob())
|
||||
.then(blob => {
|
||||
const url = URL.createObjectURL(blob);
|
||||
document.getElementById('img').src = url;
|
||||
});
|
||||
```
|
||||
|
||||
### Tweet with image
|
||||
|
||||
```javascript
|
||||
const response = await fetch('https://quotes.imbenji.net/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
displayName: 'Jane Smith',
|
||||
username: '@janesmith',
|
||||
avatarUrl: 'https://example.com/avatar.jpg',
|
||||
text: 'Check out this amazing view! 🌄',
|
||||
imageUrl: 'https://example.com/photo.jpg',
|
||||
timestamp: 1735574400
|
||||
})
|
||||
});
|
||||
|
||||
const blob = await response.blob();
|
||||
// Save or display the image
|
||||
```
|
||||
|
||||
### Using base64 images
|
||||
|
||||
```javascript
|
||||
fetch('https://quotes.imbenji.net/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
displayName: 'Alice',
|
||||
username: '@alice',
|
||||
avatarUrl: 'data:image/png;base64,iVBORw0KGgo...',
|
||||
text: 'Using base64 images works too!',
|
||||
imageUrl: 'data:image/jpeg;base64,/9j/4AAQSkZJ...',
|
||||
timestamp: 1735574400
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
### Python example
|
||||
|
||||
```python
|
||||
import requests
|
||||
import time
|
||||
|
||||
response = requests.post('https://quotes.imbenji.net/generate', json={
|
||||
'displayName': 'Python User',
|
||||
'username': '@pythonista',
|
||||
'text': 'Making API calls with Python!',
|
||||
'timestamp': int(time.time())
|
||||
})
|
||||
|
||||
with open('quote.png', 'wb') as f:
|
||||
f.write(response.content)
|
||||
```
|
||||
|
||||
### cURL with GET
|
||||
|
||||
```bash
|
||||
curl -G "https://quotes.imbenji.net/generate" \
|
||||
--data-urlencode "displayName=Test User" \
|
||||
--data-urlencode "username=@testuser" \
|
||||
--data-urlencode "text=This is a test tweet" \
|
||||
--data-urlencode "timestamp=1735574400" \
|
||||
--output quote.png
|
||||
```
|
||||
|
||||
## Caching
|
||||
|
||||
The API automatically caches generated images for 24 hours from the last request. Identical requests will be served from cache instantly.
|
||||
|
||||
- Cache hits include `X-Cache: HIT` header
|
||||
- Cache misses include `X-Cache: MISS` header
|
||||
- Cache is cleaned up hourly
|
||||
- Images are stored based on SHA-256 hash of parameters
|
||||
|
||||
## Timestamp Format
|
||||
|
||||
The `timestamp` parameter expects a Unix epoch timestamp in **seconds** (not milliseconds).
|
||||
|
||||
**JavaScript:**
|
||||
```javascript
|
||||
const timestamp = Math.floor(Date.now() / 1000);
|
||||
```
|
||||
|
||||
**Python:**
|
||||
```python
|
||||
import time
|
||||
timestamp = int(time.time())
|
||||
```
|
||||
|
||||
The timestamp will be formatted as: `5:58 PM · Dec 29, 2025`
|
||||
|
||||
## Default Avatar
|
||||
|
||||
If no `avatarUrl` is provided, a default Twitter-style placeholder avatar will be used.
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
Currently, there are no rate limits. Please use responsibly.
|
||||
|
||||
## Self-Hosting
|
||||
|
||||
### Docker (Recommended)
|
||||
|
||||
```bash
|
||||
git clone <repository>
|
||||
cd quotegen
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
The API will be available at `http://localhost:3000`
|
||||
|
||||
### Manual Setup
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
## Health Check
|
||||
|
||||
```bash
|
||||
curl https://quotes.imbenji.net/health
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"status": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Details
|
||||
|
||||
- **Resolution:** 3240x3240 (1:1 aspect ratio)
|
||||
- **Format:** PNG
|
||||
- **Max tweet width:** 450px (auto-scaled to fit)
|
||||
- **Cache TTL:** 24 hours from last access
|
||||
- **Cleanup interval:** Every hour
|
||||
|
||||
## Limitations
|
||||
|
||||
- Tweet text is not wrapped intelligently (use `\n` for line breaks if needed)
|
||||
- Very long tweets may be cut off
|
||||
- External image URLs must be publicly accessible
|
||||
- Base64 images should be reasonably sized
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions, please contact the maintainer.
|
||||
|
||||
---
|
||||
|
||||
**Built with:** Node.js, Express, node-html-to-image, Puppeteer
|
||||
Reference in New Issue
Block a user