--- name: replit-hello-world description: 'Create a minimal working Replit app with database, object storage, and auth. Use when starting a new Replit project, testing your setup, or learning Replit''s built-in services (DB, Auth, Object Storage). Trigger with phrases like "replit hello world", "replit starter", "replit quick start", "first replit app", "replit example". ' allowed-tools: Read, Write, Edit, Bash(npm:*), Bash(pip:*) version: 1.12.0 license: MIT author: Jeremy Longshore tags: - saas - replit - starter - database - api compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw --- # Replit Hello World ## Overview Build a working Replit app that demonstrates core platform services: Express/Flask server, Replit Database (key-value store), Object Storage (file uploads), Auth (user login), and PostgreSQL. Produces a running app you can deploy. ## Prerequisites - Replit App created (template or blank) - `.replit` and `replit.nix` configured (see `replit-install-auth`) - Node.js 18+ or Python 3.10+ ## Instructions ### Step 1: Node.js — Express + Replit Database ```typescript // index.ts import express from 'express'; import Database from '@replit/database'; const app = express(); const db = new Database(); app.use(express.json()); // Health check with Replit env vars app.get('/health', (req, res) => { res.json({ status: 'ok', repl: process.env.REPL_SLUG, owner: process.env.REPL_OWNER, timestamp: new Date().toISOString(), }); }); // Replit Key-Value Database CRUD // Limits: 50 MiB total, 5,000 keys, 1 KB per key, 5 MiB per value app.post('/api/items', async (req, res) => { const { key, value } = req.body; await db.set(key, value); res.json({ stored: key }); }); app.get('/api/items/:key', async (req, res) => { const value = await db.get(req.params.key); if (value === null) return res.status(404).json({ error: 'Not found' }); res.json({ key: req.params.key, value }); }); app.get('/api/items', async (req, res) => { const prefix = (req.query.prefix as string) || ''; const keys = await db.list(prefix); res.json({ keys }); }); app.delete('/api/items/:key', async (req, res) => { await db.delete(req.params.key); res.json({ deleted: req.params.key }); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); console.log(`Repl: ${process.env.REPL_SLUG} by ${process.env.REPL_OWNER}`); }); ``` **package.json dependencies:** ```json { "dependencies": { "@replit/database": "^2.0.0", "express": "^4.18.0" }, "devDependencies": { "@types/express": "^4.17.0", "typescript": "^5.0.0" } } ``` ### Step 2: Python — Flask + Replit Database ```python # main.py from flask import Flask, request, jsonify from replit import db import os app = Flask(__name__) @app.route('/health') def health(): return jsonify({ 'status': 'ok', 'repl': os.environ.get('REPL_SLUG'), 'owner': os.environ.get('REPL_OWNER'), }) # Replit DB works like a Python dict @app.route('/api/items', methods=['POST']) def create_item(): data = request.json db[data['key']] = data['value'] return jsonify({'stored': data['key']}) @app.route('/api/items/') def get_item(key): if key not in db: return jsonify({'error': 'Not found'}), 404 return jsonify({'key': key, 'value': db[key]}) @app.route('/api/items') def list_items(): prefix = request.args.get('prefix', '') keys = db.prefix(prefix) if prefix else list(db.keys()) return jsonify({'keys': keys}) @app.route('/api/items/', methods=['DELETE']) def delete_item(key): if key in db: del db[key] return jsonify({'deleted': key}) if __name__ == '__main__': app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 3000))) ``` ### Step 3: Add Object Storage (File Uploads) ```typescript // storage.ts — Replit Object Storage (App Storage) import { Client } from '@replit/object-storage'; const storage = new Client(); // Upload text content await storage.uploadFromText('notes/hello.txt', 'Hello from Replit!'); // Upload from file on disk await storage.uploadFromFilename('uploads/photo.jpg', '/tmp/photo.jpg'); // Download as text const { value } = await storage.downloadAsText('notes/hello.txt'); console.log(value); // "Hello from Replit!" // Download as bytes const { value: bytes } = await storage.downloadAsBytes('uploads/photo.jpg'); // List objects with prefix const objects = await storage.list({ prefix: 'notes/' }); for (const obj of objects) { console.log(obj.name); // "notes/hello.txt" } // Check existence const { exists } = await storage.exists('notes/hello.txt'); // Copy object await storage.copy('notes/hello.txt', 'archive/hello-backup.txt'); // Delete object await storage.delete('notes/hello.txt'); ``` **Python Object Storage:** ```python from replit.object_storage import Client storage = Client() # Upload text storage.upload_from_text('notes/hello.txt', 'Hello from Replit!') # Download content = storage.download_as_text('notes/hello.txt') # List with prefix objects = storage.list(prefix='notes/') # Delete storage.delete('notes/hello.txt') # Check existence exists = storage.exists('notes/hello.txt') ``` ### Step 4: Add Auth-Protected Route ```typescript // Add to index.ts app.get('/api/me', (req, res) => { const userId = req.headers['x-replit-user-id']; if (!userId) return res.status(401).json({ error: 'Login required' }); res.json({ id: userId, name: req.headers['x-replit-user-name'], image: req.headers['x-replit-user-profile-image'], }); }); // Client-side: fetch('/__replauthuser') returns current user ``` ### Step 5: `.replit` for This App ```toml entrypoint = "index.ts" run = "npx tsx index.ts" modules = ["nodejs-20:v8-20230920-bd784b9"] [nix] channel = "stable-24_05" [env] PORT = "3000" [deployment] run = ["sh", "-c", "npx tsx index.ts"] deploymentTarget = "autoscale" ``` ## Output After running, verify at these endpoints: - `GET /health` — returns Repl metadata - `POST /api/items` — stores key-value data - `GET /api/items?prefix=` — lists keys - `GET /api/me` — returns authenticated user (when deployed) ## Error Handling | Error | Cause | Solution | |-------|-------|----------| | `Cannot find module '@replit/database'` | Not installed | `npm install @replit/database` | | `db.set is not a function` | Wrong import | Use `new Database()` not `import db` | | `REPLIT_DB_URL undefined` | Not on Replit | DB only available inside a Repl | | Object Storage 403 | No bucket provisioned | Create bucket in Object Storage pane | | Auth headers empty | Running in dev | Auth works only on deployed `.replit.app` | ## Resources - [Replit Database](https://docs.replit.com/cloud-services/storage-and-databases/replit-database) - [Object Storage Overview](https://docs.replit.com/cloud-services/storage-and-databases/object-storage/overview) - [Object Storage TypeScript SDK](https://docs.replit.com/cloud-services/storage-and-databases/object-storage/typescript-api-reference) - [Replit Auth](https://docs.replit.com/replit-workspace/replit-auth) ## Next Steps Deploy with `replit-deploy-integration` or add PostgreSQL with `replit-data-handling`.