{"id":29403778,"url":"https://github.com/julianpeeters/avrohugger","last_synced_at":"2025-07-10T19:02:38.552Z","repository":{"id":25471572,"uuid":"28902106","full_name":"julianpeeters/avrohugger","owner":"julianpeeters","description":"Generate Scala case class definitions from Avro schemas","archived":false,"fork":false,"pushed_at":"2025-05-05T04:12:49.000Z","size":1571,"stargazers_count":202,"open_issues_count":32,"forks_count":121,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-06-07T23:52:43.599Z","etag":null,"topics":["avro","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/julianpeeters.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-01-07T06:39:58.000Z","updated_at":"2025-05-05T04:05:04.000Z","dependencies_parsed_at":"2023-02-12T12:00:37.620Z","dependency_job_id":"33c517e6-fdc5-4c4a-b95e-ab6502e8d160","html_url":"https://github.com/julianpeeters/avrohugger","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/julianpeeters/avrohugger","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julianpeeters%2Favrohugger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julianpeeters%2Favrohugger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julianpeeters%2Favrohugger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julianpeeters%2Favrohugger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/julianpeeters","download_url":"https://codeload.github.com/julianpeeters/avrohugger/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julianpeeters%2Favrohugger/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264637601,"owners_count":23642026,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["avro","scala"],"created_at":"2025-07-10T19:01:08.516Z","updated_at":"2025-07-10T19:02:38.543Z","avatar_url":"https://github.com/julianpeeters.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# avrohugger\n\n**Schema-to-case-class code generation for working with Avro in Scala.**\n\n* `avrohugger-core`: Generate source code at runtime for evaluation at a later step.\n* `avrohugger-filesorter`: Sort schema files for proper compilation order.\n* `avrohugger-tools`: Generate source code at the command line with the avrohugger-tools jar.\n\n**Alternative Distributions:**\n\n* [sbt](https://github.com/julianpeeters/sbt-avrohugger): `sbt-avrohugger` - Generate source code at compile time with an sbt plugin.\n* [Maven](https://github.com/makubi/avrohugger-maven-plugin): `avrohugger-maven-plugin` - Generate source code at compile time with a maven plugin.\n* [Mill](https://github.com/joan38/mill-avro): `mill-avro` - Generate source code at compile time with a Mill plugin.\n* [Gradle](https://github.com/zladovan/gradle-avrohugger-plugin): `gradle-avrohugger-plugin` - Generate source code at compile time with a gradle plugin.\n* [mu-rpc](https://github.com/higherkindness/mu-scala): `mu-scala` - Generate rpc models, messages, clients, and servers.\n\nTable of contents\n=================\n\n  * [Supported Formats: `Standard`, `SpecificRecord`](#generates-scala-case-classes-in-various-formats)\n  * [Supported Datatypes](#supports-generating-case-classes-with-arbitrary-fields-of-the-following-datatypes)\n  * [Logical Types Support](#logical-types-support)\n  * [Protocol Support](#protocol-support)\n  * [Doc Support](#doc-support)\n  * [Usage](#usage)\n    * [`avrohugger-core`](#avrohugger-core)\n      * [Get the dependency](#get-the-dependency-with)\n      * [Description](#description)\n      * [Example](#example)\n      * [Customizable type mapping](#customizable-type-mapping)\n      * [Customizable namespace mapping](#customizable-namespace-mapping)\n      * [Generate Classes Instead of Case Classes](#generate-classes-instead-of-case-classes)\n    * [`avrohugger-filesorter`](#avrohugger-filesorter)\n    * [`avrohugger-tools`](#avrohugger-tools)\n  * [Warnings](#warnings)\n  * [Best Practices](#best-practices)\n  * [Testing](#testing)\n  * [Credits](#credits)\n\n\n##### Generates Scala case classes in various formats:\n\n* `Standard` Vanilla case classes (for use with Apache Avro's [`GenericRecord`\nAPI](https://avro.apache.org/docs/1.11.1/getting-started-java/#serializing-and-deserializing-with-code-generation), etc.)\n\n* `SpecificRecord` Case classes that implement `SpecificRecordBase` and\ntherefore have mutable `var` fields (for use with the Avro Specific API -\nScalding, Spark, Avro, etc.).\n\n##### Supports generating case classes with arbitrary fields of the following datatypes:\n\n|Avro|`Standard`|`SpecificRecord`|Notes|\n|----------|---------|----------|---------|\n|INT|Int|Int| See [Logical Types: `date`](https://github.com/julianpeeters/avrohugger#logical-types-support)|\n|LONG|Long|Long| See [Logical Types: `timestamp-millis`](https://github.com/julianpeeters/avrohugger#logical-types-support)|\n|FLOAT|Float|Float||\n|DOUBLE|Double|Double||\n|STRING|String|String||\n|BOOLEAN|Boolean|Boolean||\n|NULL|Null|Null||\n|MAP|Map|Map||\n|ENUM|scala.Enumeration\u003cbr\u003eScala case object\u003cbr\u003eJava Enum\u003cbr\u003eEnumAsScalaString|Java Enum\u003cbr\u003eEnumAsScalaString| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|BYTES|Array[Byte]\u003cbr\u003eBigDecimal|Array[Byte]\u003cbr\u003eBigDecimal| See [Logical Types: `decimal`](https://github.com/julianpeeters/avrohugger#logical-types-support)|\n|FIXED|case class\u003cbr\u003ecase class + schema|case class extending `SpecificFixed`| See [Logical Types: `decimal`](https://github.com/julianpeeters/avrohugger#logical-types-support)|\n|ARRAY|Seq\u003cbr\u003eList\u003cbr\u003eArray\u003cbr\u003eVector|Seq\u003cbr\u003eList\u003cbr\u003eArray\u003cbr\u003eVector| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|UNION|Option\u003cbr\u003eEither\u003cbr\u003eShapeless Coproduct\u003cbr\u003eScala 3 Union Types|Option\u003cbr\u003eEither\u003cbr\u003eShapeless Coproduct\u003cbr\u003eScala 3 Union Types| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|RECORD|case class\u003cbr\u003ecase class + schema|case class extending `SpecificRecordBase`| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|PROTOCOL|_No Type_\u003cbr\u003eScala ADT|RPC trait\u003cbr\u003eScala ADT| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|Date|java.time.LocalDate\u003cbr\u003ejava.sql.Date\u003cbr\u003eInt|java.time.LocalDate\u003cbr\u003ejava.sql.Date\u003cbr\u003eInt| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|TimeMillis|java.time.LocalTime\u003cbr\u003eInt|java.time.LocalTime\u003cbr\u003eInt| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|TimeMicros|java.time.LocalTime\u003cbr\u003eLong|java.time.LocalTime\u003cbr\u003eLong| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|TimestampMillis|java.time.Instant\u003cbr\u003ejava.sql.Timestamp\u003cbr\u003eLong|java.time.Instant\u003cbr\u003ejava.sql.Timestamp\u003cbr\u003eLong| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|TimestampMicros|java.time.Instant\u003cbr\u003ejava.sql.Timestamp\u003cbr\u003eLong|java.time.Instant\u003cbr\u003ejava.sql.Timestamp\u003cbr\u003eLong| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|LocalTimestampMillis|java.time.LocalDateTime\u003cbr\u003eLong|java.time.LocalDateTime\u003cbr\u003eLong| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|LocalTimestampMicros|java.time.LocalDateTime\u003cbr\u003eLong|java.time.LocalDateTime\u003cbr\u003eLong| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|UUID|java.util.UUID|java.util.UUID| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n|Decimal|BigDecimal|BigDecimal| See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)|\n\n##### Logical Types Support:\n\n_NOTE: Currently logical types are only supported for `Standard` and `SpecificRecord` formats_\n\n* `date`: Annotates Avro `int` schemas to generate `java.time.LocalDate` or `java.sql.Date` (See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)). Examples: [avdl](https://github.com/julianpeeters/sbt-avrohugger/blob/master/src/sbt-test/avrohugger/GenericSerializationTests/src/main/avro/logical.avdl#L9), [avsc](https://github.com/julianpeeters/sbt-avrohugger/blob/master/src/sbt-test/avrohugger/GenericSerializationTests/src/main/avro/logical.avsc#L22-L27).\n* `decimal`: Annotates Avro `bytes` and `fixed` schemas to generate `BigDecimal`. Examples: [avdl](https://github.com/julianpeeters/sbt-avrohugger/blob/master/src/sbt-test/avrohugger/GenericSerializationTests/src/main/avro/logical.avdl#L6), [avsc](https://github.com/julianpeeters/sbt-avrohugger/blob/master/src/sbt-test/avrohugger/GenericSerializationTests/src/main/avro/logical.avsc#L6-L14).\n* `timestamp-millis`: Annotates Avro `long` schemas to genarate `java.time.Instant` or `java.sql.Timestamp` or `long` (See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)). Examples: [avdl](https://github.com/julianpeeters/sbt-avrohugger/blob/master/src/sbt-test/avrohugger/GenericSerializationTests/src/main/avro/logical.avdl#L8), [avsc](https://github.com/julianpeeters/sbt-avrohugger/blob/master/src/sbt-test/avrohugger/GenericSerializationTests/src/main/avro/logical.avsc#L15-L21).\n* `uuid`: Annotates Avro `string` schemas and idls to generate `java.util.UUID` (See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping)). Example: [avsc](https://github.com/julianpeeters/sbt-avrohugger/blob/master/src/sbt-test/avrohugger/GenericSerializationTests/src/main/avro/logical.avsc#L29-L35).\n* `time-millis`: Annotates Avro `int` schemas to genarate `java.time.LocalTime` or `java.sql.Time` or `int`\n\n##### Protocol Support:\n\n* the records defined in `.avdl`, `.avpr`, and json protocol strings can be generated as ADTs if the protocols define more than one Scala definition (_note:_ message definitions are ignored when this setting is used). See [Customizable Type Mapping](https://github.com/julianpeeters/avrohugger#customizable-type-mapping).\n\n* For `SpecificRecord`, if the protocol contains messages then an RPC trait is generated (instead of generating and ADT, or ignoring the message definitions).\n\n\n##### Doc Support:\n\n* `.avdl`: Comments that begin with `/**` are used as the documentation string for the type or field definition that follows the comment.\n\n* `.avsc`, `.avpr`, and `.avro`: Docs in Avro schemas are used to define a case class' ScalaDoc\n\n* `.scala`: ScalaDocs of case class definitions are used to define record and field docs\n\n\n_Note:_ Currently [Treehugger](http://eed3si9n.com/treehugger/comments.html#Scaladoc+style+comments) appears to generate Javadoc style docs (thus compatible with ScalaDoc style).\n\n\n\n\n## Usage\n\n* **Library For Scala 2.12, 2.13, and 3**\n* **Parses Schemas and IDLs with Avro version 1.11**\n* **Generates Code Compatible with Scala 2.12, 2.13, 3**\n\n\n\n#### `avrohugger-core`\n\n##### Get the dependency with:\n\n    \"com.julianpeeters\" %% \"avrohugger-core\" % \"2.13.0\"\n\n\n##### Description:\n\nInstantiate a `Generator` with `Standard` or `SpecificRecord` source formats.\nThen use\n\n\n`tToFile(input: T, outputDir: String): Unit`\n\n\nor\n\n\n`tToStrings(input: T): List[String]`\n\n\nwhere `T` can be `File`, `Schema`, or `String`.\n\n##### Example\n\n\n\n    import avrohugger.Generator\n    import avrohugger.format.SpecificRecord\n    import java.io.File\n\n    val schemaFile = new File(\"path/to/schema\")\n    val generator = new Generator(SpecificRecord)\n    generator.fileToFile(schemaFile, \"optional/path/to/output\") // default output path = \"target/generated-sources\"\n\n\nwhere an input `File` can be `.avro`, `.avsc`, `.avpr`, or `.avdl`,\n\n\nand where an input `String` can be the string representation of an Avro schema,\nprotocol, IDL, or a set of case classes that you'd like to have implement\n`SpecificRecordBase`.\n\n\n##### Customizable Type Mapping:\n\nTo reassign Scala types to Avro types, use the following (e.g. for customizing `Specific`):\n    \n    import avrohugger.format.SpecificRecord\n    import avrohugger.types.ScalaVector\n    \n    val myScalaTypes = Some(SpecificRecord.defaultTypes.copy(array = ScalaVector))\n    val generator = new Generator(SpecificRecord, avroScalaCustomTypes = myScalaTypes)\n\n* `record` can be assigned to `ScalaCaseClass` and `ScalaCaseClassWithSchema`(with schema in a companion object)\n* `array` can be assigned to `ScalaSeq`, `ScalaArray`, `ScalaList`, and `ScalaVector`\n* `enum` can be assigned to `JavaEnum`, `ScalaCaseObjectEnum`, `EnumAsScalaString`, and `ScalaEnumeration`\n* `fixed` can be assigned to `ScalaCaseClassWrapper` and `ScalaCaseClassWrapperWithSchema`(with schema in a companion object)\n* `union` can be assigned to `OptionShapelessCoproduct`, `OptionEitherShapelessCoproduct`, `OptionalShapelessCoproduct` or `OptionScala3UnionType`\n* `int`, `long`, `float`, `double` can be assigned to `ScalaInt`, `ScalaLong`, `ScalaFloat`, `ScalaDouble`\n* `protocol` can be assigned to `ScalaADT` and `NoTypeGenerated`\n* `decimal` can be assigned to e.g. `ScalaBigDecimal(Some(BigDecimal.RoundingMode.HALF_EVEN))` and `ScalaBigDecimalWithPrecision(None)` (via Shapeless Tagged Types)\n\nSpecifically for unions:\n\n| Field Type ⬇️ / Behaviour ➡️            | OptionShapelessCoproduct                      | OptionEitherShapelessCoproduct                | OptionalShapelessCoproduct                    | OptionScala3UnionType      |\n|-----------------------------------------|-----------------------------------------------|-----------------------------------------------|-----------------------------------------------|----------------------------|\n| `[{\"type\": \"map\", \"values\": \"string\"}]` | `Map[String, String]`                         | `Map[String, String]`                         | `Map[String, String] :+: CNil`                | `Map[String, String]`      \n| `[\"null\", \"double\"]`                    | `Option[Double]`                              | `Option[Double]`                              | `Option[Double :+: CNil]`                     | `Option[Double]`           \n| `[\"int\", \"string\"]`                     | `Int :+: String :+: CNil`                     | `Either[Int, String]`                         | `Int :+: String :+: CNil`                     | `Int \\| String`            \n| `[\"null\", \"int\", \"string\"]`             | `Option[Int :+: String :+: CNil]`             | `Option[Either[Int, String]]`                 | `Option[Int :+: String :+: CNil]`             | `Option[Int \\| String]`    \n| `[\"boolean\", \"int\", \"string\"]`          | `Boolean :+: Int :+: String :+: CNil`         | `Boolean :+: Int :+: String :+: CNil`         | `Boolean :+: Int :+: String :+: CNil`         | `Boolean \\| Int \\| String` \n| `[\"null\", \"boolean\", \"int\", \"string\"]`  | `Option[Boolean :+: Int :+: String :+: CNil]` | `Option[Boolean :+: Int :+: String :+: CNil]` | `Option[Boolean :+: Int :+: String :+: CNil]` | `Option[Boolean \\| Int \\| String]`\n\n##### Customizable Namespace Mapping:\n\nNamespaces can be reassigned by instantiating a `Generator` with a custom\nnamespace map:\n\n\n    val generator = new Generator(SpecificRecord, avroScalaCustomNamespace = Map(\"oldnamespace\"-\u003e\"newnamespace\"))\n\n_Note:_ Namespace mappings work for with KafkaAvroSerializer but not for KafkaAvroDeserializer; if anyone knows how to configure the deserializer to map incoming schema names to target class names please speak up!\n    \nWildcarding the beginning of a namespace is permitted, place a single asterisk after the prefix that you want to map and any matching schema will have its \nnamespace rewritten. Multiple conflicting wildcards are not permitted.\n\n    val generator = new Generator(SpecificRecord, avroScalaCustomNamespace = Map(\"example.*\"-\u003e\"example.newnamespace\"))\n\n\n#### `avrohugger-filesorter`\n\n\n##### Get the dependency with:\n\n    \"com.julianpeeters\" %% \"avrohugger-filesorter\" % \"2.13.0\"\n    \n\n##### Description:\n\nTo ensure dependent schemas are compiled in the proper order (thus avoiding `org.apache.avro.SchemaParseException: Undefined name: \"com.example.MyRecord\"` parser errors), sort avsc and avdl files with the `sortSchemaFiles` method on `AvscFileSorter` and `AvdlFileSorter`respectively.\n\n\n##### Example:\n\n\n    import avrohugger.filesorter.AvscFileSorter\n    import java.io.File\n    \n    val sorted: List[File] = AvscFileSorter.sortSchemaFiles((srcDir ** \"*.avsc\"))\n\n\n#### `avrohugger-tools`\n\n\n  Download the avrohugger-tools jar for Scala [2.12](https://search.maven.org/remotecontent?filepath=com/julianpeeters/avrohugger-tools_2.12/2.13.0/avrohugger-tools_2.12-2.13.0-assembly.jar), or Scala [2.13](https://search.maven.org/remotecontent?filepath=com/julianpeeters/avrohugger-tools_2.13/2.13.0/avrohugger-tools_2.13-2.13.0-assembly.jar) (\u003e30MB!) and use it like the avro-tools jar `Usage: [-string] (schema|protocol|datafile) input... outputdir`:\n\n\n* `generate` generates Scala case class definitions:\n\n`java -jar /path/to/avrohugger-tools_2.12-2.13.0-assembly.jar generate schema user.avsc . `\n\n\n* `generate-specific` generates definitions that extend Avro's `SpecificRecordBase`:\n\n`java -jar /path/to/avrohugger-tools_2.12-2.13.0-assembly.jar generate-specific schema user.avsc . `\n\n\n## Warnings\n\n1) If your framework is one that relies on reflection to get the Schema, it\nwill fail since Scala fields are private. Therefore preempt it by passing in\na Schema to DatumReaders and DatumWriters (e.g. `val sdw = SpecificDatumWriter[MyRecord](schema)`).\n\n2) For the `SpecificRecord` format, generated case class fields must be\nmutable (`var`) in order to be compatible with the SpecificRecord API. _Note:_\nIf your framework allows `GenericRecord`, [avro4s](https://github.com/sksamuel/avro4s)\nprovides a type class that converts to and from immutable case classes cleanly.\n\n3) `SpecificRecord` requires that `enum` be represented as `JavaEnum`\n\n\n## Testing\n\nTo test for regressions, please run `sbt:avrohugger\u003e + test`.\n\nTo test that generated code can be de/serialized as expected, please run:\n1) `sbt:avrohugger\u003e + publishLocal`\n2) then clone sbt-avrohugger and update its avrohugger dependency to the locally\npublished version\n3) finally run `sbt:sbt-avrohugger\u003e scripted avrohugger/*`, or, e.g., `scripted avrohugger/GenericSerializationTests`\n\n\n#### Credits\nDepends on [Avro](https://github.com/apache/avro) and [Treehugger](https://github.com/eed3si9n/treehugger). `avrohugger-tools` is based on [avro-tools](http://avro.apache.org/docs/1.7.7/gettingstartedjava.html#Serializing+and+deserializing+with+code+generation).\n\n\nContributors:\n\n|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | | | |\n|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|     :---      | :---      |          :--- |\n| [Marius Soutier](https://github.com/mariussoutier) \u003c/br\u003e [Brian London](https://github.com/BrianLondon) \u003c/br\u003e [alancnet](https://github.com/alancnet) \u003c/br\u003e [Matt Coffin](https://github.com/mcoffin) \u003c/br\u003e [Ryan Koval](http://github.ryankoval.com) \u003c/br\u003e [Simonas Gelazevicius](https://github.com/simsasg) \u003c/br\u003e [Paul Snively](https://github.com/PaulAtBanno) \u003c/br\u003e [Marco Stefani](https://github.com/inafets) \u003c/br\u003e [Andrew Gustafson](https://github.com/agustafson) \u003c/br\u003e [Kostya Golikov](https://github.com/lazyval) \u003c/br\u003e [Plínio Pantaleão](https://github.com/plinioj) \u003c/br\u003e [Sietse de Kaper](https://github.com/targeter) \u003c/br\u003e [Martin Mauch](https://github.com/nightscape) \u003c/br\u003e [Leon Poon](https://github.com/LeonPoon) \u003c/br\u003e [Andrzej Ressel](https://github.com/andrzejressel) | [Paul Pearcy](https://github.com/ppearcy) \u003c/br\u003e [Matt Allen](https://github.com/Matt343) \u003c/br\u003e [C-zito](https://github.com/C-Zito) \u003c/br\u003e [Tim Chan](https://github.com/timchan-lumoslabs) \u003c/br\u003e [Saket](https://github.com/skate056) \u003c/br\u003e [Daniel Davis](https://github.com/wabu) \u003c/br\u003e [Zach Cox](https://github.com/zcox) \u003c/br\u003e [Diego E. Alonso Blas](https://github.com/diesalbla) \u003c/br\u003e [Fede Fernández](https://github.com/fedefernandez) \u003c/br\u003e [Rob Landers](https://github.com/withinboredom) \u003c/br\u003e [Simon Petty](https://github.com/simonpetty) \u003c/br\u003e [Andreas Drobisch](https://github.com/adrobisch) \u003c/br\u003e [Timo Schmid](https://github.com/timo-schmid) \u003c/br\u003e [Dmytro Orlov](https://github.com/DmytroOrlov)  \u003c/br\u003e [Mikołaj Jakubowski](https://github.com/mkljakubowski) | [Stefano Galarraga](https://github.com/galarragas) \u003c/br\u003e [Lars Albertsson](https://github.com/lallea) \u003c/br\u003e [Eugene Platonov](https://github.com/jozic) \u003c/br\u003e [Jerome Wacongne](https://github.com/ch4mpy) \u003c/br\u003e [Jon Morra](https://github.com/jon-morra-zefr) \u003c/br\u003e [Raúl Raja Martínez](https://github.com/raulraja) \u003c/br\u003e [Kaur Matas](https://github.com/kmatasflp) \u003c/br\u003e [Chris Albright](https://github.com/chrisalbright) \u003c/br\u003e [Francisco Díaz](https://github.com/franciscodr) \u003c/br\u003e [Bobby Rauchenberg](https://github.com/bobbyrauchenberg) \u003c/br\u003e [Leonard Ehrenfried](https://github.com/leonardehrenfried) \u003c/br\u003e [François Sarradin](https://github.com/fsarradin) \u003c/br\u003e [niqdev](https://github.com/niqdev) \u003c/br\u003e [rsitze-mmai](https://github.com/rsitze-mmai) \u003c/br\u003e [Wessel W. Bakker](https://github.com/wwbakker)| [Julien BENOIT](https://github.com/jbenoit2011)  \u003c/br\u003e [Adam Drakeford](https://github.com/dr4ke616) \u003c/br\u003e [Carlos Silva](https://github.com/alchimystic) \u003c/br\u003e [ismail Benammar](https://github.com/ismailBenammar) \u003c/br\u003e [mcenkar](https://github.com/mcenkar) \u003c/br\u003e [Luca Tronchin](https://github.com/ltronky) \u003c/br\u003e [LydiaSkuse](https://github.com/LydiaSkuse) \u003c/br\u003e [Algimantas Milašius](https://github.com/AlgMi) \u003c/br\u003e [Leonard Ehrenfried](https://github.com/leonardehrenfried) \u003c/br\u003e [Massimo Siani](https://github.com/massimosiani)  \u003c/br\u003e [Konstantin](https://github.com/tyger) \u003c/br\u003e [natefitzgerald](https://github.com/natefitzgerald) \u003c/br\u003e  [Victor](https://github.com/gafiatulin) \u003c/br\u003e [steve-e](https://github.com/steve-e) |\n\n\n##### Criticism is appreciated.\n\n##### Fork away, just make sure the tests pass before sending a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjulianpeeters%2Favrohugger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjulianpeeters%2Favrohugger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjulianpeeters%2Favrohugger/lists"}