@el_saintt/crispy-goggles
v1.1.0
Published
All-in-one portfolio data aggregator API - Includes core, all plugins, adapters, and CLI tools
Maintainers
Readme
@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?
- Why Use Crispy Goggles?
- Installation
- Quick Start
- Features
- Supported Platforms
- Usage
- Configuration
- API Reference
- CLI Commands
- Examples
- Contributing
- License
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
# Install separate packages for each platform
npm install @octokit/rest # GitHub
npm install googleapis # YouTube
npm install twitter-api-v2 # Twitter
npm install axios # For various REST APIs
# ... and many more
# Write custom integration code for each platform
# Manage 10+ different authentication methods
# Handle rate limiting, caching, errors separatelyWith Crispy Goggles
# One package, everything included
npm install @el_saintt/crispy-goggles// Simple, unified API
const client = new PortfolioClient();
client.use(GitHubPlugin.githubPlugin);
client.use(YouTubePlugin.youtubePlugin);
const data = await client.fetchAll();
// Get normalized data from all platformsInstallation
As a Library
npm install @el_saintt/crispy-gogglesOr with other package managers:
# Yarn
yarn add @el_saintt/crispy-goggles
# pnpm
pnpm add @el_saintt/crispy-goggles
# bun
bun add @el_saintt/crispy-gogglesCLI Tool (Global Install)
npm install -g @el_saintt/crispy-gogglesAfter global installation, you can use the crispy-goggles command anywhere.
Quick Start
1. Initialize Configuration
npx crispy-goggles initThis 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';
// Create client
const client = new PortfolioClient({
cache: { ttl: 3600 }, // Cache for 1 hour
rateLimit: { maxRequests: 10, perSeconds: 60 }
});
// Register plugins
client.use(GitHubPlugin.githubPlugin);
client.use(YouTubePlugin.youtubePlugin);
// Fetch data from all platforms
const allData = await client.fetchAll();
// Or fetch from specific platform
const githubData = await client.fetch('github');
console.log(allData);3. Test Your Configuration
npx crispy-goggles testThis 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:
| Platform | Data Types | Authentication | |----------|-----------|----------------| | 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 } }
}
});
// Register all plugins
client.use(GitHubPlugin.githubPlugin);
client.use(YouTubePlugin.youtubePlugin);
client.use(MediumPlugin.mediumPlugin);
client.use(DevToPlugin.devtoPlugin);
// Fetch from all platforms
const allData = await client.fetchAll();
// Or fetch individually
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 // 1 hour
})
});CLI Tools
Crispy Goggles includes a powerful CLI for managing your portfolio configuration.
Initialize Project
npx crispy-goggles initInteractive mode (default):
- Select platforms to configure
- Enter credentials interactively
- Generate configuration files
Non-interactive mode:
npx crispy-goggles init --no-interactive --services github,youtube,mediumTest Connections
# Test all services
npx crispy-goggles test
# Test specific service
npx crispy-goggles test github
# Test with verbose output
npx crispy-goggles test --verbose
# Test and fetch sample data
npx crispy-goggles test --fetchValidate Configuration
npx crispy-goggles validateValidates:
- Configuration file syntax
- Environment variables
- Credential formats
- API connectivity
Generate TypeScript Types
npx crispy-goggles typesGenerates type-safe helpers based on your configuration.
View Service Information
# List all available plugins
npx crispy-goggles plugins
# Get details about a specific service
npx crispy-goggles info githubFramework Adapters
Express.js
import express from 'express';
import { PortfolioClient, GitHubPlugin, ExpressAdapter } from '@el_saintt/crispy-goggles';
const app = express();
const client = new PortfolioClient({ /* config */ });
client.use(GitHubPlugin.githubPlugin);
// Use built-in middleware
app.use('/api/portfolio', ExpressAdapter.createRouter(client));
// Or create custom routes
app.get('/api/github', async (req, res) => {
const data = await client.fetch('github');
res.json(data);
});Next.js
// app/api/portfolio/route.ts
import { PortfolioClient, GitHubPlugin, NextJSAdapter } from '@el_saintt/crispy-goggles';
const client = new PortfolioClient({ /* config */ });
client.use(GitHubPlugin.githubPlugin);
export const GET = NextJSAdapter.createHandler(client);
// Or custom API route
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, // 1 hour
type: 'memory' // or 'redis'
},
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
GITHUB_USERNAME=your-username
GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
# YouTube
YOUTUBE_API_KEY=AIzaxxxxxxxxx
YOUTUBE_CHANNEL_ID=UCxxxxxxxxx
# Dev.to
DEVTO_API_KEY=xxxxxxxxxxxxx
# Twitter
TWITTER_BEARER_TOKEN=xxxxxxxxxxxxxAPI Reference
PortfolioClient
Main client for interacting with platform APIs.
const client = new PortfolioClient(config);Methods:
use(plugin)- Register a pluginfetch(serviceId)- Fetch data from specific servicefetchAll()- Fetch data from all registered servicesvalidateConfiguration()- Validate current configuration
Plugins
All plugins follow the same interface:
import { GitHubPlugin } from '@el_saintt/crispy-goggles';
client.use(GitHubPlugin.githubPlugin);Available plugins:
GitHubPlugin.githubPluginYouTubePlugin.youtubePluginMediumPlugin.mediumPluginDevToPlugin.devtoPluginTwitterPlugin.twitterPluginLinkedInPlugin.linkedinPluginInstagramPlugin.instagramPluginFigmaPlugin.figmaPluginStackOverflowPlugin.stackoverflowPluginSubstackPlugin.substackPlugin
CLI Commands
| Command | Description | Options |
|---------|-------------|---------|
| 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
# Clone the repository
git clone https://github.com/stElmitchay/crispy-goggles.git
# Install dependencies
pnpm install
# Build packages
pnpm build
# Run tests
pnpm test
# Watch mode
pnpm devLicense
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! 🥽✨
