Open-source project
abetusk/neatocal avatar
abetusk/neatocal

NeatoCal: a year on one printable page, configured entirely by URL

A single page printable calendar

880 stars62 forksJavaScriptMIT

At a glance

What is it?
NeatoCal renders a full year as a single printable page from a plain web page, with the year, month range, layout, weekday and month labels, moon phases and colours all set through URL parameters rather than a settings file. It is a JavaScript port of Neatnik's Calendar with no external dependencies and no build step.
Who is it for?
Use NeatoCal when you want a wall calendar you can print or render as an image without installing anything, since every option is a URL parameter and the whole tool is a handful of local files with no external dependencies. Do not expect it to be a calendar application, because it draws a year grid and nothing else: there are no events, no subscription format beyond the ICS overlay and no accounts.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 72 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A year drawn as a grid, then printed

NeatoCal puts the full year on a single page. The idea is a wall calendar rather than a desktop calendar: twelve months laid out together so that a year is visible at a glance, and the output is designed to be printed. The project is a JavaScript port of Neatnik's Calendar, with added parameters, and it is described as dependency free with all files local. That last point is the design constraint that shapes everything else. There is no bundler, no package manager step and no network call at runtime, so the calendar is a directory of HTML, JavaScript and CSS files that you can copy onto a web server, a USB stick behind a local file server, or a small home lab box. The repository root holds index.html, neatocal.html, neatocal.js, a css directory, an example directory with data files and ICS examples, an img directory for the screenshots, and a test directory.

Four layouts decide the shape of the page

The layout parameter takes four values and it is the single biggest visual decision you make. The default layout is the standard year grid. The aligned-weekdays layout lines the weekdays up so every column of dates shares the same weekday, which is the version to use if the calendar is going to be annotated and read column by column. The hallon-almanackan layout comes from the Swedish almanac tradition and stacks the months differently. The weekly-grid layout is the fourth option, a grid built around weeks rather than months. Each layout has a screenshot in the img directory and a linked example URL. The start_day parameter, which starts the week on a day other than Monday, is documented as valid only with the aligned-weekdays layout, so that constraint is worth reading before you experiment.

Month ranges turn the year into an academic calendar

Three parameters control the time span rather than its appearance. The year parameter changes the year, defaulting to the current one. The start_month parameter sets the first month, zero indexed so that 0 is January and 1 is February. The n_month parameter sets how many months to show, with a default of 12. Those three combine into the presets the README suggests, and any of them can be typed straight into the address bar.

bash
https://abetusk.github.io/neatocal?year=2030
https://abetusk.github.io/neatocal?start_month=7
https://abetusk.github.io/neatocal?n_month=6

An academic calendar, for instance, is start_month=7, which begins in September and runs through to August of the following year, and two half page calendars of six months each are start_month=0 with n_month=6 and start_month=6 with n_month=6. The n_month value is what makes the calendar useful for a single semester or a quarter, which is a case the twelve-month default cannot serve.

Labels are language aware and overridable field by field

The language parameter sets the language for month and day codes, but it is only a starting point, because the values are overridden if month_code or weekday_code is specified. The weekday_code parameter takes a comma separated list of weekday codes, defaulting to Su,M,T,W,R,F,Sa, and elements can be left blank if no code is wanted for that day. The month_code parameter does the same for months, defaulting to Jan through Dec, and elements can be blank there as well. On top of that, weekday_format accepts long, short or narrow for the representation of weekdays, and month_format accepts numeric, 2-digit, long, short or narrow for months, with both requiring a language to be specified. The combination of a language setting and per-field overrides is what makes a custom abbreviation set possible without touching the code, and the blank element rule is the detail that lets you suppress a column rather than rename it.

Moon phases with three separate knobs

The show_moon_phase parameter, defaulting to false, turns on lunar phase display. Three further parameters shape it. The moon_phase_style chooses how a phase is drawn, with css as the default, plus symbol and name as alternatives. The moon_phase_position places the phase below the date by default or inline with it. The moon_phase_display decides when phases appear, with changes as the default, meaning only on the days a phase actually transitions, and all meaning every single day. The example directory contains a moon_phase.json file, which suggests the phase calculation or its data is supplied through the same JSON mechanism as the rest of the calendar rather than being computed from scratch in the browser. Given the precision required to place a phase on the right day, that is the likely design.

Styling without a stylesheet

