Skip to main content

Loading…

Skip to main content
HomeProjectsPostsApproachesStackResourcesContact
Justin Tsugranes LogoJustin Tsugranes Logo

Justin Tsugranes

HomeProjectsPostsApproachesStackResourcesContact

Stay in the loop

Occasional notes on what I'm building, lessons earned, and the studio behind it.

By subscribing, you agree to receive No spam. Unsubscribe in one click anytime. from Justin Tsugranes. No spam. Unsubscribe anytime. Privacy Policy

© 2026 Total Ventures LLC. All rights reserved.

Privacy PolicyTerms of ServiceCookie Policy
← All approaches

Approach · workflow · in production

CI Local Before CI Remote

I run all CI checks and validations locally before pushing code, ensuring immediate feedback and preventing remote build failures.

CI Local Before CI Remote means I run the entire suite of continuous integration checks—linting, formatting, type checking, and all tests—on my development machine before committing or pushing code to a remote repository. This shifts the feedback loop left, catching issues in seconds rather than waiting for a remote pipeline to fail minutes later.

What it is

This approach involves configuring local development environments to execute the same validation steps that a remote CI/CD pipeline would. It's not just about basic linting; it encompasses the full battery of checks: code formatting, static analysis, type validation, unit tests, and often a subset of integration tests. The goal is to replicate the remote CI environment's validation stage as closely as possible on my machine, ensuring that any code I push is already verified to pass the foundational checks.

Why I do it this way

The primary driver is efficiency. Waiting for a remote CI pipeline—whether it's GitHub Actions, Vercel, or a custom Firebase deployment script—to run for several minutes only to report a trivial linting error or type mismatch is a waste of time and resources. By front-loading these checks, I eliminate unnecessary remote build cycles. This aligns with my Fail Fast, Fix Faster philosophy, allowing me to identify and correct issues immediately, often before the code even leaves my editor. For a solo operator running a multi-product studio with AI as the team, this efficiency is critical. It reduces the cognitive load of context switching and keeps my focus on building. Furthermore, it's a pragmatic approach that contributes to Cash Before Vanity by minimizing compute time on remote CI services, which can accrue costs.

How it works in practice

I implement this using `git hooks`, primarily `pre-commit` and `pre-push` hooks managed by `husky`. For monorepos, `nx` is indispensable. When working on Total Formula 1, for instance, `pre-push` hooks trigger `nx affected:lint`, `nx affected:typecheck`, and `nx affected:test`. This ensures only the projects impacted by my changes are validated, keeping the local feedback loop fast. If any check fails, the push is aborted, preventing a broken state from ever reaching the remote. For Firebase functions, I'll often spin up `firebase emulators:start` and run local integration tests against them before deployment. For frontends like Pregnancy Power Hour or Inky, which deploy to Vercel, the local checks mirror Vercel's build process. This includes running `eslint`, `prettier`, and `tsc` for type safety, which I consider part of Tests as Design—ensuring the code's structure and behavior are sound from the outset. My agentic engineering workflow, where Claude Code or Gemini might generate code, heavily relies on these local checks to validate agent output before I accept and commit it.

Where this breaks down

This approach is highly effective, but it has limitations. The most common issue is environment drift: if the local development environment isn't perfectly aligned with the remote CI environment (e.g., different Node.js versions, OS differences), a local pass might still result in a remote failure. I mitigate this with strict version pinning and using tools like `nvm` or Docker. Another challenge arises with complex integration tests that require external, non-mockable services or specific network configurations not easily replicated locally. In these cases, a remote CI stage is still necessary for the final validation. Lastly, if the local validation suite becomes too time-consuming, there's a risk of developers bypassing the hooks. My use of `nx affected` helps keep local runtimes manageable, but it's a constant balance between thoroughness and developer experience.

FAQs

Does this replace remote CI pipelines?
No. It front-loads the majority of checks. Remote CI still handles deployment, final integration tests requiring external services, and security scans.
What if local checks take too long?
For monorepos, use tools like `nx affected` to run checks only on changed projects. For smaller repos, ensure your test suite is optimized for speed.
How do you ensure local and remote environments match?
I use strict version pinning for dependencies and Node.js. Tools like `nvm` or Docker containers help maintain consistency across environments.

I run this and four other brands. Want to see the operator playbook in detail?

Get the Builder's Playbook →
Written by Justin Tsugranes, Founder, Total Ventures· Founder, Total Ventures · U.S. Army veteran (13 years) · M.M. Jazz Studies, University of South Carolina
Last reviewed July 22, 2026

Related

  • Tests as DesignI use tests as the initial design specification for new features, ensuring the API is usable and well-defined before writing implementation code.
  • Commit Often, Push DeliberatelyI use 'Commit Often, Push Deliberately' to maintain a detailed local history of iterative work, ensuring every remote push represents a stable, tested, and deployable state.
  • KISS, YAGNI, Rule of ThreeI apply KISS, YAGNI, and the Rule of Three to ensure I ship the simplest viable solution today, avoiding premature complexity and abstracting only when a pattern explicitly repeats.
  • Fail Fast, Fix FasterThis approach ensures that every error, from local type mismatches to production outages, is immediately and loudly surfaced, making it impossible to ignore and enabling rapid resolution.
  • Document While ShippingThis approach integrates documentation updates directly into the code commit process, ensuring that documentation always reflects the current state of the system.
  • Agent-First DevelopmentAgent-First Development is my method for optimizing codebases for AI agents to write and maintain most of the code, enabling me to scale product development as a solo operator.