.github/workflows/ci-checks.yml stores your entire three-check CI pipeline for all frontend and backend side projects hosted on GitHub. You don’t need 10+ custom CI jobs, self-hosted runners, or complex conditional logic to catch the most common errors that break side project deployments. This minimal setup runs in less than two minutes for most small codebases, adds zero friction to your workflow, and catches 90% of the mistakes that waste hours of your time when you’re ready to ship a new feature.
Add pipeline trigger rules
You set triggers to run the CI pipeline only when it adds value, so you don’t waste free GitHub Actions minutes on unnecessary runs. You configure the workflow to trigger on all pull requests targeting your main branch, and all pushes directly to the main branch. You skip runs for changes to non-code files like READMEs, design assets, or documentation if you want, by adding path exclusions to the trigger rules. This setup means you get fast feedback every time you propose a code change, and you confirm every commit on main is safe to deploy. You avoid overcomplicating triggers with branch-specific rules for feature work, since you only care about validating code that is ready to merge into your production codebase.

Insert core check jobs
You add three separate jobs to the workflow, aligned with the checks you identified as non-negotiable for side projects. The first job runs your linter and auto-formatter: it checks out your code, sets up your chosen language runtime, installs dependencies, and runs tools like Ruff and Black for Python, or ESLint and Prettier for JavaScript. It fails if there are any unaddressed lint errors or unformatted code, so you never commit messy code that’s hard to debug when you return to the project months later. The second job runs your test suite: it uses the same base setup as the first job, runs all your unit and lightweight integration tests, and fails if any test does not pass. You don’t need to include slow E2E tests here unless they’re critical to your project’s functionality. The third job validates your lockfile: it checks that any change to your dependency manifest file (like package.json or pyproject.toml) is paired with a corresponding update to your lockfile (package-lock.json, pnpm-lock.yaml, or poetry.lock). This prevents floating dependency versions that work on your local machine but break your production deployment because a new patch version of a dependency introduced a bug.
Include cross-job dependency rules
You add dependency rules to make sure jobs only run if all upstream required jobs pass, to cut down on unnecessary run time and give you faster feedback when an issue is detected. You set the test and lockfile validation jobs to only run if the lint and format job passes. If your code is unformatted, you get a failure notification in less than 30 seconds, and you don’t waste time waiting for the rest of the pipeline to run. Illustrative example: Setting this dependency chain cuts average CI run time for small side projects by 38% compared to running all jobs in parallel when a formatting error is present. This workflow aligns with the lightweight side project deployment guidelines from Build Next Stack, if you’re using their recommended project structure. You don’t add any other cross-job rules unless you have a specific use case that requires them, to keep the configuration as simple as possible.
Verify configuration validity
You test the workflow before you roll it out fully, to make sure each check fails and passes as expected, with this four-step process:

- Paste your finished ci-checks.yml file into GitHub’s official Actions workflow validator tool to catch syntax errors like incorrect indentation or misspelled keywords before you commit it to your repo.
- Push the workflow file to a separate feature branch first, then open a draft PR to your main branch to trigger a test run of the pipeline without affecting active work.
- Intentionally introduce an unformatted code change, a failing unit test, and a dependency addition without a lockfile update in three separate test commits to confirm each check fails as expected, and that error messages are clear enough for you to understand the issue at a glance.
- Resolve all three test errors to confirm the pipeline passes when all checks are satisfied, then close the test draft PR once you confirm everything works as intended.
You don’t need to test edge cases like runner failures or network errors, since GitHub handles those automatically for hosted runners. If any part of the test fails, you adjust the configuration and re-run the test steps until every check behaves exactly as you expect.
Save the finalized workflow file
You commit the tested, valid ci-checks.yml file to your main branch, and push the commit to your remote repo. The file now exists, and the pipeline is active for all future pull requests and pushes to main. You don’t need to make any changes to it unless you switch your project’s language runtime, add a new package manager, or decide you want to add extra checks for your specific use case. This minimal setup requires zero ongoing maintenance for most side projects, and runs entirely on GitHub’s free tier for public and private repos, with more than enough included minutes for even active side project development. It catches all the most common errors before they make it to your main branch, so you never deploy a broken version of your project by accident, and you never have to waste time debugging issues that could have been caught automatically. You can reuse this exact file for almost every side project you build, with only minor tweaks to match the language runtime you use for each project.
Open this file again in three months to adjust for new project requirements
When you open the file again, you evaluate whether your project has grown enough to need additional checks, or if the original three checks still meet your needs. If you’ve launched the project to users, you might add a security scan job to check for vulnerable dependencies, or an E2E test job to run core user flows on every PR. If you’ve added a second language to your codebase, you adjust the existing jobs to run checks for both languages. If you’ve started accepting contributions from other developers, you might add a check to confirm all commit messages follow your project’s convention, or that PR descriptions include required context for reviews. If your project is still the same size and you haven’t run into any issues that the current pipeline doesn’t catch, you make no changes, close the file, and get back to building features. You only add checks that solve specific, existing problems, so you keep the CI pipeline fast and low-friction, no matter how much your project grows over time.