Beyond the named parameters there is a general styling mechanism. Parameters for weekday text, weekend text, month text, week number, day in month and weekend day in month can each be styled for font size, font weight, foreground colour and background colour. These are given as URL parameters using the pattern [VARIABLE]_[CSSTYPE], where the variable is one of year, month, weekday, weekend, week, date or weekend_date, and the CSS type maps to a CSS property: font_size to fontSize, font_weight to fontWeight, foreground_color to color, background_color to background. The example given is a weekend font size of 1.4vmin, and using viewport units is how a single calendar scales across a wall display and a sheet of A4 without a media query. Two related parameters handle colour directly: highlight_color for the weekend highlight, defaulting to eee, and today_highlight_color for the current day. The font_family parameter changes the typeface, with Oswald as the default, which is a web font the project loads locally.

Data files, the ICS overlay and the help screen

Three parameters extend the calendar beyond the grid. The data parameter sets the location of a JSON data file, and the example directory shows the shapes you might point it at: data.json, data_error.json, data_weeknumber.json, sched.json and moon_phase.json. The data_error.json file in particular suggests the project expects malformed input to be handled rather than ignored, which is worth checking before you wire up your own. The ics parameter shows an ICS drag-and-drop prompt overlay on load, and the example directory carries example.ics and example_rrule.ics, one plain and one with a recurrence rule, so the calendar can hand itself to a real calendar application. The help parameter shows a help screen, which is a sensible fallback for a tool whose entire interface is a URL: someone who lands on the page can be told what to do. The weekday_code default of Sa rather than Sat also hints at a European convention in the defaults.

Where NeatoCal is the wrong tool

Four limits apply. It draws a year, not a schedule: there is no agenda, no events, no reminders, and the ICS support is a drag-and-drop handoff rather than a subscription. It has no interface to click, because every option lives in the URL, which is a feature for a generated poster and a barrier for a casual user, though the help parameter partly addresses that. It needs a data file for the richer features, so a fully static HTML file alone gives you the plain grid. And it is a single page project with no GitHub releases, so there is no version history to pin and no changelog to consult; the last push to the repository was on 2026-08-14, and any change you rely on is a commit rather than a release. The licence field on the repository says MIT, and the project credits Neatnik's Calendar as the design it was ported from.

Editorial conclusion

Use NeatoCal when you want a wall calendar you can print or render as an image without installing anything, since every option is a URL parameter and the whole tool is a handful of local files with no external dependencies. Do not expect it to be a calendar application, because it draws a year grid and nothing else: there are no events, no subscription format beyond the ICS overlay and no accounts. Verify first that the printing behaviour suits your printer, because the project ships a separate Printing-Issues.md page for exactly that, and that the data JSON you point the data parameter at has the fields your calendar expects, since the example directory includes a data_error.json alongside the working examples.

Frequently asked questions

What is NeatoCal and how do I get it?

It is a JavaScript port of Neatnik's Calendar that renders a full year on a single printable page. It is dependency free with all files local, so there is nothing to install: the repository holds index.html, neatocal.html, neatocal.js and a css directory that you serve yourself, and a live demo is hosted on GitHub Pages.

Which calendar layouts does NeatoCal offer?

The layout parameter accepts default, aligned-weekdays, hallon-almanackan and weekly-grid. The start_day parameter, which changes the first weekday, is documented as valid only with the aligned-weekdays layout.

How do I make an academic year calendar with NeatoCal?

Use the start_month parameter, which is zero indexed, together with n_month. The README gives an academic calendar running from September to August as start_month=7, and half page calendars as start_month=0 with n_month=6 and start_month=6 with n_month=6.

Can NeatoCal show moon phases?

Yes, with show_moon_phase, which defaults to false. The display is shaped by moon_phase_style for css, symbol or name, moon_phase_position for below or inline, and moon_phase_display for changes by default or all, and the example directory contains a moon_phase.json file.

How do I customise the text and colours in NeatoCal?

The weekday_code and month_code parameters take comma separated label lists whose elements can be blank, and the language, weekday_format and month_format parameters control the built-in labels. Colours and fonts come from highlight_color, today_highlight_color and font_family, and detailed styling uses [VARIABLE]_[CSSTYPE] parameters such as weekend_font_size.

Official sources

  1. abetusk/neatocal on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/abetusk-neatocal.svg)](https://hysenlabs.com/projects/abetusk-neatocal)

Was this useful?