Nitropage v0.59

One small step for semver, one giant leap for website editing. Introducing SolidStart v1, S3 file storage, Markdown support, focal point image cropping, editor zoom, page load optimizations and a lot more.

Katja Lutz

Web Developer

Announcements
19.08.2024

Sorry about that, you can read about the reasons why I skipped making a trailer this time, in the Funding-Section.

Five months ago, after the official announcement blog post, I planned to work on several Nitropage-based websites and get a realistic feeling of the strengths and weaknesses of the editor in different production setups, while waiting for the ongoing development of SolidStart - the underlying system.

To my surprise SolidStart released its major version already, just two months after my announcement. From that moment on I knew that I had to get back to work on Nitropage and upgrade all internal systems from SolidStart v0.3.10 to v1.0. What I am presenting to you today is the culmination of all the changes that happened since that point.

This is more than just an upgrade of pretty much all internal systems, this includes new essential features for users and developers alike and marks a very important step towards v1.0 of Nitropage. Meanwhile the starter kit has grown to a whooping 36 built-in blueprints!

To give you a list of the most noteworthy hightlights:

Nitropage v0.59 isn't released yet, but you can already try it out with the following command, which will guide you through the whole setup of a new project:

pnpm create nitropage@latest

Feedback & Release date

The new version hasn't been released yet, giving you the opportunity to try it out first. If you compare it to the currently shipped v0.58.1, you will find that almost no stone has left unturned. For active users of the old version this also means that they have to manually migrate their projects and turn some stones by hand, but don't worry: this site already runs the new version and the migration took me only about 15 minutes.

You can send me feedback over the #nitropage Discord channel on the Solid server or via my other contact options outlined here. Depending on the amount and significance of your feedbacks, v0.59 will be released in about two weeks, together with a short migration guide.

Funding

The funding situation doesn't look as bright as the new version. Making open source software of this size sustainable feels like a fight against the whole humanity some days. If you are a developer you probably already know what I am talking about. The truth is that I invested most of my own money to bring this project to life, because I believe that having a free, fully-featured and open source website builder would help humanity tremendously. But so far I didn't truly succeed in sharing this idea with other people. Most people haven't really heard of Nitropage to begin with and those who did are still waiting for others to use it first, nobody likes taking the initial risk. It's a vicious cycle that probably only would end with a miracle or with questionable marketing tactics such as fake likes and followers. As a single human with a relentless illness (Phantosmia) I can only do so much to keep this project alive and I absolutely need you. If you like the philosophy behind this project and you have an interest to keep it alive, then I plead you to:

  • Like it - Honestly, the current like count of 11 is insulting for a project with over 1000 commits.
    1 of these likes is from my mom. Be better than my mom.
  • Subscribe to the newsletter - You won't receive endless spam mails from this, promised!
  • Share the project on social media and talk about it with your friends.
  • Try it out and share your experience.
  • Share your NP-based websites on #nitropage so that we can create an amazing showcase and blow newcomers away.
  • Contribute new blueprints for the starter kit.
  • Donate - This software might be free, but I actually still need to pay my rent and eat food some days.
  • Become a sponsor.

I am wholeheartedly committed to this project, but I cannot continue working on it in a meaningful pace, if it stays broadly unknown in the following months. So I plead you: Let's make the miracle become a reality!

Joining the SolidStart team

It's already some weeks ago since this happened, but I am very proud to officially announce that I got to be part of the awesome SolidStart contributors team! This voluntary engagement allows me to discuss and support the development of SolidStart and Vinxi in a more effective, direct way and to share the experience that I am getting as a major user of the framework.

Additions for users

With the administrative topics out of the way, let's now take a deeper look at the new features and changes of Nitropage v0.59. Even though the main focus of this version was the internal migration to SolidStart v1, I just couldn't stop myself from also improving some user-facing parts.

New toolbar & responsive tools

The toolbar of the page editor got an overhauled look and is now positioned at the top. Gone are the days where the toolbar covers elements on the page. This new position also made space for a new page zoom option. Last but not least the resize handle for the page preview now covers the whole page height, which is powered by corvus fantastic Resizable primitive, made by Jasmin.

