PlanMe · Designers
The step-by-step process
Ten steps from an empty artboard to a delivered pack: document setup, tokens, day sheets, colour, fonts, export, file name and the checker. Work them in order — each one assumes the last.
Step 1. Set up the document
Draw at the exact paper proportion, one artboard per file. Set the canvas in millimetres and match the viewBox to those same numbers.
- 1Create a document with a single artboard at the size you need (table below).
- 2Set the document units to millimetres.
- 3Make sure there is exactly one artboard. A second one breaks the import.
- 4Keep bleed inside the canvas: the page is clipped to exactly that box.
| Paper | Size (mm) | viewBox |
|---|---|---|
| A4 | 210 × 297 | 0 0 210 297 |
| A5 | 148 × 210 | 0 0 148 210 |
| Letter | 215.9 × 279.4 | 0 0 215.9 279.4 |
<svg xmlns="http://www.w3.org/2000/svg"
width="210mm" height="297mm" viewBox="0 0 210 297"
preserveAspectRatio="xMidYMid meet">A4 and A5 share the same proportion (1:√2), so the A4 file is reused for A5 automatically. Only Letter needs its own drawing — two files per template, not three.
Step 2. Draw the layout
Draw it as a finished page for one specific month: a real grid, real headers, real rules. Only the text itself becomes a token in the next step.
For a month grid, draw 42 text elements in six rows of seven. Aligning them to the right weekday and blanking the leading cells is handled for you.
- 1Lay down the background, frames, rules and decoration.
- 2Create a separate text object for every place variable text will appear.
- 3Give each text object its final size, weight and alignment.
- 4Check the longest label in the manifest still fits.
Step 3. Put the tokens in
A token looks like [family.key] and goes in text content or in any attribute value. At render time each one is replaced with a real value.
- 1Replace the variable text with its token (reference further down this page).
- 2Type the token in one go; do not edit it in the middle.
- 3Select the whole text object and style it all at once, never part of it.
- 4Never convert the text to outlines: PlanMe has to substitute into it.
<rect fill="[color.primary]"/>
<text style="fill:[color.text];font-family:[font.heading]">
[month.name] [year]
</text>An unknown token is replaced with nothing — silently. A typo like [colour.primary] simply deletes the text. This is why step 9 matters.
Step 4. Day sheets — the one tricky part
A week is packed onto a whole number of sheets by giving the weekend half the height of a normal day. Hence five day templates.
The important bit: a sheet numbers its days FROM ITSELF, not from the start of the week. [sheet.date.0] is whichever day that sheet opens on. That is why one day-2-up drawing serves both Mon+Tue and Wed+Thu.
- 1Use [sheet.*] on day sheets — never [week.day.N].
- 2Number the slots from zero, top to bottom.
- 3In day-1-plus-2 and day-2-plus-2 the last two days are the weekend; give them about half the height of the others.
- 4You may draw more slots than needed: the extras blank themselves.
| Template | Days per sheet | Sheets per week |
|---|---|---|
| day-1-up | 1 | Mon 7 · Sun 7 |
| day-2-up | 2 | Mon 2 · Sun 3 |
| day-3-up | 3 | Mon 1 · Sun 2 |
| day-1-plus-2 | 3 | Mon 1 · Sun — |
| day-2-plus-2 | 4 | Mon 1 · Sun — |
| day-1-plus-notes | 1 | Mon — · Sun 1 |
[week.day.N] on a day sheet shows the right date only on the week's first sheet, then someone else's numbers. It is the most common mistake in this system.
Step 5. Colour
Two workable approaches — pick per pack.
- 1Simplest: copy the pack's palette hex values from the manifest (stylePacks[].palette) and draw with them directly. For a mono pack this is nearly always right — it is only black, grey and white.
- 2If one drawing must serve several packs: after exporting, open the .svg in a text editor and swap each hex for the matching [color.*]. You cannot type a token into Illustrator's colour picker.
On interior pages avoid light greys thinner than 0.5 pt — a home laser printer simply will not put them on paper.
Step 6. Fonts
System stacks work with no effort. If the pack uses its own typeface, put the .woff2 in a fonts/ folder and declare it in pack.json.
- 1Put the font in fonts/ next to your SVGs.
- 2Add it to the fonts array in pack.json.
- 3Reference it in the SVG by ordinary font-family, or via [font.heading].
- 4Check the licence allows web and PDF embedding.
{
"slug": "mono-serif",
"name": "Serif",
"fonts": [
{ "family": "MyDisplay", "weight": 700, "file": "MyDisplay.woff2" }
]
}Step 7. Export from Illustrator
The export settings matter more than they look: half of all artwork problems start here.
- 1File → Export → Export As… → SVG.
- 2Styling: Presentation Attributes. NOT Internal CSS, or colours will not be substituted.
- 3Font: SVG (never Convert to outlines).
- 4Images: Embed.
- 5Object IDs: Layer Names. Decimal: 2.
- 6Minify off. Responsive off.
Internal CSS shows up as .st0-style classes in the file. The checker in step 9 catches it immediately.
Step 8. Name the file
The file name is an address, not a description. It is how PlanMe knows which page you drew and at what size.
- 1The shape is <template-key>.<paper>.svg — for example month-calendar.A4.svg.
- 2Take the key from the list at the bottom of this page, character for character.
- 3The paper is exactly A4, A5 or Letter, capitalised.
A file with a mistyped key imports silently and never renders. It is a known sharp edge — which is what the checker is for.
Step 9. Check it before sending
The checker finds everything the system would otherwise swallow: unknown tokens, Internal CSS, outlined type, tokens split across tspans, a wrongly proportioned artboard.
- 1Put the files in storage/assets/<slug>/.
- 2Run the checker (command below).
- 3Fix everything it reports as an error. Warnings are your call.
- 4Send one finished file early rather than twenty at the end.
npm run assets:checkStep 10. Hand over the pack
One folder per pack. pack.json is only needed if the pack ships its own fonts — otherwise we add it.
<pack-slug>/
pack.json
cover.A4.svg
cover.Letter.svg
month-calendar.A4.svg
...
fonts/
MyDisplay.woff2The folder slug must match the pack slug from the style packs section exactly.
Token reference
Three rules worth knowing first: tokens cannot nest; a token cannot contain brackets; resolved values are XML-escaped, so font stacks come back with ' where they had apostrophes — that is correct and renders fine.
| Token | What it gives |
|---|---|
| [color.primary] … [color.line] | The pack's palette: primary, accent, background, surface, text, muted, line. |
| [font.heading] / [font.body] | The pack's font stacks — heading and body. |
| [themeName] / [motif] | The pack's display name and its short decorative motif. |
| [title] / [subtitle] / [heading] | Planner title, subtitle and page heading, from the user's settings. |
| [year] | The planner year. |
| [label.*] | Static captions, translated into the planner's language. Full list below. |
| [month.name] / [month.short] | The page's month name, full and abbreviated. |
| [month.year] | The year the month belongs to — a range can span two. |
| [month.days] | Number of days in the page's month. |
| [weekday.long.N] / [weekday.short.N] | Weekday headers 0–6, rotated to the user's start of week. |
| [grid.0] … [grid.41] | The month grid, six rows of seven. Cells before the 1st and after the last day are empty. |
| [monthday.1] … [monthday.31] | The day number if it exists this month, else empty: a 31-slot row self-trims in February. |
| [day.1] … [day.31] | Literal digits 1–31. NOT calendar-aware — fixed column headers only. |
| [week.day.N] / [week.date.N] / [week.iso.N] | Day N (0–6) of the page's week: the number, the full date, the ISO date. |
| [week.range] / [week.number] / [week.month] | Week headers: the range, the ISO week number, the first day's month. |
| [sheet.date.N] / [sheet.day.N] / [sheet.iso.N] | Day N of THIS sheet — numbered from the sheet, not the week. Slots past the sheet's capacity are empty. |
| [sheet.weekday.long.N] / [sheet.weekday.short.N] | Weekday name for day N of this sheet. |
| [sheet.range] / [sheet.count] | The sheet's date range and how many days it holds. |
| [date] / [date.day] / [date.weekday] / [date.iso] | The sheet's first day: full date, day number, weekday, ISO. |
| [config.<key>] | Any value from the page's config; empty when absent. |
Common mistakes
- Type converted to outlines. PlanMe has nothing to substitute into — the page keeps your placeholder text forever.
- A token split across tspans. Happens when you edit text mid-string or style part of a line. [month.name] becomes [mon + th.name] and never matches.
- Exported with Internal CSS. Colours stop responding to the pack.
- [week.day.N] on a day sheet instead of [sheet.*]. The dates are right only on the week's first sheet.
- A typo in a token. The value disappears with no warning at all.
- Two artboards in one file. Only the first is imported.
- A hardcoded year or month name. The file works for exactly one year.
Every [label.*] token
These are the static captions PlanMe translates for you. Write [label.notes], not “Notes” — otherwise the page stays English inside a Ukrainian planner.
| Key | Token |
|---|---|
| amount | [label.amount] |
| atAGlance | [label.atAGlance] |
| bed | [label.bed] |
| budget | [label.budget] |
| career | [label.career] |
| dailyPlan | [label.dailyPlan] |
| dailyTracker | [label.dailyTracker] |
| date | [label.date] |
| description | [label.description] |
| edition | [label.edition] |
| expenses | [label.expenses] |
| finance | [label.finance] |
| freeReflection | [label.freeReflection] |
| goals | [label.goals] |
| gratefulFor | [label.gratefulFor] |
| gratitude | [label.gratitude] |
| habitTracker | [label.habitTracker] |
| health | [label.health] |
| healthWellness | [label.healthWellness] |
| hours | [label.hours] |
| income | [label.income] |
| intentions | [label.intentions] |
| meals | [label.meals] |
| moodEnergy | [label.moodEnergy] |
| notes | [label.notes] |
| personal | [label.personal] |
| quality | [label.quality] |
| reflectAppreciate | [label.reflectAppreciate] |
| savings | [label.savings] |
| schedule | [label.schedule] |
| sleep | [label.sleep] |
| smallWin | [label.smallWin] |
| thisYearIWill | [label.thisYearIWill] |
| todo | [label.todo] |
| top3 | [label.top3] |
| topPriorities | [label.topPriorities] |
| transactions | [label.transactions] |
| wake | [label.wake] |
| water | [label.water] |
| waterIntake | [label.waterIntake] |
| watermark | [label.watermark] |
| weekNotes | [label.weekNotes] |
| weekSpread | [label.weekSpread] |
| weeklyPlan | [label.weeklyPlan] |
| yearOverview | [label.yearOverview] |
Page template keys
The first part of the file name. A wrong key imports silently and never renders.
coveryear-overviewmonth-calendarweek-one-pageday-1-upday-2-upday-3-upday-1-plus-2day-2-plus-2day-1-plus-noteshabit-trackerhealth-trackernotes-linedgoalsbudgetgratitude