Skip to main content
CarboIT LogoCarboIT
If you need help with your project, feel free to contact us.
Cover Image for Launching ShotTech: How Carboit Built a Production-Ready SaaS to Showcase Our Technical Excellence

Launching ShotTech: How Carboit Built a Production-Ready SaaS to Showcase Our Technical Excellence

Luis Carbonel
Luis Carbonel

Building ShotTech: When Your Software Consultancy Becomes Its Own Best Client

At Carboit, we've always believed that the best way to understand our clients' challenges is to face them ourselves. That's why we built ShotTech – not just as another SaaS product, but as a living demonstration of what modern, scalable software architecture looks like when done right.


The Journey: From Internal Need to Public Service

It started with a simple frustration. While developing client applications, we repeatedly needed reliable screenshot capabilities for documentation, testing, and monitoring. Existing solutions were either too expensive, too slow, or too limited. As a boutique software consultancy in Austin, we decided to solve this problem properly – and in doing so, create a showcase of our technical capabilities.

ShotTech Dashboard Overview ShotTech's clean, intuitive dashboard showcases our approach to user experience design

Why Build a SaaS Product?

Building ShotTech wasn't about pivoting our business model. It was about:

  • Demonstrating expertise through real-world implementation
  • Understanding the full lifecycle of SaaS operations
  • Creating a technical reference for future client projects
  • Contributing to the developer community through open source

User Experience: Where Backend Architecture Meets Frontend Design

One of the key lessons from building ShotTech was understanding how clean architecture enables great user experiences. Our hexagonal backend architecture allows for rapid feature development, which translates to a polished frontend.

Screenshot Billing Interface Screenshot Billing Interface Screenshot Billing Interface Screenshot Billing Interface Real-time screenshot gallery with instant status updates and detailed metadata


Technical Deep-Dive: The Architecture Behind ShotTech

The Kotlin/Ktor Foundation

We chose Kotlin with the Ktor framework for our backend – a decision that reflects our commitment to modern, efficient technologies. Our open-source backend repository showcases enterprise-grade patterns and practices.

Hexagonal Architecture in Practice

Our implementation follows true hexagonal architecture principles with clear separation between domain, application, and infrastructure layers. Here's a real example from our codebase:

Use Case (Application Layer):

kotlin
1// TakeScreenshotUseCase.kt - Pure business logic 2class TakeScreenshotUseCase( 3 private val screenshotRepository: ScreenshotRepository, 4 private val queueRepository: QueueRepository, 5 private val tokenGenerationPort: TokenGenerationPort? = null 6) { 7 suspend operator fun invoke(request: Request): Response { 8 val jobId = "job_${System.currentTimeMillis()}_${UUID.randomUUID().toString().take(8)}" 9 10 // Pure domain logic - no framework dependencies 11 val job = ScreenshotJob( 12 id = jobId, 13 userId = request.userId, 14 apiKeyId = request.apiKeyId, 15 status = ScreenshotStatus.QUEUED, 16 request = request.screenshotRequest, 17 webhookUrl = request.webhookUrl, 18 createdAt = Clock.System.now() 19 ) 20 21 // Use ports (interfaces) not concrete implementations 22 screenshotRepository.save(job) 23 queueRepository.enqueue(job) 24 val secureToken = tokenGenerationPort?.generateToken(job) 25 26 return Response(jobId, ScreenshotStatus.QUEUED, "30-60s", queueRepository.size().toInt()) 27 } 28}

Domain Entity (Domain Layer):

kotlin
1// ScreenshotRequest.kt - Rich domain model with validation 2data class ScreenshotRequest( 3 val url: String, 4 val width: Int = 1920, 5 val height: Int = 1080, 6 val fullPage: Boolean = false, 7 val format: ScreenshotFormat = ScreenshotFormat.PNG 8) { 9 init { 10 require(url.isNotBlank()) { "URL cannot be blank" } 11 require(width in 320..1920) { "Width must be between 320 and 1920" } 12 require(height in 240..1080) { "Height must be between 240 and 1080" } 13 } 14 15 fun isValidUrl(): Boolean = try { 16 val uri = java.net.URI(url) 17 uri.scheme in listOf("http", "https") && uri.host != null 18 } catch (e: Exception) { 19 false 20 } 21}

Port Interface (Domain Layer):

kotlin
1// StorageOutputPort.kt - Contract for external dependencies 2interface StorageOutputPort { 3 suspend fun upload(data: ByteArray, filename: String): String 4 suspend fun uploadFromFile(filePath: String, filename: String): String 5 suspend fun delete(filename: String): Boolean 6 suspend fun getPresignedUrl(filename: String, expirationMinutes: Int = 60): String 7}

Adapter Implementation (Infrastructure Layer):

