A high-performance, modern blockchain explorer and data synchronization system for the Steem blockchain, built with Go and React.
- Overview
- Architecture
- Projects
- Quick Start
- Deployment
- Development
- Monitoring
- Configuration
- Contributing
- License
SteemDB is a comprehensive blockchain data platform that provides:
- RESTful API: Modern web API for accessing blockchain data
- WebSocket Support: Real-time data streaming for live updates
- Modern Web Interface: React-based frontend with TypeScript
- Comprehensive Monitoring: Prometheus metrics and Grafana dashboards
- β‘ High Performance: Modern Go implementation
- π Rich APIs: RESTful API with WebSocket support
- π¨ Modern UI: React 19 with TypeScript and Tailwind CSS
- π Monitoring: Built-in Prometheus metrics and Grafana dashboards
- π³ Containerized: Full Docker and Docker Compose support
- π Reliable: Comprehensive error handling and automatic recovery
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SteemDB System β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββ ββββββββββββββββ β
β β steemdb- β β steemdb- β β
β β web β β frontend β β
β β β β β β
β β β’ REST API β β β’ React UI β β
β β β’ WebSocket β β β’ TypeScriptβ β
β β β’ Nginx β β β’ Tailwind β β
β β β’ Go Backendβ β β’ Vite β β
β ββββββββ¬ββββββββ ββββββββ¬ββββββββ β
β β β β β
β ββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββ β
β β β β
β ββββββΌββββββ β
β β MongoDB β β
β β β β
β β Primary β β
β β Database β β
β ββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Monitoring Stack β β
β β β’ Prometheus (Metrics Collection) β β
β β β’ Grafana (Visualization) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Backend Services: Go (1.23 for steemdb-web, 1.25 for steemdb-sync)
- Frontend: React 19, TypeScript, Vite, Tailwind CSS
- Database: MongoDB (6.0 in
docker-compose.production.yml, 4.4 in the devdocker-compose.yml) - Web Framework: Gin
- WebSocket: Gorilla WebSocket
- Monitoring: Prometheus, Grafana (scrape the sync services)
- Containerization: Docker, Docker Compose
- Process Management: Supervisord
Modern web service providing RESTful API and WebSocket support, with full legacy API compatibility.
Features:
- RESTful API for accounts, blocks, witnesses, posts, and statistics
- Posts API: List, detail, replies, votes, and reblogs
- Labs API: PowerUp, PowerDown, Rshares, Curation/Author leaderboards, Flags, Clients, Benefactors, Pending posts
- Legacy API compatibility: 302 redirects for backward compatibility
- WebSocket real-time data streaming (aligned with legacy live.py functionality)
- Nginx integration for static file serving
- Health checks (
/health,/ready)
Documentation: steemdb-web/README.md
Modern React-based frontend application with full feature parity to legacy system.
Features:
- React 19 with TypeScript
- Tailwind CSS for styling
- Zustand for state management
- TanStack Query for data fetching
- React Router DOM for navigation
- Recharts for data visualization
- Posts Pages: List, detail, replies, votes, and reblogs
- Labs Pages: PowerUp, PowerDown, Rshares, Curation, Author, Flags, Clients, Benefactors, Pending
- Dashboard: Network performance, reward pool, and global properties
- Accounts: Account details, history, and statistics
- Witnesses: Witness information and voting
Documentation: steemdb-frontend/README.md
- Docker 20.10+ and Docker Compose 2.0+
- Go 1.23+ for steemdb-web, 1.25+ for steemdb-sync (for development)
- Node.js 18+ and pnpm 8+ (for frontend development)
- MongoDB (included via Docker Compose: 4.4 in the dev stack, 6.0 in the production stack)
This is the fastest way to get started with all services running.
-
Clone the repository
git clone <repository-url> cd steemdb
-
Configure services (optional)
# Edit web service configuration vim steemdb-web/configs/config.yaml -
Start all services
docker-compose up -d
-
Verify services are running
# Check service status docker-compose ps # View logs docker-compose logs -f # Check health endpoints curl http://localhost/health
-
Access services
- Frontend: http://localhost/
- API: http://localhost/api/v1/
- WebSocket: ws://localhost/ws
- MongoDB: localhost:27017
cd steemdb-web
go mod download
go run cmd/web/main.go configs/config.yamlcd steemdb-frontend
pnpm install
pnpm run devTwo compose files cover two different purposes β pick deliberately:
docker-compose.yml(dev/demo): web + refresher + mongo + monitoring. It does not run the data writers (processor/live_sync), so Posts/Labs/Accounts pages stay empty until a writer fills the derived collections.docker-compose.production.yml(production, single-box all-in-one): the five resident services β steemdb-web, processor, live-sync, steemdb-refresher, mongo β plus prometheus (real scrape config) and grafana. See Production Topology below.
Available Services (docker-compose.yml, dev):
steemdb-web- Web API service with Nginx and frontendsteemdb-refresher- witness/stats/funds/clients snapshots (stats/clients/account-rescan skip while the local data lags the chain head by >1000 blocks)mongo- MongoDB databaseprometheus/grafana- monitoring (scrapes the refresher metrics)
Common Commands:
# Start all services
docker-compose up -d
# Stop all services
docker-compose down
# View logs
docker-compose logs -f [service-name]
# Restart a service
docker-compose restart [service-name]
# Rebuild and restart
docker-compose up -d --build
# View service status
docker-compose ps
# Stop and remove volumes (β οΈ deletes data)
docker-compose down -vsteemdb-web supports configuration mounting from the host, allowing you to modify settings without rebuilding images:
- Web Service:
./steemdb-web/configs:/app/configs
To modify configuration:
-
Edit configuration files on the host:
# Edit web service config vim steemdb-web/configs/config.yaml -
Restart the service to apply changes:
docker-compose restart steemdb-web
For detailed configuration instructions:
The production stack is the single-box, all-in-one topology described in
docs/AI-driver/01-architecture-overview.md. It is codified in
docker-compose.production.yml:
| Service | Role | Metrics |
|---|---|---|
steemdb-web |
REST API + WebSocket + Nginx + SPA (only published port) | - |
processor |
operations -> derived collections (the only writer of posts/votes/...) |
:9092/metrics |
live-sync |
RPC catch-up + chain-head follow (started via the live profile) |
:9091/metrics |
steemdb-refresher |
witness/stats/funds/clients snapshots (stats/clients/account-rescan skip during catch-up) | :9093/metrics |
mongo |
raw + derived data (sync side is the writer & index authority) | - |
Shared-Mongo contract: the steemdb database is written by the sync side only;
steemdb-web connects to the same database read-only. The collection/field
contract is documented in docs/AI-driver/02-data-model.md. Mongo is
not published to the host (compose network only).
Cold start & steady state (cold_ingest/steemd/repair are tools, not resident
services β details in the header of docker-compose.production.yml):
Data handoff is a manual step. The cold-start stack (
steemdb-sync/test/docker-compose/) runs its own Mongo (mongo:4.4, auth-enabled, databasesteemdb_test, separate volume), while the production compose runs a different mongo:6.0 on a fresh empty volume. Nothing copies the replayed data between the two. Skip the handoff in step 1 below and the processor starts against an empty database while live-sync would re-fetch the entire chain from block 1 over RPC β the months-long refetch the cold replay exists to avoid.
-
Replay the chain with the cold-start stack (
steemdb-sync/test/docker-compose/: steemd ingest plugin pushes ops to cold_ingest; both retire when the replay finishes), writing into the production Mongo via one of:-
Path A (recommended; matches the original design β the replay writes production directly). Bring up the production mongo alone first:
docker compose -f docker-compose.production.yml up -d mongo
Then run the cold-start stack with its writers repointed at that mongo via a local compose override (not shipped β the shipped test compose is a test fixture): set
cold_ingest'sMONGO_URIto the production mongo with databasesteemdb(notsteemdb_test). Either attach thecold-ingestcontainer to the production compose network (default namesteemdb_steemdb-network; checkdocker network ls) and usemongodb://mongo:27017/steemdb, or publish the production mongo on loopback (the commented-out127.0.0.1:27017port in its service block) and point the URI at the host. Add credentials if mongo auth is enabled. SetMONGO_DATABASE=steemdbin the cold stack's.envas well β it builds the cold stack'sMONGO_URIfrom that variable, and an explicitMONGO_DATABASEwins over a URI's database name, so both must agree onsteemdb. Only the receiver (cold-ingest) andsteemdare needed for the replay β do not also run the cold stack's processor/live-sync against the production database (the production processor does the catch-up; a second processor would race it on the same status cursor). Trade-off: zero-copy and no version boundary to cross. Mounting the productionmongo_datavolume into the cold stack's mongo:4.4 instead is also possible but drags 4.4β6.0 in-place-upgrade and auth-initialization caveats with it β prefer repointing the URI. -
Path B (fallback β replay into
steemdb_test, then dump/restore). Let the replay land in the cold stack's own database, stop its writers, then move the data (logical dump/restore is the supported way across 4.4 β 6.0 β never copy data files between major versions; mongo:6.0 images no longer bundle the tools, so use themongodb/mongodb-database-toolsimage or a host install):# Source URI (auth) is built from MONGO_USERNAME/MONGO_PASSWORD/ # MONGO_DATABASE in the cold stack's .env (steemdb-sync/test/docker-compose/). mongodump --uri="mongodb://<user>:<pass>@<cold-mongo-host>:27017/steemdb_test?authSource=admin" \ --archive=steemdb.archive mongorestore --uri="mongodb://<prod-mongo-host>:27017" \ --nsFrom=steemdb_test --nsTo=steemdb --archive=steemdb.archive
Trade-off: slower and needs disk headroom for the archive, but leaves both stacks untouched.
-
-
Verify the handoff in the production Mongo (database
steemdb; N = the replayed target height β counts must line up before anything else starts):db.blocks.countDocuments() // == N (blocks are numbered 1..N) db.operations.countDocuments() // == ops cold_ingest reported db.meta.findOne({_id: "sync_state"}).max_block // == N
Also confirm zero block gaps over the range (the
repairbinary can scan for gaps), then start the production stack without the live profile β processor catches up over the replayed operations. -
Hand off to live sync:
docker compose -f docker-compose.production.yml --profile live up -d live-sync(resumes frommeta.max_block/ highest block, then follows the chain head). -
repairis an ad-hoc maintenance binary built into the steemdb-sync image (run viadocker compose ... run --rm processor /app/repair ...).
Setup:
cp .env.production.example .env # set GRAFANA_ADMIN_PASSWORD (required) etc.
docker compose -f docker-compose.production.yml up -d --build-
Build production images
docker compose -f docker-compose.production.yml build
-
Set environment variables (via
.env, see.env.production.example)# Required GRAFANA_ADMIN_PASSWORD=<secret> # Common overrides RPC_ENDPOINT=https://api.steemit.com MONGO_URI=mongodb://mongo:27017/steemdb # sync-side writers WEB_MONGODB_URI=mongodb://mongo:27017/ # web (db name from its config)
-
Deploy with the production compose
docker compose -f docker-compose.production.yml up -d
-
Set up reverse proxy (if needed)
- Configure Nginx or Traefik for SSL termination
- Point to
http://localhost:80(or${WEB_PORT}) for the web service - Forward the
Upgrade/Connectionheaders, otherwise the/wswebsocket endpoint will not connect through the proxy
steemdb/
βββ docker-compose.yml # Dev/demo Docker Compose configuration
βββ docker-compose.production.yml # Production topology (single-box all-in-one)
βββ steemdb-web/ # Web API service
β βββ cmd/web/ # Main entry point
β βββ internal/ # Internal packages
β β βββ api/ # API handlers and routes
β β βββ database/ # Database connections
β β βββ models/ # Data models
β β βββ services/ # Business logic (incl. WebSocket service)
β βββ pkg/ # Public packages (steem RPC client, utils)
β βββ docker/ # Docker configurations (nginx, supervisor)
β βββ configs/ # Configuration files
βββ steemdb-sync/ # Data sync service
β βββ cmd/ # cold_ingest / live_sync / processor / refresher / repair
β βββ internal/ # config, metrics, model, mongo, pipeline, processor, refresher, rpc, checker
β βββ configs/ # Configuration files
βββ steemdb-frontend/ # React frontend
β βββ src/ # Source code
β βββ public/ # Static assets
-
Start development environment
# Start dependencies (MongoDB) docker-compose up -d mongo # Run web service locally cd steemdb-web && go run cmd/web/main.go configs/config.yaml # Run frontend in dev mode cd steemdb-frontend && pnpm run dev
-
Run tests
# Web service tests cd steemdb-web && go test ./... # Sync service tests cd steemdb-sync && go test ./... # Frontend: lint + type-aware build (no test framework is configured yet) cd steemdb-frontend && pnpm run lint && pnpm run build
-
Build for production
# Build web service cd steemdb-web && go build -o steemdb-web cmd/web/main.go # Build frontend cd steemdb-frontend && pnpm build
- Create handler in
steemdb-web/internal/api/ - Add route in
steemdb-web/internal/api/routes.go - Implement service logic in
steemdb-web/internal/services/ - Add tests
- Create component in
steemdb-frontend/src/pages/ - Add route in
steemdb-frontend/src/App.tsx - Update navigation if needed
- Add API integration
Prometheus is configured with real scrape targets (targets are verified against code, not guessed):
- Sync services (production compose,
monitoring/prometheus.yml):live-syncβhttp://live-sync:9091/metricsprocessorβhttp://processor:9092/metricssteemdb-refresherβhttp://steemdb-refresher:9093/metrics
- Dev compose (
monitoring/prometheus.dev.yml): scrapessteemdb-refresher:9093(the only resident sync service there). - steemdb-web is not scraped: it currently starts no metrics server (the
metrics.*config keys are unused defaults). Do not add a web scrape target until the web side actually serves/metrics.
steemdb_sync_current_block- processed/followed block heightsteemdb_sync_processor_window_duration_seconds/_blocks/_ops- processor window breakdownsteemdb_sync_mongo_write_duration_seconds/steemdb_sync_mongo_write_total- Mongo write pathsteemdb_sync_rpc_latency_seconds/steemdb_sync_rpc_total- Steem RPC calls
Grafana is not published to the host by default (reach it via SSH tunnel or
reverse proxy). In the production compose the admin password comes from
GRAFANA_ADMIN_PASSWORD in .env β there is no baked-in default. Datasource
provisioning is not included; add the prometheus datasource manually.
All services include health check endpoints:
- Web Service:
http://localhost/health(via Nginx) - MongoDB: Internal health check via mongo shell ping (
mongoshin the production stack, legacymongoin the 4.4 dev stack) - Sync services: health checks via their
/metricsendpoints (production compose)
Check service health:
# Web service
curl http://localhost/health
# All services status
docker-compose psEnvironment variables are the ones actually bound in code
(steemdb-web/pkg/utils/config.go, steemdb-sync/internal/config/config.go):
Web Service (viper BindEnv + AutomaticEnv with .->_):
SERVER_MODE- Server mode (development, production)DATABASE_MONGODB_URI(aliasMONGODB_URI) - MongoDB connection stringAUTH_JWT_SECRET- JWT secret key (overridesauth.jwt_secret)
Sync services (processor / live_sync / refresher, loadFromEnv):
MONGO_URI- MongoDB connection string (database name parsed from the URI)RPC_ENDPOINT- Steem RPC endpointLOG_LEVEL,PROCESSOR_WINDOW_SIZE,PROCESSOR_BUFFER_LIMIT,LIVE_SYNC_CHUNK_SIZE,LIVE_SYNC_FOLLOW_THRESHOLD,LIVE_SYNC_RPC_CONCURRENCY- tuning
See .env.production.example for the variables consumed by
docker-compose.production.yml.
- Web Service:
steemdb-web/configs/config.yaml
See individual project READMEs for detailed configuration options.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Go: Follow standard Go formatting (
go fmt) - TypeScript/React: Follow ESLint rules
- Commits: Use conventional commit messages in English
- All new features must include tests
- Maintain or improve test coverage
- All tests must pass before submitting PR
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: See individual project READMEs
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Complete API implementation (Accounts, Blocks, Witnesses, Posts, Labs)
- Legacy API compatibility (302 redirects)
- WebSocket real-time streaming (aligned with legacy live.py)
- Frontend pages (Posts, Labs, Dashboard, Accounts, Witnesses)
- Docker and Docker Compose deployment
- Environment variable configuration support
- Advanced caching strategies
- Performance optimizations
- Horizontal scaling support
- GraphQL API
- Mobile API optimizations
- Enhanced monitoring and alerting
- steemdb-web/README.md - Web service documentation
- steemdb-sync/README.md - Sync service documentation
- steemdb-frontend/README.md - Frontend documentation
- steemdb-web/docker/CONFIGURATION.md - Docker configuration guide
steemdb/
βββ README.md # This file - main project documentation
βββ docker-compose.yml # Dev/demo Docker Compose configuration
βββ docker-compose.production.yml # Production topology
βββ steemdb-web/ # Web API service (serves the built frontend)
βββ steemdb-sync/ # Data sync service (cold ingest, live sync, processor, refresher, repair)
βββ steemdb-frontend/ # React frontend application
The original PHP/Python application is no longer part of this branch; it is preserved on the
legacybranch for reference.
Service Ports:
80- Web service (Nginx + Frontend + API) β the only published port in production27017- MongoDB (compose network only, not published)9091/9092/9093- live_sync / processor / refresher metrics (compose network only)
Key Endpoints:
- Health:
http://localhost/health - API:
http://localhost/api/v1/ - WebSocket:
ws://localhost/ws
Built with β€οΈ for the Steem community
Note: This project refactoring was driven by @ety001.