- Write code as if the same person authored the entire codebase — consistency is paramount.
- Favor functional, declarative style: list comprehensions,
map/filter/reduce. list(dict.fromkeys(items))for order-preserving deduplication.- Concise but readable — no unnecessary verbosity, no cryptic one-liners.
- Never reinvent the wheel — always search for existing utilities before writing new code.
- PEP 8, 4-space indentation, format with
ruff format(previouslyblack), type-check withmypy. snake_casefor modules/functions,PascalCasefor classes.- Import order: stdlib → third-party → karrio core → local/relative.
- Always use
import karrio.lib as lib— NEVER the legacyDP,SF,NF,DF,XPutilities, and NEVER create new utility functions that duplicatelib.*. - Use specific exceptions; never bare
except:orexcept Exception:. - No mutable default arguments — use
functools.partialor sentinel pattern.
- All user-facing strings must use
django.utils.translation.gettext(orgettext_lazy) — never hardcode messages. - This includes: error messages, validation messages, notification text, and any string returned in API responses that users see.
- Import as
from django.utils.translation import gettext as _and wrap strings:_("Shipment created successfully"). - Internal log messages and developer-facing strings (e.g., exception names, debug logs) do NOT need
gettext.
- 2-space indentation, format with Prettier.
PascalCasefor components,camelCasefor functions/variables.- Functional components only — no class components; use hooks.
- Import order: React/Next → third-party →
@karrio/*packages → local. - Always import types from
@karrio/types— never define inline. - Use existing hooks from
@karrio/hooks/*— never raw fetch/axios. - Use existing UI components from
@karrio/ui— never duplicate patterns. - Never use
any— use proper types, orunknownwith type guards. - Use regenerate scripts (
./bin/run-generate-on, Next codegen) for type generation — never manually edit generated files.
- Tenant-scoped models inherit from
OwnedEntityand are filtered viaModel.access_by(request)(orModel.objects.filter(org=request.user.org)at the ORM level). - System models: plain
models.Model(no tenant scoping). - Register with
@core.register_modeldecorator when applicable. - Use
functools.partial(core.uuid, prefix="xxx_")for ID generation. - JSONField defaults:
functools.partial(karrio.server.core.models._identity, value=[])(never bare[]).
- Use mixin classes for shared logic between Account and System serializers.
@owned_model_serializerfor tenant-scoped serializers (handlescreated_by+link_org()).- Plain serializers for system-scoped models (manual
created_byincreate()). - Always use
Serializer.map()pattern for validation + save.
pytest— alwaysunittestfor SDK,karrio testfor Django server.- Raw SQL in migrations — use Django migration operations (
AddField,RemoveField,RenameField,AlterField,RunPython) only. RunSQL— must work across SQLite, PostgreSQL, MySQL.- New utility functions duplicating
karrio.lib— checklib.*reference first. - Bare exceptions, mutable defaults,
anytypes. - Class components in React — use function components + hooks.
- Manual CSS files — use Tailwind classes.
- Features not explicitly requested.