All of this allows you to work on your pages more efficiently and to simulate various viewing devices, even on small monitors.

P.S. the toolbar buttons now show the respective tool name, which should help new users a bit. Let me know what you think about this. Depending on future additions, the names might have to be removed again, to make space for other fancy tools.

Reworked element selection UI

Previously you could not see the blueprint name, when hovering over elements barely in the view, because the name was sticked to the top-border of the elements. With the new version this is no longer the case. You can now always see the name as it stays in the view, no matter the position of the scrollbar.

Focal point image cropping

With the complete redesign of the image optimization API I also wanted to improve the actual results that you get from it. Whats not a better way, than to finally get rid of the unprecise gravity setting and tackle proper focal point cropping?

Yes! With the new version you can set a specific focal point for each image and the automatic image cropping will make sure that the point stays visible, on all screen sizes!

Image settings

The focal point cropping feature asked for a place to configure image related settings. This place is a new dialog, opened via the Media Library. It also finally allows you to customize the Color and Description of your images.

The new image settings dialog

Youtube and Vimeo support

Internally the 'Video' Blueprint already supported Youtube and Vimeo videos for a while, but this feature was hidden from users. That's changing with the new URL field. You can see it in action on the trailer at the top of this announcement, which is hosted on Youtube - for some self-explaining reason...

New 'Markdown' blueprint

Powered by Marked, this useful new blueprint allows you not only to publish your beloved Markdown content, it can also be used to just embed some quick HTML on your site. The article you are reading at this very moment, has been written in Markdown :).

Got bigger plans and wanna write a full manual in Markdown? This blueprint automatically assigns id attributes for your headings, making it interoperable with the already existing 'Documentation' blueprint!

New 'Narrow' blueprint

It gives you access to a new narrow layout, as demonstrated by this article. Long form content is the perfect use case, as a narrow width can greatly improve readability. This replaces the Full Width option, previously existing redundantly in several other blueprints. Wanna make those narrow again? Just put them in a 'Narrow'! Now you can make all your narrowest fantasies come true.

New 'Embedded Video' blueprint

The work on this new blueprint was sponsored by Digitaler Aktivist. Originally implemented to embed videos from their self-hosted PeerTube instance, this blueprint can also be used to embed video iframes from many other sources, including Odysee and Rumble. This brings Nitropage one step closer in becoming the first choice for freedom-loving activists on the web!

Up for an example?

Here be developers

SolidStart v1.0, Nitro and Vinxi

Up to this point Nitropage was running on SolidStart v0.3.1. However v0.4 completely redesigned essential APIs, making it nearly impossible to upgrade Nitropage in a sensible way. If you wanna learn what had changed, look no further than the v0.4 announcement. Luckily the later release of SolidStart v1 signaled the stability of these new APIs and reassured that the time had come to bring Nitropage to new heights.

The migration of Nitropage to SolidStart v1.0 in numbers:

Amount Method Migrated to
52 server$ use server
6 createResource createAsync
15 createRouteData createAsync & cache
17 createRouteAction action
4 createServerAction$ action & use server

Deployment on steroids

But you are probably here to learn what advantages this migration brought to you, let's start with the biggest one: Nitropage now is built and served via Nitro and Vinxi, simplifying the deployment to hosting providers such as Netlify, Cloudflare and Vercel. We still need to figure out how simple this really is gonna be with Nitropage, but an important question with these providers is how and where to upload files. So I already proactively answered this question with the new S3 file storages.

Check out Nitros Deployment Guide to learn more about the new possibilities.

Now you might be wondering, what does Nitro have to do with Nitropage? Why the similar names? Is this a secret conspiracy? Is UnJS Nitro a product of Nitropage or vice-versa? To answer all of these questions from the get go:

Nitropage and Nitro are completely independent projects, neither of us have heard about the others projects, when we decided on the names. I'm still wondering to this day, if this is just a stunning coincidence, or a divine providence.

Page speed optimization

Solid Router added the ability to preload data on link hover, resulting in a noticeable speed improvement for desktop users, not only when visiting pages, but also in the dashboard.