kotlin
1// S3StorageAdapter.kt - Concrete implementation 2class S3StorageAdapter( 3 private val s3Client: S3Client, 4 private val bucketName: String, 5 private val region: String 6) : StorageOutputPort { 7 8 override suspend fun upload(data: ByteArray, filename: String): String { 9 return try { 10 val key = generateKey(filename) 11 val request = PutObjectRequest { 12 bucket = bucketName 13 this.key = key 14 body = ByteStream.fromBytes(data) 15 } 16 s3Client.putObject(request) 17 getUrl(key) 18 } catch (e: Exception) { 19 throw UploadFailedException(filename, e) 20 } 21 } 22}

This architecture ensures:

  • Domain logic isolation - Business rules stay in the domain layer
  • Testability - Easy to mock ports for unit testing
  • Flexibility - Swap S3 for local storage without changing use cases
  • Scalability - Add new features without touching existing code

Performance Optimizations

Achieving sub-2-second response times required several optimizations:

  • Browser pool management for instant page rendering
  • Edge server deployment for global low latency
  • Intelligent caching strategies
  • Async processing for non-blocking operations

Open Source Strategy: Building Community While Protecting IP

We made a strategic decision: open-source the backend, keep the frontend proprietary. This approach:

  • Builds trust by showing our code quality
  • Attracts contributors who improve the platform
  • Demonstrates expertise to potential clients
  • Protects business value through UI/UX differentiation

The screenshot-api repository has already attracted developers who've contributed improvements, validated our architecture decisions, and even become Carboit clients.


Market Positioning: Enterprise-Grade at Indie Prices

ShotTech competes with established players by offering:

FeatureShotTechCompetitors
Response Time1.2s average3-5s average
PricingFrom $14.99/moFrom $49/mo
Open Source✅ Backend❌ Proprietary
SLA99.9% uptime99.5% typical
FormatsPNG, JPEG, WebP, PDFLimited options

Our pricing strategy reflects our consultancy roots – we understand budget constraints while demanding enterprise reliability.


Developer Experience: API Management Done Right

Building ShotTech taught us that great architecture is meaningless without great developer experience. Our API key management system showcases security best practices while maintaining usability.

API Keys Management Interface Secure API key management with granular permissions and usage tracking

Analytics and Monitoring: Data-Driven Decisions

Understanding usage patterns and performance metrics is crucial for any SaaS. Our analytics dashboard provides real-time insights that we use to optimize the service continuously.

Usage Analytics Dashboard Comprehensive analytics showing API usage, response times, and success rates

Client Value: Lessons That Transfer

Building ShotTech taught us invaluable lessons we now apply to every client project:

1. Real-World Scalability

Running a production SaaS with customers like Vercel and Stripe means we've solved real scaling challenges – not theoretical ones.

2. Cost Optimization

We've learned to balance performance with infrastructure costs, knowledge we pass to clients building their own platforms.

3. Developer Experience

Creating an API developers love taught us the importance of documentation, SDKs, and responsive support.

4. Monitoring & Reliability

Our 99.9% uptime SLA forced us to implement robust monitoring – practices we now standard in all client deployments.

Webhook Integration: Real-Time Notifications

Modern applications require real-time communication. ShotTech's webhook system demonstrates our understanding of event-driven architecture and reliable message delivery.

Webhook Configuration Interface Robust webhook configuration with delivery tracking and automatic retry mechanisms


The Technical Stack That Powers Innovation

yaml
1Backend: 2 Language: Kotlin 3 Framework: Ktor 4 Architecture: Hexagonal/Clean 5 Database: PostgreSQL with Redis caching 6 7Infrastructure: 8 Deployment: Kubernetes on multi-region clusters 9 CDN: Global edge network 10 Monitoring: Prometheus + Grafana 11 CI/CD: GitHub Actions + ArgoCD 12 13Features: 14 - RESTful API with OpenAPI documentation 15 - Webhook notifications 16 - Batch processing capabilities 17 - OCR text extraction 18 - Mobile device simulation 19 - Video capture (beta)

Future Roadmap: Continuous Innovation

ShotTech's development continues with:

  • Advanced OCR Integration – Extract text from any webpage
  • Team Collaboration Features – Shared projects and annotations
  • Enhanced Batch Processing – Process thousands of URLs efficiently
  • AI-Powered Analysis – Automatic visual regression detection
  • GraphQL API – For more flexible data queries

Each feature we add to ShotTech becomes expertise we bring to client projects.


The Carboit Difference: We Build What We Run

When you partner with Carboit, you're working with a team that:

  • Operates production systems serving real customers
  • Understands the full stack from code to deployment
  • Practices what we preach about architecture and scalability
  • Contributes to open source and the developer community

ShotTech isn't just our product – it's our proof of capability.


Ready to Build Your Next SaaS?

Whether you need:

  • A complete SaaS platform from scratch
  • API development with enterprise-grade reliability
  • Architecture consulting for scalability
  • Technical leadership for your development team

We bring the same expertise that powers ShotTech to your project.

Explore ShotTech to see our technical capabilities in action, or contact Carboit to discuss how we can help build your next software venture.


At Carboit, we don't just build software – we run it, scale it, and perfect it. ShotTech is our commitment to excellence made visible.