title | excerpt | date |
---|---|---|
From Papercuts to Standards |
Whether unblocking students, fixing upgrade breakage or supporting ecosystem evolution, I aim to make open source more accessible and software simpler |
2025-05-06 |
Hi, I'm Karl Horky (GitHub, LinkedIn), Technical Founder at UpLeveled - tech education programs for all skill levels.
In an educational landscape of AI-generated solutions, disconnected islands of knowledge and barriers to entry, I focus on helping students level up by designing accessible curricula and contributing to open source.
I've been in open source for over 13 years, and in tech for more than 20, through which I have used a range of languages and technologies, from QBasic and C to Perl, PHP, Python, Ruby on Rails and then finally on to JavaScript / TypeScript.
Now I mostly work with TypeScript, React, Next.js, Node.js, SQL and Bash.
Through my work in education, I've become interested in:
- new approaches in web frameworks like React Server Components / Server Actions and the Islands Architecture
- SQL-in-JS tooling like SafeQL,
prettier-plugin-embed
, Postgres.js - secure-by-default and pit-of-success approaches to building safe and correct software, eg. enforcement and guidance through linting rules and expressive, strict API design
- patterns to reduce abstraction and indirection in code
My work at UpLeveled has focused on designing, developing and delivering accessible curricula for students ranging from beginners to more experienced engineers.
As part of this work, we maintain some of our own open source projects:
- Preflight: command line interface for students to check their code quality
eslint-config-upleveled
andeslint-plugin-upleveled
: ESLint config and plugin with custom rules- System Setup: Windows, macOS and Linux setup guides
- numerous example repositories like Examples of Broken Security with Next.js + Postgres.js and UpLeveled Next.js example - Winter 2025
In addition to our own projects, UpLeveled also lives what we teach and aims to be good open source citizens by contributing to other projects when we encounter problems.
One common type of problem we encounter is the "papercut":
- bugs or inconsistencies which appear to be minor
- to more experienced developers, mildly annoying and not worth fixing
- to students, potentially a blocker to their learning
These papercuts can include errors during setup steps, documentation issues, small bugs and even security issues.
By fixing these papercuts, we can help students focus on learning and building projects, and raise all boats by contributing the fix to everyone else.
Another area of focus for UpLeveled is keeping up to date:
- we produce new versions of our curricula multiple times per year
- we upgrade to new versions of OSes, browsers, runtimes, frameworks and libraries
- we report and fix any issues we encounter during the upgrades
- we adopt new patterns and consider new tools
Some examples of issues and pull requests related to these upgrades:
In January 2023, while adopting the Next.js App Router and switching our material to React Server Components, we found that Route Handlers did not have the same capabilities to check return types using TypeScript, and contributed this feature to Next.js:
- Add optional generic parameter to
NextResponse
invercel/next.js
During a June 2024 iteration on our Expo / React Native lecture,
we switched the scaffolder and template we used and dropped the
obsolete config in .npmrc
:
- Switch to
create-expo-app
+blank-typescript
, remove.npmrc
cmds inupleveled/system-setup
More recently, a March 2025 upgrade to
[email protected]
caused resolution
errors for Bun modules like bun:test
while using
eslint-plugin-import-x
, which we fixed with a documentation
update:
- Document eslint-import-resolver-typescript
bun
option, fix ESM import inun-ts/eslint-plugin-import-x
Over the long term, another goal of UpLeveled is to help evolve the ecosystem by extending compatibility, encouraging adoption of new technologies and discussing new standards proposals.
Extending compatibility has included issues and pull requests such as:
- Node.js Type Stripping in
node_modules/*/*.ts
innodejs/typescript
- Add nested
transforms in
porsager/postgres
- Support for SafeQL on
Windows
in
ts-safeql/safeql
- Recognize referential actions as keywords in ON
UPDATE/DELETE
in
sql-formatter-org/sql-formatter
Encouraging adoption of new technologies has also ranged across multiple topics, but an area which has often required additional attention has been ESM, including TypeScript module resolution:
- "module": "node16" error:
This expression is not callable
inpostcss/postcss
- disposable-email-domains: Use CommonJS export for "module":
"node16"
in
DefinitelyTyped/DefinitelyTyped
- Module not found: Fully Specified ESM Imports (with
.js
extension) in TypeScript invercel/next.js
While we have not yet invested the time to become deeply involved in shaping standards by activities like writing spec docs or becoming a TC39 champion, we have at times added feedback in existing discussions or contributed short proposal notes:
- Skip parameters in function parameter lists on Bluesky
await fetch.json(url)
proposal on Twitter- Standard wire data format + form field error message UI for showing server validation errors without JS on Twitter
- Add style ordinal/cardinal to NumberFormat
(RBNF)
in
tc39/ecma402
I can highly recommend getting involved in open source - benefits include the ability to:
- learn about new technologies
- learn how to communicate and work with others
- network with developers in the community
- become familiar with interesting projects
There are plenty of resources on how to get started with open source, so I won't write another guide on that. If you're looking for a good place to start, try How to Contribute to Open Source by Open Source Guides.
Here are my more personal field notes for contributors:
- Superpower: match the style and philosophy of the project
- read the code of the project and try to match the style
- also match the philosophy or goal of the project, if there is one
- avoids wasting time on back and forth
- Superpower: review your own contributions
- read your own code as if you're the reviewer
- try to find issues and fix them before submitting
- comment on surprising or unusual parts of your contribution
- Start small, but contribute widely
- to ease into open source, make small contributions - small contributions are also helpful for others
- if you resolve or work around an issue others have reported, add your approach if it's not already there
- if you find a small issue, report or fix it
- get into the habit of looking through the issues and pull requests of projects you use - soon you'll be contributing to a wide range of projects
- Don't fall in love with your solution
- be open to feedback and changes
- acknowledge that your solution might not be the best one, or may not be accepted at all
- Use AI carefully in your contributions
- AI can help you understand the codebase and suggest changes that match the style
- review AI-generated code carefully - it can produce low-quality output aka "AI slop"
- using AI tools can make the difference between contributing and not contributing
- Use the Refined GitHub browser extension to simplify the GitHub interface and add helpful features
- Report issues with enough information to make them actionable
- explain what you were trying to do
- describe what you observed
- describe what you expected
- include a minimal reproduction repo or code block
- include the steps to reproduce the issue
- include relevant version numbers
- prefer code blocks over screenshots
- think through the problem and provide a guess of what the problem might be near the end of the issue
During my time contributing to open source, I have also developed opinions on how projects can optimize their CX (Contributor Experience) for new contributors:
- Optimize for contributions from web clients such as the GitHub
web interface
- avoid requiring a full local dev environment or terminal execution, also for contributions changing tests
- Optimize for AI-assisted contributions
- describe the project's style and provide instructions for
LLMs in standard locations like
.github/instructions/*.instructions.md
or.cursor/rules/*.mdc
- describe the project's style and provide instructions for
LLMs in standard locations like
- Simplify documentation and make it easier to understand for a
wide audience
- avoid jargon
- prioritize clarity over purity / brevity - short explanations are often not enough for a wide audience
- don't avoid repetition - it can help with navigation and comprehension
- embed runnable examples and playgrounds in the docs
- Provide a bug reproduction template
- example: Next.js repro template
- example: Reproduction Template of ESLint Stylistic
- example: GitHub template for creating a Rspack minimal reproducible example
- more examples: Awesome Open Source Automation
Thanks to the Open Source Initiative and Nick Vidal for collaborating on Maintainer Month and showcasing maintainers through this and other articles.