Luxor.jl: simple 2D vector drawing for Julia
Simple drawings using vector graphics; Cairo "for tourists!"
At a glance
- What is it?
- Luxor is a Julia package for procedural 2D vector graphics that positions itself as Cairo for tourists, with shorter names, default contexts and simplified functions. It is a deliberately narrow tool: static pictures, shapes, clipping masks, turtle graphics and simple animations, and the README points elsewhere for anything elaborate.
- Who is it for?
- Luxor fits a Julia user who wants to draw a diagram, a poster or a simple animation from a script and would rather not learn the full Cairo interface, and it fits as a teaching surface for 2D graphics. It is the wrong choice for interactive work, for elaborate animation, or for the 2D and 3D plotting that Makie covers, since the README itself routes you to Makie, Javis.jl and Pluto.jl for those.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Julia, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Cairo, but with the sharp edges taken off
The project description sets the tone in three words: simple drawings using vector graphics, Cairo for tourists.
Luxor is a Julia package for drawing simple static 2D vector graphics. It provides basic drawing functions and utilities for working with shapes, polygons, clipping masks, PNG and SVG images, turtle graphics, and simple animations.
The design goal is stated explicitly in the README: the focus of Luxor is on simplicity and ease of use, and it should be easier to use than plain Cairo.jl, with shorter names, default contexts and simplified functions. That is a precise description of a wrapper's job, and it is worth understanding what it implies. Luxor sits on top of the Cairo bindings for Julia, so you get the same rendering engine and the same output formats, but with a smaller and flatter surface to learn. The functions are named the way a person would say them out loud, the context is created for you rather than passed around, and the underscore-heavy names of the underlying API do not appear.
The second thing the README stresses is the execution model. Luxor is thoroughly procedural and static: your code issues a sequence of simple graphics commands until you have completed a drawing, and then the results are saved into a PDF, PNG, SVG or EPS file.
That model is the whole contract. There is no retained scene graph, no interactive canvas and no retained mode. You draw, then you save, and the drawing exists as a file.
What is in the box, and what the model costs
The utility list is short enough to enumerate, which is unusual for a graphics package and reflects the stated scope.
There are basic drawing functions, utilities for shapes and polygons, clipping masks for restricting what a subsequent operation can touch, functions for working with PNG and SVG images, turtle graphics for line-by-line drawing, and simple animations.
Turtle graphics are worth a second look, because they change the shape of the code you write. Instead of specifying geometry, you move a cursor and draw as you go, which is how you produce drawings that are more algorithmic than geometric. For certain kinds of artwork, in particular recursive and generative pieces, that is a much shorter program than listing coordinates.
The cost of the procedural model shows up in a specific place: nothing is retained between commands. There is no object you can query later, no layer you can go back and edit, and no scene you can re-render at a different size. If a drawing turns out to be wrong, you change the code and run it again. That is the right trade for a script that produces a finished picture, and the wrong one for anything where you expect to adjust the output interactively after seeing it.
The output formats close the loop. PDF, PNG, SVG and EPS cover print, raster, vector and legacy vector, and the SVG support also means the same drawing can be inspected in a browser or an editor afterwards.
Three explicit off-ramps from the README
The README is unusually helpful here, because it names the tools you should use instead, in three separate cases. Each of those is a different kind of project, and together they tell you what Luxor is not.
For complex or sophisticated graphics in 2D and 3D, the README says Makie.jl is the best choice. That is a different category of library: a plotting and visualisation system with a much larger feature set, a different API, and interactive capability.
For complex or elaborate animations, the README points to Javis.jl together with Makie. Javis is a Julia animation package, and the pairing suggests the intended split, with Makie handling the drawing primitives and Javis handling the timeline and the export.
For interactivity, the README points to Pluto.jl and Makie. Luxor is not interactive, and the README says so directly. A Pluto notebook is a reactive document format for Julia, and pairing it with a plotting system gives you a live document where changing a value redraws the figure.
Read together, these three sentences are a design brief for Luxor as well as a set of alternatives. It is for static output, produced by a script, in two dimensions, at a level of complexity where a handful of shapes and paths suffice.
The comparison with Cairo.jl is the one to hold on to, because it is the difference in kind rather than in scale. Makie, Javis and Pluto extend what you can produce. Luxor makes the same class of output easier to write, and the smaller API surface is the entire product.
Two versions of the documentation, and where the tutorials are
The documentation badges at the top of the README are the first thing a new user should read, because they encode a convention that many Julia packages follow and that trips people up.
The stable documentation describes the current release. The development documentation contains changes that are still in the master branch and may change before the next release. Two sets of docs for one package means you have to know which one you are reading, and the distinction is a version difference, not a beginner versus advanced difference.
The manual itself is the Luxor Manual, hosted at the JuliaGraphics GitHub Pages site, and the README states that tutorials can be found there by clicking the badges. That is the primary learning resource, and the README adds a second and third path: a YouTube channel with Luxor-related videos, and blog posts by the author at cormullion.github.io.
The author is worth noting because the project is not a committee effort. The CI badges point at workflows under the cormullion repository for the Luxor project, the appveyor configuration names the luxor-jl project, and the package's own description in the README reads like a personal design statement rather than a corporate one. That is common in the Julia ecosystem, where a package is often one person's work with a community around it, and it has a practical consequence for you: the bus factor is one person, and the pace of the 4.x releases is the pace at which that person works.
The gallery figure in the README, a luxorgallery.svg in the documentation assets, is the fastest way to judge whether the output style suits your purpose before you write any code.
What the repository layout says about the project
The top-level listing is conventional Julia package structure, and it tells you where to look for things.
src/ holds the package source, test/ the test suite, ext/ the package extensions, docs/ the manual sources, benchmark/ a benchmarks directory, and data/ the data used by examples or tests. There is a Project.toml for the package environment, a CHANGELOG.md, a CONTRIBUTING.md and a LICENSE.md. The .JuliaFormatter.toml at the root shows the project is formatted with JuliaFormatter, which is a Julia community convention that keeps the diff readable.
The badges tell you the rest of the story. There are build status badges for GitHub Actions and AppVeyor, and a Travis badge, so the package is tested on more than one continuous integration service, which for a graphics library matters because rendering output can differ between platforms. A code coverage badge points at codecov, and a PkgEval badge points at the Julia package quality report, which is the community's automated check that a package installs, imports and precompiles cleanly on the supported Julia versions.
That PkgEval badge is the one most people skip past and the one most worth knowing about. Because Luxor sits on Cairo, its installation depends on that native dependency being available and working on your platform, and the PkgEval report is where you would look to see whether it does on yours.
There is a benchmark/ directory, which tells you the author cares about the performance of the drawing path, and a CHANGELOG.md, which is the document to read before upgrading a version that has moved through 4.x.
Version cadence and the licence question
The release history is a steady sequence of 4.x tags. v4.4.1 came on 2026-01-25, and then v4.5 and v4.5.0 both landed on 2026-04-09, an hour apart by the timestamps. The repository is not archived, and the last push was on 2026-08-19, so work continues between releases rather than stopping at a tag.
That two-tags-on-one-day pattern is normal in the Julia ecosystem, where a release is often cut for a registry event and a patch tag follows immediately, and it does not indicate two different features. It does mean you should read the CHANGELOG rather than infer behaviour from a version number.
The licence is the item to check before you commit to anything. GitHub reports the licence for this repository as a custom one that it cannot classify, and the root holds a LICENSE.md file, which is the authoritative text. The file extension and the presence of a separate licence document in a package with a CHANGELOG and CONTRIBUTING guide are the conventions of a permissive open source project, but the classification on the file's own says you should read it rather than assume.
Put together, Luxor is a well-organised, well-documented, narrowly scoped package with a clear set of successors named in its own README. That combination is unusual and useful: the documentation tells you what the tool is for and where its edges are, which is more than most graphics packages offer. Whether the edge is where your task sits is the question a quick script and a look at the gallery will answer.
Editorial conclusion
Luxor fits a Julia user who wants to draw a diagram, a poster or a simple animation from a script and would rather not learn the full Cairo interface, and it fits as a teaching surface for 2D graphics. It is the wrong choice for interactive work, for elaborate animation, or for the 2D and 3D plotting that Makie covers, since the README itself routes you to Makie, Javis.jl and Pluto.jl for those. Before adopting, read LICENSE.md, since GitHub reports a custom licence that it cannot classify, and pin the version you test, because the 4.x line was still moving with v4.5.0 published on 2026-04-09 and the last push on 2026-08-19.
Frequently asked questions
What is Luxor.jl and what is it used for?
It is a Julia package for drawing simple static 2D vector graphics, providing basic drawing functions and utilities for shapes, polygons, clipping masks, PNG and SVG images, turtle graphics and simple animations. The drawing is procedural and the result is saved to a PDF, PNG, SVG or EPS file.
How is Luxor different from Cairo.jl?
Luxor is built on the Cairo bindings and aims to be easier to use than plain Cairo.jl, with shorter names, fewer underscores, default contexts and simplified functions. The README says that for more complex and sophisticated graphics in 2D and 3D, Makie.jl is the better choice.
Which tools should I use instead of Luxor for animation or interactivity?
The README points to Javis.jl and Makie for complex or elaborate animations, and to Pluto.jl and Makie for interactivity, noting that Luxor is not interactive. It also points to Makie for sophisticated 2D and 3D graphics generally.
Where are the Luxor tutorials and how do I tell the docs versions apart?
Tutorials are in the Luxor Manual on the JuliaGraphics GitHub Pages site, and the README adds a YouTube channel and the author's blog. The stable documentation describes the current release, while the development documentation contains changes still in the master branch that may change before the next release.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/juliagraphics-luxor-jl)Was this useful?