Skip to main content 首页 创作者 jeremylongshore claude-code-plugins-plus-skills replit-sdk-patterns
replit-sdk-patterns Apply production-ready patterns for Replit Database, Object Storage, and Auth APIs.
Use when implementing Replit integrations, structuring data access layers,
or establishing team coding standards for Replit services.
Trigger with phrases like "replit patterns", "replit best practices",
"replit code patterns", "idiomatic replit", "replit SDK".
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill replit-sdk-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... 同仓库更多 Skills Implement user sign-up and sign-in flows with Clerk.
Use when building authentication UI, customizing sign-in experience,
or implementing OAuth social login.
Trigger with phrases like "clerk sign-in", "clerk sign-up",
"clerk login flow", "clerk OAuth", "clerk social login".
Implement session management and middleware with Clerk.
Use when managing user sessions, configuring route protection,
or implementing token refresh and custom JWT templates.
Trigger with phrases like "clerk session", "clerk middleware",
"clerk route protection", "clerk token", "clerk JWT".
Configure enterprise SSO, role-based access control, and organization management.
Use when implementing SSO integration, configuring role-based permissions,
or setting up organization-level controls.
Trigger with phrases like "clerk SSO", "clerk RBAC",
"clerk enterprise", "clerk roles", "clerk permissions", "clerk organizations".
jeremylongshore
jeremylongshore/claude-code-plugins-plus-skills
打开 GitHub 仓库 name replit-sdk-patterns description Apply production-ready patterns for Replit Database, Object Storage, and Auth APIs.
Use when implementing Replit integrations, structuring data access layers,
or establishing team coding standards for Replit services.
Trigger with phrases like "replit patterns", "replit best practices",
"replit code patterns", "idiomatic replit", "replit SDK".
allowed-tools Read, Write, Edit version 1.12.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","replit","python","typescript","patterns"] compatibility Designed for Claude Code, also compatible with Codex and OpenClaw
Replit SDK Patterns
Overview
Production-ready patterns for Replit's built-in services: Key-Value Database (@replit/database / replit.db), Object Storage (@replit/object-storage), PostgreSQL (DATABASE_URL), and Auth headers. Covers singleton clients, error handling, and type-safe wrappers.
Prerequisites
.replit and replit.nix configured (see replit-install-auth)
Familiarity with async/await patterns
Understanding of Replit's service model
Instructions
Step 1: Database Client Singleton (Node.js)
import Database from '@replit/database' ;
let instance : Database | null = null ;
export function getKV ( ): Database {
if (!instance) {
instance = new Database ();
}
return instance;
}
export async function kvGet<T>(key : string ): Promise <T | null > {
const value = await getKV ().get (key);
return value as T | null ;
}
export async function kvSet<T>( : , : T): < > {
(). (key, value);
}
( ): < []> {
(). (prefix);
}
( ): < > {
(). (key);
}
key
string
value
Promise
void
await
getKV
set
export
async
function
kvList
prefix = ''
Promise
string
return
getKV
list
export
async
function
kvDelete
key : string
Promise
void
await
getKV
delete
Step 2: Object Storage Wrapper
import { Client } from '@replit/object-storage' ;
let storage : Client | null = null ;
export function getStorage ( ): Client {
if (!storage) {
storage = new Client ();
}
return storage;
}
export async function uploadText (path : string , content : string ): Promise <void > {
try {
await getStorage ().uploadFromText (path, content);
} catch (err : any ) {
if (err.name === 'BucketNotFoundError' ) {
throw new Error ('Object Storage bucket not provisioned. Create one in the Object Storage pane.' );
}
if (err.name === 'TooManyRequestsError' ) {
throw new Error ('Object Storage rate limited. Retry after backoff.' );
}
throw err;
}
}
export async function downloadText (path : string , fallback = '' ): Promise <string > {
try {
const { value } = await getStorage ().downloadAsText (path);
return value ?? fallback;
} catch {
return fallback;
}
}
export async function listObjects (prefix : string ): Promise <string []> {
const objects = await getStorage ().list ({ prefix });
return objects.map (obj => obj.name );
}
Step 3: PostgreSQL Connection Pool
import { Pool , PoolConfig } from 'pg' ;
let pool : Pool | null = null ;
export function getPool ( ): Pool {
if (!pool) {
if (!process.env .DATABASE_URL ) {
throw new Error ('DATABASE_URL not set. Provision PostgreSQL in the Database pane.' );
}
const config : PoolConfig = {
connectionString : process.env .DATABASE_URL ,
ssl : { rejectUnauthorized : false },
max : 10 ,
idleTimeoutMillis : 30000 ,
connectionTimeoutMillis : 5000 ,
};
pool = new Pool (config);
pool.on ('error' , (err ) => {
console .error ('PostgreSQL pool error:' , err.message );
});
}
return pool;
}
export async function query<T>(sql : string , params ?: any []): Promise <T[]> {
const result = await getPool ().query (sql, params);
return result.rows as T[];
}
export async function withTransaction<T>(
fn : (client : import ('pg' ).PoolClient ) => Promise <T>
): Promise <T> {
const client = await getPool ().connect ();
try {
await client.query ('BEGIN' );
const result = await fn (client);
await client.query ('COMMIT' );
return result;
} catch (err) {
await client.query ('ROLLBACK' );
throw err;
} finally {
client.release ();
}
}
Step 4: Auth Middleware Pattern
import { Request , Response , NextFunction } from 'express' ;
export interface ReplitUser {
id : string ;
name : string ;
bio : string ;
url : string ;
profileImage : string ;
roles : string ;
teams : string ;
}
export function extractUser (req : Request ): ReplitUser | null {
const id = req.headers ['x-replit-user-id' ] as string ;
if (!id) return null ;
return {
id,
name : (req.headers ['x-replit-user-name' ] as string ) || '' ,
bio : (req.headers ['x-replit-user-bio' ] as string ) || '' ,
url : (req.headers ['x-replit-user-url' ] as string ) || '' ,
profileImage : (req.headers ['x-replit-user-profile-image' ] as string ) || '' ,
roles : (req.headers ['x-replit-user-roles' ] as string ) || '' ,
teams : (req.headers ['x-replit-user-teams' ] as string ) || '' ,
};
}
export function requireAuth (req : Request , res : Response , next : NextFunction ) {
const user = extractUser (req);
if (!user) return res.status (401 ).json ({ error : 'Login required' });
(req as any ).user = user;
next ();
}
Step 5: Python Patterns
from replit import db
from replit.object_storage import Client as ObjectStorage
import os, json
class KVStore :
@staticmethod
def get (key: str , default=None ):
return db.get(key, default)
@staticmethod
def set (key: str , value ):
db[key] = value
@staticmethod
def delete (key: str ):
if key in db:
del db[key]
@staticmethod
def list_keys (prefix: str = '' ) -> list :
return db.prefix(prefix) if prefix else list (db.keys())
class FileStore :
def __init__ (self ):
self ._client = ObjectStorage()
def upload (self, path: str , content: str ):
self ._client.upload_from_text(path, content)
def download (self, path: str ) -> str :
return self ._client.download_as_text(path)
def exists (self, path: str ) -> bool :
return self ._client.exists(path)
def delete (self, path: str ):
self ._client.delete(path)
def list (self, prefix: str = '' ) -> list :
return [obj.name for obj in self ._client.list (prefix=prefix)]
def get_replit_user (request ) -> dict | None :
user_id = request.headers.get('X-Replit-User-Id' )
if not user_id:
return None
return {
'id' : user_id,
'name' : request.headers.get('X-Replit-User-Name' , '' ),
'roles' : request.headers.get('X-Replit-User-Roles' , '' ),
'image' : request.headers.get('X-Replit-User-Profile-Image' , '' ),
}
Step 6: Retry with Backoff
export async function withRetry<T>(
fn : () => Promise <T>,
opts = { maxRetries : 3 , baseMs : 1000 , maxMs : 30000 }
): Promise <T> {
for (let attempt = 0 ; attempt <= opts.maxRetries ; attempt++) {
try {
return await fn ();
} catch (err : any ) {
if (attempt === opts.maxRetries ) throw err;
const delay = Math .min (opts.baseMs * 2 ** attempt, opts.maxMs );
const jitter = Math .random () * delay * 0.1 ;
await new Promise (r => setTimeout (r, delay + jitter));
}
}
throw new Error ('Unreachable' );
}
Error Handling Pattern Use Case Benefit Singleton client All services Avoids connection leaks Typed wrappers KV/SQL queries Catches schema issues at compile time Retry + backoff Transient failures Handles cold starts and rate limits Transaction helper Multi-step writes Atomic operations, safe rollback
Resources
Next Steps Apply patterns in replit-core-workflow-a for real-world usage.