eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

Theming system

Open StarfallProjects opened this issue 4 years ago • 15 comments

I appreciate this is a non-trivial feature suggestion. I don't think it's been suggested yet (search for "theme" didn't find anything) so logging it:

It would be great to have a theme system (as far as I can see this doesn't exist at present?) This would allow people to build reusable and extendable themes, which can be kept in sync (i.e. updates to the theme can be easily received by all theme users)

Broad outline:

  • Themes in a separate directory, named in the config file
  • Either themes are npm packages, or themes can be added as a git submodule.
  • Themes can be extended by CSS and JS in the normal assets directory
  • Themes can be partially overwritten by placing a file of the same name in the layouts directory (e.g. to overwrite the theme's footer.njk layout, you would place a footer.njk file in your layouts directory)

For themes as packages: MkDocs does this - themes can be pip packages. More details in the Mkdocs docs and the general concept is explained nicely in material theme docs. I believe Jekyll also takes this approach (themes are gems)

For themes as git submodules: Hugo does this. Forestry article

Pros and cons to both: the git submodules approach requires theme users to use git (or alternatively just copy the theme and lose the benefit of updates) But the package approach makes building themes a bit trickier: instead of basically building a site and sticking it on GitHub, theme builders would need to create an npm package.

StarfallProjects avatar Feb 12 '20 18:02 StarfallProjects

I did something like this loading-via-config idea for my *.11.js theme (named Lloyd) on my personal site, only I haven’t abstracted it out to a submodule (yet?).

reubenlillie avatar Feb 13 '20 03:02 reubenlillie

@reubenlillie will have a proper look tomorrow (on mobile at present) but: could someone else take your theme, add it their own site, keep it synced for any updates you make, and overwrite parts of it? If so then awesome - and how? :p

StarfallProjects avatar Feb 13 '20 20:02 StarfallProjects

@StarfallProjects, well, that actually sounds like the perfect use case for a submodule. My current theme is modeled a bit too closely with my own content for the conversion to be a quick process. But I am working on a starter repo that I can abstract into a separate theme repository. How's that sound?

reubenlillie avatar Feb 14 '20 00:02 reubenlillie

That would be cool. I'm curious how the overwriting would work? (I realise git submodules handles the rest of it)

StarfallProjects avatar Feb 14 '20 13:02 StarfallProjects

I like the idea of node modules. You can still publish them to a git repo, and just tag the repo with the version number. Installing and updating is just

npm install git+https://repo.url/here.git

It might be cool to make the .eleventy.js config do something like the following:

dir: {
  input: "src",
  output: "public",
  includes: ["_includes", "../node_modules/11ty-theme/_includes"],
  layouts: ["_layouts", "../node_modules/11ty-theme/_layouts"]
}

ethancalvo avatar Apr 07 '20 17:04 ethancalvo

Enter npm link ;-)

Ryuno-Ki avatar Apr 07 '20 18:04 Ryuno-Ki

How would it work for customising/overwriting?

For example, in MkDocs, you can create a file in your layout's folder with the same name as the file in the theme folder, and this overrides it, allowing you to customise bits of the theme (without modifying the theme itself) It is also possible to configure themes from the config file (things like colours). Similarly in Hugo I believe, you can add settings to the config file that the theme accesses.

StarfallProjects avatar Apr 08 '20 10:04 StarfallProjects

@StarfallProjects Yeah, exactly it should look in order. So in the example of the .eleventy.js file above, elleventy should first look in the _includes folder for a specified include, if not found there, look in the next directory.

node-sass does something similar, you can specify include-paths that tell it where to start looking for @import files.

Also Jekyll themes work by specifying the theme in the _config.yml file, and if jekyll can't find an include or _sass file in the immediate project, it goes to the theme to find the file.

ethancalvo avatar Apr 08 '20 16:04 ethancalvo

You might be able to hack it with the current system by creating a _temp directory, copy the contents of an eleventy theme in node_modules into it, and then copy the contents of _includes into the _temp file.

cp -r node_modules/11ty-theme/_includes/ _temp
cp -r _includes/ _temp

Then set up your .eleventy.js file as follows:

dir: {
  includes: "_temp"
}

and then add _includes/ to your .eleventyignore file.

During development you may want to set up a watch that just keeps copying changes to _includes into _temp

ethancalvo avatar Apr 08 '20 16:04 ethancalvo

I'm a fan of this idea too. I've deployed a starter with the beginnings of this working (see https://github.com/jacebenson/jace-ty/)

https://github.com/jacebenson/jace-ty/#theme-files-take-a-backseat-to-local-files-meaning goes over it briefly but, I'll put that text here too

When you use this starter you'll notice most the template files are in src/theme/jace-ty/. This is on purpose. If you make a file in src/layouts/ with the same name as a file in src/theme/jace-ty/, you're layouts file is used. If you want to revert to this theme, rename or delete your file.

How does this work? Well, in site.js you define a theme near the top, that builds the proper path for the starter njk files. If you want a new theme, you can create a sibling folder to jace-ty. In site.js I've added a function to look at what file exists based on a simple path. If /layouts/file.njk exists, return that, otherwise, return the theme file.

The problem I have with this is the top level collection *.md file. Look at ./src/post/post.md. There it's hardcoded to jace-ty theme, you can change that but I've not figured out how to do that part.

jacebenson avatar Jan 13 '21 08:01 jacebenson

@jacebenson On a side note: Is your site.js related to https://sitejs.org/ in any way?

Ryuno-Ki avatar Jan 18 '21 19:01 Ryuno-Ki

@Ryuno-Ki no

jacebenson avatar Jan 19 '21 06:01 jacebenson

My two thoughts: (1) After reading this thread I have one fear: A theme system usually goes with a template hierarchy. Those are often achieved with implicit overrides: naming conventions, domain specific languages (TYPO3, Neos) etc. At the moment 11ty has minimal black box characteristics. I prefer that even over SSGs like Hugo.

(2) 11ty has no limits on your site and data structure. It isn't focused on blogging or a specific idea of a site. It could output something entirely different than HTML! If we agree that this is a good feature then what good is a theme feature? I mean you could just copy a starter repo and adjust it to your liking. If there are updates to the starter (and you customized your site even a little) then you always need to check the changes and merge them by hand. If you don't customize anything then you can simply apply a patch (11ty file in root and all template files in a folder).

Maybe I don't understand you problem deeply enough. Maybe I come from a totally different background. (All my sites are unique and share maybe some helpers that are copied.) Maybe the problem isn't so relevant (7 upvotes in 1.5 years.)

One way to proceed could be the development of a special plugin that allows for certain theme like behavior. Then it would be completely optional (satisfying my fear) and there could be even several implementations of them (solving my second thought).

maxstoyanov avatar Aug 08 '21 16:08 maxstoyanov

It could output something entirely different than HTML!

I actually do that with sitemap.xml.

I'm quite sure, @zachleat will go the plugin route here. For that, exposing hooks could be something we need to think of.

Ryuno-Ki avatar Aug 08 '21 16:08 Ryuno-Ki

@maxstoyanov I think the idea is that in many cases, the updates in the templates (things like adapting to new dependencies, improvements to base structure, new functions) and the customisations applied by users (theme tweaking, content addition) are largely independent. Bumping a theme version in package.json and fixing a few breakages is a whole different beast than pulling dozens of commits and wrangling divergent git histories.

LoicGrobol avatar Aug 23 '22 14:08 LoicGrobol