@quikturn/logos
May 29, 2026 · View on GitHub
TypeScript SDK for the Quikturn Logos API -- fetch any company's logo by domain name.
Get your API key -- free tier available, no credit card required.
| Package | Description | Install |
|---|---|---|
@quikturn/logos | Core SDK -- URL builder, browser client, server client, web component | pnpm add @quikturn/logos |
@quikturn/logos-react | React components -- logo, carousel, grid | pnpm add @quikturn/logos-react |
@quikturn/logos-next | Next.js -- next/image wrapper, loaders, server helpers | pnpm add @quikturn/logos-next |
@quikturn/logos-vue | Vue 3 components -- logo, carousel, grid, plugin | pnpm add @quikturn/logos-vue |
@quikturn/logos-svelte | Svelte 5 components -- logo, carousel, grid, runes | pnpm add @quikturn/logos-svelte |
@quikturn/logos-angular | Angular 17+ -- standalone components, signals, pipe | pnpm add @quikturn/logos-angular |
Install
pnpm add @quikturn/logos
Requires Node.js >= 18. Works with pnpm, npm, or yarn.
Need an API key? Sign up at getquikturn.io -- takes 30 seconds.
Pick Your Entry Point
| Entry Point | Import | Use Case |
|---|---|---|
| Universal | @quikturn/logos | URL builder, types, constants -- zero dependencies, any runtime |
| Browser | @quikturn/logos/client | Blob URLs, retry/backoff, scrape polling, events |
| Server | @quikturn/logos/server | Buffer output, streaming, batch operations |
| Element | @quikturn/logos/element | <quikturn-logo> web component with built-in attribution |
Framework Packages
| Package | Import | Framework |
|---|---|---|
| React | @quikturn/logos-react | React 18+ -- components, hooks, context |
| Next.js | @quikturn/logos-next | Next.js 14+ -- next/image wrapper, server helpers |
| Vue | @quikturn/logos-vue | Vue 3.3+ -- SFCs, composables, plugin |
| Svelte | @quikturn/logos-svelte | Svelte 5 -- runes, snippets, context |
| Angular | @quikturn/logos-angular | Angular 17+ -- standalone components, signals, pipe |
Quick Start
URL Builder
The simplest way to get a logo URL. Runs everywhere -- browsers, Node.js, edge runtimes -- with no network calls.
import { logoUrl } from "@quikturn/logos";
const url = logoUrl("github.com");
// => "https://logos.getquikturn.io/github.com"
const url = logoUrl("stripe.com", {
token: "qt_abc123",
size: 256,
format: "webp",
greyscale: true,
theme: "dark",
});
Search
Search for company logos by name or domain:
import { searchLogos } from "@quikturn/logos";
const results = await searchLogos({
q: "stripe",
token: "pk_live_xxx",
});
for (const result of results.results) {
console.log(result.domain, result.logoUrl);
}
SSR Note:
searchLogosdeduplicates concurrent identical requests at the module level. In server-side rendering environments, pass anAbortSignalto bypass deduplication and ensure per-request isolation. Note: providing your own signal opts out of the default 10-second fetch timeout — useAbortSignal.timeout(10000)(or your preferred duration) to prevent hung requests in server environments.
Search Options
| Option | Type | Default | Description |
|---|---|---|---|
q | string | required | Search query |
mode | "autocomplete" | "search" | "autocomplete" | Search mode |
page | number | 1 | Page number |
limit | number | 10 (autocomplete) / 25 (search) | Results per page. Capped at 20 (autocomplete) / 100 (search). |
filters | SearchFilters | — | Optional field filters |
sort | string | — | Sort expression |
token | string | — | API token (publishable key) |
baseUrl | string | — | Override API base URL (staging) |
signal | AbortSignal | — | Optional AbortSignal for request cancellation |
Browser Client
import { QuikturnLogos } from "@quikturn/logos/client";
const client = new QuikturnLogos({ token: "qt_your_publishable_key" });
const { url, blob, contentType } = await client.get("github.com", {
size: 256,
format: "webp",
});
document.querySelector("img")!.src = url;
// Clean up blob URLs when done
client.destroy();
Server Client
import { QuikturnLogos } from "@quikturn/logos/server";
const client = new QuikturnLogos({ secretKey: "sk_your_secret_key" });
// Single logo
const { buffer, contentType } = await client.get("github.com");
// Batch fetch
for await (const result of client.getMany(["github.com", "stripe.com", "vercel.com"])) {
if (result.success) console.log(`${result.domain}: ${result.buffer!.byteLength} bytes`);
}
// Stream to file
import { createWriteStream } from "node:fs";
import { Readable } from "node:stream";
const stream = await client.getStream("github.com", { format: "png" });
Readable.fromWeb(stream).pipe(createWriteStream("logo.png"));
Web Component
No framework needed. Import the element entry and use it in plain HTML:
<script type="module">
import "@quikturn/logos/element";
</script>
<quikturn-logo domain="github.com" token="qt_abc123" size="64"></quikturn-logo>
Renders the logo with a "Powered by Quikturn" attribution badge protected by shadow DOM.
React
pnpm add @quikturn/logos-react
import { QuikturnProvider, QuikturnLogo, QuikturnLogoCarousel } from "@quikturn/logos-react";
function App() {
return (
<QuikturnProvider token="qt_your_key">
<QuikturnLogo domain="github.com" size={64} />
<QuikturnLogoCarousel
domains={["github.com", "stripe.com", "vercel.com", "figma.com"]}
speed={120}
fadeOut
pauseOnHover
/>
</QuikturnProvider>
);
}
Full API reference: @quikturn/logos-react docs
Next.js
pnpm add @quikturn/logos-next
import { QuikturnProvider, QuikturnImage } from "@quikturn/logos-next";
export default function Page() {
return (
<QuikturnProvider token="qt_your_key">
<QuikturnImage domain="github.com" width={128} height={128} alt="GitHub" />
</QuikturnProvider>
);
}
Full API reference: @quikturn/logos-next docs
Vue
pnpm add @quikturn/logos-vue
<script setup lang="ts">
import { QuikturnLogo, QuikturnLogoCarousel } from "@quikturn/logos-vue";
</script>
<template>
<QuikturnLogo domain="github.com" :size="64" />
<QuikturnLogoCarousel
:domains="['github.com', 'stripe.com', 'vercel.com', 'figma.com']"
:speed="120"
fade-out
pause-on-hover
/>
</template>
Full API reference: @quikturn/logos-vue docs
Svelte
pnpm add @quikturn/logos-svelte
<script>
import { QuikturnProvider, QuikturnLogo, QuikturnLogoCarousel } from "@quikturn/logos-svelte";
</script>
<QuikturnProvider token="qt_your_key">
<QuikturnLogo domain="github.com" size={64} />
<QuikturnLogoCarousel
domains={["github.com", "stripe.com", "vercel.com", "figma.com"]}
speed={120}
fadeOut
pauseOnHover
/>
</QuikturnProvider>
Full API reference: @quikturn/logos-svelte docs
Angular
pnpm add @quikturn/logos-angular
// app.config.ts
import { provideQuikturnLogos } from "@quikturn/logos-angular";
export const appConfig = {
providers: [provideQuikturnLogos({ token: "qt_your_key" })],
};
import { Component } from "@angular/core";
import { QuikturnLogoComponent, QuikturnLogoCarouselComponent } from "@quikturn/logos-angular";
@Component({
selector: "app-example",
standalone: true,
imports: [QuikturnLogoComponent, QuikturnLogoCarouselComponent],
template: `
<quikturn-logo domain="github.com" [size]="64" />
<quikturn-logo-carousel
[domains]="['github.com', 'stripe.com', 'vercel.com', 'figma.com']"
[speed]="120"
[fadeOut]="true"
[pauseOnHover]="true"
/>
`,
})
export class ExampleComponent {}
Full API reference: @quikturn/logos-angular docs
Authentication
| Key Type | Prefix | Environment | Auth Method |
|---|---|---|---|
| Publishable | qt_ / pk_ | Browser | Query parameter (?token=...) |
| Secret | sk_ | Server only | Authorization: Bearer header |
Publishable keys are safe to expose in client-side code (max 800px). Secret keys must never reach the browser (max 1200px). Manage your keys in the Quikturn dashboard.
// Browser
import { QuikturnLogos } from "@quikturn/logos/client";
const client = new QuikturnLogos({ token: "qt_your_publishable_key" });
// Server
import { QuikturnLogos } from "@quikturn/logos/server";
const client = new QuikturnLogos({ secretKey: "sk_your_secret_key" });
API Reference
logoUrl(domain, options?)
Pure URL builder. No network calls, no side effects.
import { logoUrl } from "@quikturn/logos";
Options:
| Property | Type | Default | Description |
|---|---|---|---|
token | string | -- | API key appended as query parameter |
size | number | 128 | Output width in pixels |
width | number | 128 | Alias for size |
greyscale | boolean | false | Desaturation filter |
theme | "light" | "dark" | -- | Background-optimized rendering |
format | string | "image/png" | "png", "jpeg", "webp", "avif" (or full MIME type) |
Returns: string | Throws: DomainValidationError
Browser Client
import { QuikturnLogos } from "@quikturn/logos/client";
Constructor
| Option | Type | Default | Description |
|---|---|---|---|
token | string | required | Publishable key (qt_/pk_ prefix) |
| maxRetries | number | 2 | Max retries for 429/5xx responses |
Methods
client.get(domain, options?) -- Fetches a logo and returns a blob URL.
| Option | Type | Default |
|---|---|---|
size | number | 128 |
format | string | "image/png" |
greyscale | boolean | false |
theme | "light" | "dark" | -- |
scrapeTimeout | number | -- |
onScrapeProgress | (event) => void | -- |
signal | AbortSignal | -- |
Returns Promise<{ url: string, blob: Blob, contentType: string, metadata: LogoMetadata }>.
client.getUrl(domain, options?) -- Returns a plain URL string without a network request.
client.on(event, handler) / client.off(event, handler) -- Listen for "rateLimitWarning" or "quotaWarning" events.
client.destroy() -- Revokes all tracked blob URLs and removes event listeners. Call this to prevent memory leaks.
Server Client
import { QuikturnLogos } from "@quikturn/logos/server";
Constructor
| Option | Type | Default | Description |
|---|---|---|---|
secretKey | string | required | Secret key (sk_ prefix) |
| maxRetries | number | 2 | Max retries for 429/5xx responses |
Methods
client.get(domain, options?) -- Returns Promise<{ buffer: Buffer, contentType: string, metadata: LogoMetadata }>.
client.getMany(domains, options?) -- Batch fetch with concurrency control. Returns AsyncGenerator<BatchResult>.
| Option | Type | Default |
|---|---|---|
concurrency | number | 5 |
continueOnError | boolean | true |
signal | AbortSignal | -- |
client.getStream(domain, options?) -- Returns Promise<ReadableStream> for zero-copy streaming.
client.getUrl(domain, options?) -- Returns a URL string (secret key NOT included -- use Authorization header).
client.on(event, handler) / client.off(event, handler) -- Same events as the browser client.
Web Component
import "@quikturn/logos/element";
| Attribute | Type | Description |
|---|---|---|
domain | string | Domain to fetch logo for (required) |
token | string | Publishable API key |
size | string | Image width in pixels |
format | string | "png", "jpeg", "webp", or "avif" |
greyscale | (presence) | Greyscale filter when attribute is present |
theme | string | "light" or "dark" |
Auto-registers as <quikturn-logo> on import. Shadow DOM protects the attribution badge with !important CSS rules.
Error Handling
All errors extend LogoError with a typed code property for exhaustive switch handling:
import { LogoError } from "@quikturn/logos";
try {
const { url } = await client.get("example.com");
} catch (err) {
if (err instanceof LogoError) {
switch (err.code) {
case "RATE_LIMIT_ERROR": /* backoff */ break;
case "NOT_FOUND_ERROR": /* fallback */ break;
case "AUTHENTICATION_ERROR": /* check key */ break;
// ...
}
}
}
| Error | Code | Status | Extra Properties |
|---|---|---|---|
DomainValidationError | DOMAIN_VALIDATION_ERROR | -- | domain |
AuthenticationError | AUTHENTICATION_ERROR | 401 | -- |
ForbiddenError | FORBIDDEN_ERROR | 403 | reason |
NotFoundError | NOT_FOUND_ERROR | 404 | domain |
BadRequestError | BAD_REQUEST_ERROR | 400 | -- |
RateLimitError | RATE_LIMIT_ERROR | 429 | retryAfter, remaining, resetAt |
QuotaExceededError | QUOTA_EXCEEDED_ERROR | 429 | retryAfter, limit, used |
ScrapeTimeoutError | SCRAPE_TIMEOUT_ERROR | -- | jobId, elapsed |
Types & Constants
import type {
ThemeOption, // "light" | "dark"
SupportedOutputFormat, // "image/png" | "image/jpeg" | "image/webp" | "image/avif"
FormatShorthand, // "png" | "jpeg" | "webp" | "avif"
LogoRequestOptions,
LogoMetadata,
BrowserLogoResponse,
ServerLogoResponse,
ScrapeProgressEvent,
LogoErrorCode, // discriminated union of all error codes
} from "@quikturn/logos";
| Constant | Value |
|---|---|
BASE_URL | "https://logos.getquikturn.io" |
DEFAULT_WIDTH | 128 |
DEFAULT_FORMAT | "image/png" |
SUPPORTED_FORMATS | Set of 4 MIME types |
FORMAT_ALIASES | { png, jpeg, webp, avif } -> MIME mapping |
Configuration
Formats
| Format | Shorthand | MIME Type |
|---|---|---|
| PNG | "png" | image/png |
| JPEG | "jpeg" | image/jpeg |
| WebP | "webp" | image/webp |
| AVIF | "avif" | image/avif |
Both forms are accepted: format: "webp" and format: "image/webp" are equivalent.
Themes
Use "light" for light backgrounds and "dark" for dark backgrounds. The API adjusts the logo's color profile to maximize contrast.
Rate Limits & Quotas
Rate limits and monthly quotas are enforced server-side and vary by plan. The SDK automatically retries with exponential backoff when limits are hit and emits "rateLimitWarning" / "quotaWarning" events so you can react in your UI. See pricing & plan details.
Resources
- Quikturn website -- sign up, manage keys, explore the API
- Dashboard -- usage analytics, key management, plan upgrades
- Pricing -- free tier, pro, and enterprise plans
- React components --
@quikturn/logos-reactdocs - Next.js components --
@quikturn/logos-nextdocs - Vue components --
@quikturn/logos-vuedocs - Svelte components --
@quikturn/logos-sveltedocs - Angular components --
@quikturn/logos-angulardocs - GitHub -- source, issues, contributions
Contributing
We welcome, appreciate, and applaud all contributions! See CONTRIBUTING.md for setup instructions and guidelines.
License
MIT -- built by Quikturn