@el_saintt/crispy-goggles
A unified portfolio data aggregator that consolidates content from multiple platforms into a single, easy-to-use API
Crispy Goggles is an all-in-one TypeScript/JavaScript library that helps developers aggregate and display their portfolio content from various platforms (GitHub, YouTube, Medium, Twitter, LinkedIn, and more) through a single, consistent interface. Perfect for building developer portfolios, personal websites, and content dashboards.

Table of Contents
What is Crispy Goggles?
Crispy Goggles is a portfolio data aggregation platform that solves a common problem for developers and content creators: managing and displaying content from multiple platforms.
Instead of manually integrating with GitHub API, YouTube API, Medium RSS feeds, Twitter API, and others separately, Crispy Goggles provides:
- ✅ Unified interface - One consistent API for all platforms
- ✅ Built-in caching - Reduce API calls and improve performance
- ✅ Type safety - Full TypeScript support with generated types
- ✅ Error handling - Graceful degradation when services are unavailable
- ✅ Rate limiting - Automatic rate limit handling
- ✅ Easy setup - Interactive CLI for configuration
- ✅ Framework agnostic - Works with Express, Next.js, or any Node.js environment
The Problem It Solves
Building a developer portfolio that showcases your work across multiple platforms typically requires:
- Learning and integrating with 5-10 different APIs
- Managing authentication tokens and credentials for each service
- Implementing caching to avoid rate limits
- Handling errors and edge cases for each platform
- Normalizing data formats from different sources
- Maintaining all these integrations over time
Crispy Goggles does all of this for you in a single package.
Why Use Crispy Goggles?
Before Crispy Goggles
npm install @octokit/rest
npm install googleapis
npm install twitter-api-v2
npm install axios
With Crispy Goggles
npm install @el_saintt/crispy-goggles
const client = new PortfolioClient();
client.use(GitHubPlugin.githubPlugin);
client.use(YouTubePlugin.youtubePlugin);
const data = await client.fetchAll();
Installation
As a Library
npm install @el_saintt/crispy-goggles
Or with other package managers:
yarn add @el_saintt/crispy-goggles
pnpm add @el_saintt/crispy-goggles
bun add @el_saintt/crispy-goggles
CLI Tool (Global Install)
npm install -g @el_saintt/crispy-goggles
After global installation, you can use the crispy-goggles
command anywhere.
Quick Start
1. Initialize Configuration
npx crispy-goggles init
This interactive wizard will:
- Help you select which platforms to integrate
- Prompt for API credentials
- Generate configuration files
- Create environment variable templates
2. Use in Your Application
import { PortfolioClient, GitHubPlugin, YouTubePlugin } from '@el_saintt/crispy-goggles';
const client = new PortfolioClient({
cache: { ttl: 3600 },
rateLimit: { maxRequests: 10, perSeconds: 60 }
});
client.use(GitHubPlugin.githubPlugin);
client.use(YouTubePlugin.youtubePlugin);
const allData = await client.fetchAll();
const githubData = await client.fetch('github');
console.log(allData);
3. Test Your Configuration
npx crispy-goggles test
This will validate your credentials and test connectivity to all configured platforms.
Features
Core Features
- 🔌 10+ Platform Plugins - GitHub, YouTube, Medium, Dev.to, Twitter, LinkedIn, Instagram, Figma, Stack Overflow, Substack
- ⚡ Performance Optimized - Built-in caching with Redis or in-memory options
- 🛡️ Type Safe - Full TypeScript support with auto-generated types
- 🔄 Rate Limiting - Automatic rate limit handling and retry logic
- 📊 Unified Data Model - Consistent data structure across all platforms
- 🎨 Framework Adapters - Pre-built integrations for Express and Next.js
- 🛠️ Developer Tools - CLI for setup, testing, and validation
- 📝 Extensible - Easy to create custom plugins for additional platforms
Built-in Capabilities
- Caching System - Reduce API calls and improve response times
- Error Recovery - Graceful degradation when platforms are unavailable
- Credential Management - Secure handling of API tokens and secrets
- Data Transformation - Normalize data from different platforms
- Batch Operations - Fetch from multiple platforms in parallel
- Logging & Debugging - Comprehensive logging for troubleshooting
Supported Platforms
Crispy Goggles includes built-in support for these platforms:
GitHub | Repositories, stars, commits, issues, PRs | Personal access token |
YouTube | Videos, playlists, channel stats | API key |
Medium | Articles, publications | Username (RSS) |
Dev.to | Posts, reactions, comments | API key |
Twitter | Tweets, mentions, followers | Bearer token |
LinkedIn | Posts, connections, profile | OAuth 2.0 |
Instagram | Posts, stories, profile | Access token |
Figma | Files, projects, designs | Access token |
Stack Overflow | Questions, answers, reputation | API key (optional) |
Substack | Newsletter posts | Username (RSS) |
Note: Some platforms require API approval or developer accounts. Check each platform's documentation for specific requirements.
Usage
As a Library
Basic Usage
import { PortfolioClient, GitHubPlugin } from '@el_saintt/crispy-goggles';
const client = new PortfolioClient({
services: {
github: {
credentials: {
username: 'your-username',
token: process.env.GITHUB_TOKEN
}
}
}
});
client.use(GitHubPlugin.githubPlugin);
const repos = await client.fetch('github');
With Multiple Platforms
import {
PortfolioClient,
GitHubPlugin,
YouTubePlugin,
MediumPlugin,
DevToPlugin
} from '@el_saintt/crispy-goggles';
const client = new PortfolioClient({
cache: { ttl: 3600 },
services: {
github: { credentials: { username: 'user', token: process.env.GITHUB_TOKEN } },
youtube: { credentials: { apiKey: process.env.YOUTUBE_API_KEY, channelId: 'channel-id' } },
medium: { credentials: { username: '@username' } },
devto: { credentials: { apiKey: process.env.DEVTO_API_KEY } }
}
});
client.use(GitHubPlugin.githubPlugin);
client.use(YouTubePlugin.youtubePlugin);
client.use(MediumPlugin.mediumPlugin);
client.use(DevToPlugin.devtoPlugin);
const allData = await client.fetchAll();
const githubData = await client.fetch('github');
const youtubeData = await client.fetch('youtube');
With Caching
import { PortfolioClient, RedisCache } from '@el_saintt/crispy-goggles';
const client = new PortfolioClient({
cache: new RedisCache({
host: 'localhost',
port: 6379,
ttl: 3600
})
});
CLI Tools
Crispy Goggles includes a powerful CLI for managing your portfolio configuration.
Initialize Project
npx crispy-goggles init
Interactive mode (default):
- Select platforms to configure
- Enter credentials interactively
- Generate configuration files
Non-interactive mode:
npx crispy-goggles init --no-interactive --services github,youtube,medium
Test Connections
npx crispy-goggles test
npx crispy-goggles test github
npx crispy-goggles test --verbose
npx crispy-goggles test --fetch
Validate Configuration
npx crispy-goggles validate
Validates:
- Configuration file syntax
- Environment variables
- Credential formats
- API connectivity
Generate TypeScript Types
npx crispy-goggles types
Generates type-safe helpers based on your configuration.
View Service Information
npx crispy-goggles plugins
npx crispy-goggles info github
Framework Adapters
Express.js
import express from 'express';
import { PortfolioClient, GitHubPlugin, ExpressAdapter } from '@el_saintt/crispy-goggles';
const app = express();
const client = new PortfolioClient({ });
client.use(GitHubPlugin.githubPlugin);
app.use('/api/portfolio', ExpressAdapter.createRouter(client));
app.get('/api/github', async (req, res) => {
const data = await client.fetch('github');
res.json(data);
});
Next.js
import { PortfolioClient, GitHubPlugin, NextJSAdapter } from '@el_saintt/crispy-goggles';
const client = new PortfolioClient({ });
client.use(GitHubPlugin.githubPlugin);
export const GET = NextJSAdapter.createHandler(client);
export async function GET(request: Request) {
const data = await client.fetchAll();
return Response.json(data);
}
Configuration
Configuration File
Create portfolio.config.ts
:
import type { PortfolioConfig } from '@el_saintt/crispy-goggles';
export const config: PortfolioConfig = {
cache: {
ttl: 3600,
type: 'memory'
},
rateLimit: {
maxRequests: 10,
perSeconds: 60
},
services: {
github: {
credentials: {
username: process.env.GITHUB_USERNAME!,
token: process.env.GITHUB_TOKEN!
}
},
youtube: {
credentials: {
apiKey: process.env.YOUTUBE_API_KEY!,
channelId: process.env.YOUTUBE_CHANNEL_ID!
}
}
}
};
Environment Variables
Create .env.local
:
GITHUB_USERNAME=your-username
GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
YOUTUBE_API_KEY=AIzaxxxxxxxxx
YOUTUBE_CHANNEL_ID=UCxxxxxxxxx
DEVTO_API_KEY=xxxxxxxxxxxxx
TWITTER_BEARER_TOKEN=xxxxxxxxxxxxx
API Reference
PortfolioClient
Main client for interacting with platform APIs.
const client = new PortfolioClient(config);
Methods:
use(plugin)
- Register a plugin
fetch(serviceId)
- Fetch data from specific service
fetchAll()
- Fetch data from all registered services
validateConfiguration()
- Validate current configuration
Plugins
All plugins follow the same interface:
import { GitHubPlugin } from '@el_saintt/crispy-goggles';
client.use(GitHubPlugin.githubPlugin);
Available plugins:
GitHubPlugin.githubPlugin
YouTubePlugin.youtubePlugin
MediumPlugin.mediumPlugin
DevToPlugin.devtoPlugin
TwitterPlugin.twitterPlugin
LinkedInPlugin.linkedinPlugin
InstagramPlugin.instagramPlugin
FigmaPlugin.figmaPlugin
StackOverflowPlugin.stackoverflowPlugin
SubstackPlugin.substackPlugin
CLI Commands
init | Initialize configuration | --no-interactive , --services |
test [service] | Test API connections | --verbose , --fetch , --json |
validate | Validate configuration | --json , --config |
types | Generate TypeScript types | --output |
info <service> | Show service details | - |
plugins | List available plugins | --json |
Global Options:
-v, --verbose
- Enable verbose output
--json
- Output as JSON
-c, --config <path>
- Config file path
-e, --env <path>
- Environment file path
Examples
Building a Portfolio Dashboard
import { PortfolioClient, GitHubPlugin, YouTubePlugin, MediumPlugin } from '@el_saintt/crispy-goggles';
const client = new PortfolioClient({
cache: { ttl: 3600 }
});
client.use(GitHubPlugin.githubPlugin);
client.use(YouTubePlugin.youtubePlugin);
client.use(MediumPlugin.mediumPlugin);
async function getDashboardData() {
const data = await client.fetchAll();
return {
github: {
repos: data.github.repositories,
stars: data.github.totalStars
},
youtube: {
videos: data.youtube.recentVideos,
subscribers: data.youtube.subscriberCount
},
medium: {
posts: data.medium.articles
}
};
}
REST API Endpoint
import express from 'express';
import { PortfolioClient, GitHubPlugin } from '@el_saintt/crispy-goggles';
const app = express();
const client = new PortfolioClient();
client.use(GitHubPlugin.githubPlugin);
app.get('/api/stats', async (req, res) => {
try {
const data = await client.fetchAll();
res.json({ success: true, data });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});
app.listen(3000);
Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
git clone https://github.com/stElmitchay/crispy-goggles.git
pnpm install
pnpm build
pnpm test
pnpm dev
License
MIT © Portfolio API Contributors
Support
Why "Crispy Goggles"?
Because managing multiple platform integrations should be crystal clear (like looking through crispy, clean goggles) and not a blurry mess! 🥽✨