Technical Documentation — Goodnotes Dynamic Template .gntemplate

TL;DR
What is .gntemplate?
Create your first .gntemplate file
Add more themes
Support user-defined themes
Generate more lines and columns instead of just stretching them
Support Full-Page Typing
Verify that .gntemplate is created correctly
  1. TL;DR

    UserFacingTemplateName.gntemplate
    / template.svg // the only required file
    / themes
    / 1 - User FacingThemeNameX
    /red-light.css
    / 2 - User Facing ThemeNameY
    /blue-light.css
    / 3 - User Facing Theme NameZ
    / blue-dark.css
    1. Save your template artwork as template.svg
    2. Open template.svg with any text editor (e.g. TextEdit on macOS) to explicitly set preserveAspectRatio for the root <svg> element
    3. Extract CSS for each theme (if you want to support 2+ themes)
    4. Put CSS-based themes under the themes folder where each folder has a user facing theme name
    5. Compress template.svg and the themes folder to get a ZIP archive
    6. Rename Archive.zip to a file with the name you want users to see and .gntemplate extension
    7. Import the .gntemplate into Goodnotes Template Library to see how it works end-to-end
  2. What is .gntemplate?

    .gntemplate is a strictly-structured SVG-based file format which allows to define layout and look of a page template with one or more themes. We introduced it to simplify the creation process compared to the old PDF-based approach where each size and theme variation was backed by a standalone PDF file. It also allows users to choose arbitrary page size (not only fixed presets like A4/A3/...) while it's still the creator who controls how the template adapts to changes of aspect ratio.

    .gntemplate already allows creators to support some features that were not possible in the past (e.g. user-defined themes and Full-Page Typing) and we are open to new ideas based on your feedback.

  3. Create your first .gntemplate file

  4. Add more themes

    You can support 2+ color variations of the same templates by adding each theme into a folder with its user facing name under the themes folder. It’s up to you to define the themes order by using such format:

    1 - Navy
    2 - Ambrosia
    3 - Brick
    ...

    We will automatically exclude this ordering prefixes from UI so for the example above users will only see Navy, Ambrosia, Brick as options.

    Each theme folder should contain a single CSS file called <color>-<mode>.css (e.g. red-light.css) where the color corresponds to one of the options we support and use in both Marketplace (so users can filter by color and find your template) and Template Library (circle dots as visual hints):

    yellow
    white
    dark
    grey
    brown
    neutral
    red
    orange
    green
    blue
    navy
    purple
    pink
    clear
    multicolor

    The -light/-dark suffix is used for typing features so we know whether it’s better to use black/white text overlays by default.Example: Bright.gntemplate

  5. Support user-defined themes

    Let users override some of your template colors by using our special names in your SVG and CSS:

    gnBackgroundFill
    gnBackgroundStroke
    gnForegroundFill
    gnForegroundStroke
    gnAccentFill
    gnAccentStroke

    Here is how you can do it:

    1. Add class=“gnBackgroundFill” (or any other supported name) to some existing element(s) in template.svg  that you want to make customisable
    2. Explicitly set values for all of the customised classes in the CSS files - we will use your CSS as the source of the truth

    Example:

    template.svg:

    <svg
      xmlns="http://www.w3.org/2000/svg"
      width="100%" height="100%" preserveAspectRatio="none"
    >
      <rect class="gnBackgroundFill" width="100%" height="100%" fill="#51D7F5"/>
      <line class="gnAccentStroke" x1="85%" x2="85%" y1="0" y2="100%" stroke-width="5%" stroke="#0A9DBF"/>
    </svg>

    pink-light.css:

    .gnBackgroundFill {
      fill: #662625;
    }
    
    .gnAccentStroke {
      stroke: #FFFFFF;
    }
    
  6. Generate more lines and columns instead of just stretching them

    In contrast to notebook covers, when designing paper templates you usually expect to see more lines as the page grows without increasing spacing between them. This is where SVG <pattern> is the most suitable tool. Some editors have first-class support of this feature (e.g. Adobe Illustrator) while other don’t. Consider defining <pattern> directly in SVG file using a text/code editor for most flexibility. Often you would want to use it together with preserveAspectRatio="none" so the content is properly adapted for any page size.Example:

    <svg
    xmlns="http://www.w3.org/2000/svg"
    width="595" height="842" preserveAspectRatio="none"
    >
    <defs>
    <pattern id="pattern" width="100%" height="17.5" patternUnits="userSpaceOnUse">
    <rect class="gnForegroundFill" y="17" width="100%" height="0.5" fill="#D0D2D3"/>
    </pattern>
    </defs>

    <rect class="gnBackgroundFill" width="100%" height="100%" fill="#F8F7E9"/>
    <rect y="10%" width="100%" height="80%" fill="url(#pattern)"/>
    </svg>
  7. Support Full-Page Typing

    Another opt-in feature is making your template compatible with Full-Page Typing experience in Goodnotes. You can either set FPT rules explicitly or get the default insets if your page template doesn’t have visual alignment (e.g. lines).

    Example 1. The same <rect> to fill it with <pattern> and use for typing:

    <rect id="gn-typing-1" data-line-height="17" data-line-spacing="0.5" x="5%" y="10%" width="90%" height="80%" fill="url(#pattern)"/>

    Example 2. Different rects with invisible typing <rect>:

    <rect y="10%" width="100%" height="80%" fill="url(#pattern)"/>
    <rect id="gn-typing-1" data-line-height="36" data-vertical-alignment="center" data-header-style="paragraph" x="5%" y="10%" width="90%" height="80%" fill="none"/>
    

    Related parameters:

    data-line-height // e.g. 15.5
    data-line-spacing // e.g. 0.5; default is 0
    data-vertical-alignment // "bottom"/"center"; default is "bottom"
    data-background-style // "light"/"dark"; inferred if not explicitly set
    data-header-style // "heading1"/"paragraph"; default is "heading1"

    Note: Dimensions for attributes like data-line-height are defined in points, where 72 points equal to 1 inch.



  8. Verify that .gntemplate is created correctly

    1. Compress template.svg and the themes folder to get a ZIP archive
    2. Rename Archive.zip to a file with the name you want users to see and .gntemplate extension
    3. Import the .gntemplate into Goodnotes Template Library to see how it works end-to-end