The new version also leverages Solids stream render and Suspense. This is gonna be especially useful, when you wanna show data from slow external sources, just wrap your related blueprints in Suspense boundaries and fallback to some fancy loading spinners.

Last but not least, blueprints are now loaded in a more optimal way: Nitropage keeps a list of already loaded blueprints and only loads the missing ones, when navigating between pages.

Starter Kit

The migration asked for a complete revamp of the starter kit. A lot of files have changed in small ways. Upgrading your own projects to the new format is still relatively simple if you follow some key steps, that I will document in an upcoming migration guide.

Two notable changes are, that the sqlite database file and local file uploads are moved to a centralized .data folder and that the prisma database schema is using the new prismaSchemaFolder feature.

Refactored '@npio' packages

Contributing to a large project like Nitropage can feel very daunting. In an attempt to simplify the onboarding process for new contributors and to reduce the cognitive load, the nitropage npm package has been split up into several packages:

  • @npio/cli: Command-line tools for schema updates, user management and blueprint scaffolding
  • @npio/filesystem: Driver-agnostic filesystem layer
  • @npio/internals: Internal functionality used across the whole project
  • @npio/server: Backend related API for end-users
  • nitropage: Frontend and the pieces to glue everything together

Global server configuration

v0.59 comes with a new convinient place for all server related configurations. The same configuration is also consumed by the command-line utilities, enabling features like the CLI based user management. If you have worked with Vites config in the past, you should feel right at home with this:

export default defineServerConfig(() => {
  return {
    auth: {
      password: process.env["NP_AUTH_IRON_PASSWORD"]!,
      cookie: {
        maxAge: parseInt(process.env["NP_AUTH_COOKIE_MAXAGE"] || "0"),
      },
    },
    image: {
      sizes: [320, 512, 640, 768, 1024, 1280, 1536],
      maxAge: 365 * 24 * 60 * 60,
    },
    filesystem: {
      defaultDriver: "local",
      drivers: {
        local: {
          publicPath: ".data/storage/public",
          privatePath: ".data/storage/private",
        },
      },
    },
  } satisfies ServerConfig;
});

For the full list of options, check out the default configuration included in the starter kit.

Reworked image optimization API

As mentioned in the "Road to v1.0" section from the announcement article, the image optimization sadly couldn't stay as it was, because of the completely redesigend server functions that came with the switch to Vinxi . But this complication also was a chance to greatly improve the usability of the API and I am really happy about the result I am presenting you today. So what has changed?

  • Available aspect-ratios and sizes are now globally configured, instead of per blueprint.
  • Optimization logic is moved from an internal server function to a middleware, allowing for cleaner, human-readable URLs.
  • JS-based helper APIs have been simplified drastically and are less essential because of the more accessible URL format.

Take a look at the new URL format:

Syntax:   /image/{imageId}.webp?s={size}&ar={aspectRatio}
Example:  /image/h7ynh730pys1ze97epz3x5yy.webp?s=320&ar=2/1

As you can see this makes it really easy to generate optimal image sizes on the fly. Even better the optimization also automatically crops the image along its configured focal point:

Original ?s=640&ar=1/1 ?s=320&ar=2/1
Hiking Katja Hiking Katja Hiking Katja

Responsive image helpers

Chances are you wanna optimize your images responsively for different screen sizes and device-pixel-ratios. Luckily Nitropages Image component accepts a sources array that can be generated with the new mediaSources helper.

P.S. The helper handles 1x and 2x DPR calculations implicitly - one less thing to worry about! 🎉

import {
  Image,
  mediaSources,
  useMedia,
} from "nitropage/data/media";

// Load the media records for the selected images
const images = useMedia(() => props.data.imageIds);

// From screens > 1024 the size should be 1280, with a 1:1 aspect ratio
// For smaller screens the size should be 512
<Image sources={mediaSources(images()[0], [
  { size: 1280, aspectRatio: "1/1", screen: 1024 },
  { size: 512 }
])} />

But let's take this one last step further: The media records include additional information such as an alt-description, a color and an optional base64 dataUrl which can be shown as a placeholder during loading. Manually mapping all of these to the Image component gets very pesky after some time, so you can use MediaContainer instead, which will take care of the mapping for you:

import {
  MediaContainer,
  useMedia,
} from "nitropage/data/media";

const images = useMedia(() => props.data.imageIds, {
  dataUrl: true,
});

<MediaContainer media={images()[0]} placeholder sources={[
  { size: 1280, aspectRatio: "1/1", screen: 1024 },
  { size: 512 }
]} />

S3 file storage

Many modern hosting providers drastically limit the size of uploaded files or disallow it completely. Nitropage recommends self hosting which completely avoids such limitations and gives you a lot more freedom. But you still might prefer that convenience of modern hosters and thats why I am happy to announce the support of S3 file storages!

Originally coming from Amazon, these storages allow you to efficiently store large amounts of files. These days there exist several competitors and even an open source solution MinIO, all compatible to the S3 architecture. To give you a few options:

When you've choosen your S3 provider, or launched a self-hosted MinIO, you can enter its access key and related information in the new global server configuration and Nitropage will take care of the rest. Newly uploaded files and optimized images will automatically land in the configured public bucket. Since such files are directly served from your bucket, make sure that it is configured with an anonymous download access policy.

Blueprint CSS without FOUCs

You can now freely import CSS files in your blueprint components and also take advantage of CSS modules 🥳!

Nitropage for performance reasons loads blueprint components lazily, which normally would result in dizzy flashes of unstyled content (FOUC). You probably have seen this on some other websites, the content jumps around during page load. I couldn't accept this reality and invented a package, properly server rendering CSS from lazy loaded components: Solid Lazy Plus. This is available as an independent package and therefore can be used in plain Solid projects.

Global page CSS

A fundamental goal of Nitropage is to give you, the developer, the freedom to choose how you wanna style your project. The starter kit comes with Tailwind, but you should not be locked into this choice. Thus v0.59 introduces a new PageRoot component, where you can fearlessly include global CSS rules (in most cases). Just make sure that you don't break the inline richtext editor (Quill), if you plan to use that one ;).

Built-in prose styles

Consistent typography is an integral aspect of every website. v0.59 simplifies this aspect with newly added "prose" styles, inspired by Tailwind Typography. You can access them via the Richtext component from nitropage, which is completely optional.

The 'Text', 'Heading' and 'Markdown' blueprints all share a coherent typography thanks to these styles. Currently they are set in stone, but a future goal is to offer several customization options via the editor.

Internal links work differently in the editor, then when visiting a real page: Clicking them in the editor doesn't open the related URL, preventing unexpected editor closures. Previously this trap has been achieved by rendering links and buttons as <span> elements. But this also meant that CSS rules targeting a and button could not work properly in the editor.

These traps are now completely reworked with Solid Routers useBeforeLeave and HTMLs beforeunload event, which should lead to less unexpected surprises when you are designing your snazzy hyperlinks.

Smaller HTML document size

A late addition to v0.59 that will make your sites even more efficient: Passive blueprints are no longer affected from the double data problem. The double data problem means that the result from server rendering a page has to include the needed data twice, in the form of HTML and in the form of JSON. You can read more about the problem in this detailed article by Ryan Carniato: "Why Efficient Hydration in JavaScript Frameworks is so Challenging".

The existence of passive blueprints (blueprints that are excluded from hydration) allows us to exclude data for these blueprints during server rendering and therefore decrease the HTML document size. The effect of this optimization is seen best on pages with a lot of static content, such as blog posts.

Results for nitropage.com:

Uncompressed Compressed
Original 297.1 KB 62.6 KB
Optimized 265.0 KB 55.2 KB

You found the end of this article, thank you for staying through the whole experience! If you liked what you saw you can try Nitropage v0.59 out with:

pnpm create nitropage@latest

I wanna thank all of the supporters of this project wholeheartedly, from my family, my friends, the anonymous crypto donators and bitcoin maxis, up to the inspiring and welcoming Solid community, this project wouldn't exist without you!

And a special thanks to Dave Di Biase for proof-reading this article and providing several improvement ideas!

Previous article

Announcements
04.03.2024

Announcing Nitropage

The concept behind Nitropage and the way forward.

READ MORE
Katja Lutz

Web Developer