Skip to content

feat: rewrite to Astro - #165

Open
DLakomy wants to merge 2 commits into
flix:masterfrom
DLakomy:dl/astro-rewrite
Open

feat: rewrite to Astro#165
DLakomy wants to merge 2 commits into
flix:masterfrom
DLakomy:dl/astro-rewrite

Conversation

@DLakomy

@DLakomy DLakomy commented Jul 4, 2026

Copy link
Copy Markdown

Fixes #117

Hello.

I've learned Astro yesterday and thought I might try rewriting your webpage to a static one. I've got nothing against JavaScript on your page, but saw an issue on GitHub.

What I optimized for:

  1. Similarity to React, so the current maintainers have no trouble switching. This is why I chose Astro.
  2. Limited refactors, so it doesn't take long to implement (it's difficult to merge updates from master during a full rewrite).
  3. 100% similarity, pixel for pixel, to make it easier to review. I've spent hours tweaking it and trying not to leave accidental changes (especially in the content, it's surprisingly easy to loose a paragraph...), but to be honest I'm not 100% sure I've got everything. The icons are slightly different on the documentation subpage. I guess it's a matter of fontawesome's version.
  4. Zero JavaScript at runtime (after running npm run build you can run find ./dist -name '*.js' and see no results).

Some notes:

  1. There is a TODO comment in src/components/InlineEditor.astro. It's not blocking this merge, just a suggestion for the future. I guess this would help make Flix more popular (which I hope will happen!).
  2. I've replaced the carousel (Visual Studio Code Support section on the home subpage) with a simple grid. I can try to make a pure CSS carousel, but maybe it should be removed and just point to the VSCode webpage. What do you think?

How to test:

  1. npm run build.
  2. Serve dist subdir. For example cd dist && python -m http.server 8000 and open http://localhost:8000/ in your browser. Actually, now you can even read that with curl :D
  3. There is a question in FAQ: "This site requires JavaScript" and similar. Shall I redact them, as no longer standing?

If you're interested in merging, I'm waiting for your feedback and can check again before merging, to make sure no text is lost.

@magnus-madsen

Copy link
Copy Markdown
Member

Thanks @DLakomy. This is an interesting experiment. I will have a look.

Can you sell me on Astro? I assume its a static site generator. But why this one specifically?

I will try it out locally... and report back.

@magnus-madsen

magnus-madsen commented Jul 7, 2026

Copy link
Copy Markdown
Member

A few more questions and comments:

  • How did you go about the refactor?
  • Are URLs preserved? We don't want to break links.
  • The code font is not the same or the same size?
  • Instead of bundling our own textmate grammar, perhaps we could use highlight.js?
  • Does the use of Astro mean that the website will work (mostly) without JavaScript?


---

<div><slot /></div>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does a file like this do?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a direct equivalent of the original:

function Answer({ children }) {
    return <div>{children}</div>;
}

In Astro it's not possible to write JSX in the frontmatter (the lines between ---), so AFAIK this is the only way to create a component. Source: withastro/roadmap#164

I wasn't sure whether to rewrite this (which I did) or to inline this div. I made a component to keep faq.astro similar to Faq.jsx, easier to review. We can keep it (it would make it easier to change how an Answer looks like in the future) or inline it, so nobody is wondering why it's here. I have got no strong opinion.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand. I think we should just inline components that are single <div>'s. Can we do that?

@DLakomy

DLakomy commented Jul 7, 2026

Copy link
Copy Markdown
Author

Can you sell me on Astro? I assume its a static site generator. But why this one specifically?

Sure. Some background: I'm not a frontend dev, so take what I say with a grain of salt (or a bucket of salt). I sometimes have to write a frontend, though, and in these cases I like solutions that are easy to learn and have a simple tooling. Since I know I won't be able to maintain this site long-term after this experiment, I wanted to make the codebase as approachable as possible for the existing team.

I chose Astro because:

  1. It's a bit similar to React (uses JSX), but optimized towards mainly static apps with islands (see https://docs.astro.build/en/concepts/islands/). I assumed it will make it easier for the current maintainers to switch to. It's also possible to rewrite from React to Astro gradually, but given the small size of the website I thought it's easier to just do it all at once and reduce dependencies. See: https://docs.astro.build/pl/guides/integrations-guide/react/. I think it would be theoretically possible to keep the page as is and it would render React on the server (so the client doesn't have to), but it would make the webpage dependent on two big dependencies with very little value.
  2. It allowed me to rewrite the page as is for now (unlike e.g. Hugo, which would involve significant changes).
  3. It leaves multiple good paths open for the future: adding or building a component library, switching to MDX, etc. These can all be adopted gradually. I think Rock the JVM uses this approach (MDX). It's good that all of these can be done gradually, not necessarily all at once.

What alternatives I've rejected:

  1. Hugo. I never used it, but I think it might be good for a static site; however, it would involve significant rewrite.
  2. htmx - Would enable partial updates without full page reloads, while keeping the page working without JS. But the site is already small and fast. It would also require a backend, which felt unnecessary here.
  3. Plain static HTML + CSS. And then I thought: „how do I synchronise the menu-bar thing between subpages”? Astro addresses exactly this problem in a very easy way (Layout.astro describes the common structure).

How did you go about the refactor?

I've been rewriting page by page. The first one, Home, I initially tried to use LLM, a free one. Never more... It correctly rewrote like 50%, created a nice scaffolding, but the rest one I've been fixing manually. It also didn't handle this trap in JSX (Astro 7 handles whitespaces like JSX now by default), I mean:

some text
<a href...>in a new line>

Renders as some textin a new line. I fixed by adjusting linebreaks manually, but now I know it's not the best solution (I think {' '} is).

In terms of verification, I've been carefully scrolling flix.dev and localhost next to each other (visually and the effective html) and checking if it's now identical.

The rest (the pages after Home) I've rewritten manually. I think it was a better approach. The verification was easier, because I essentially took the original React and wrote Astro components that would make it render the same.

Are URLs preserved? We don't want to break links.

I think so (I've checked for instance https://flix.dev/principles/ vs localhost:8000/principles/ and it works. The URLs are defined in Layout.astro, see const navLinks = ....

The code font is not the same or the same size?
Instead of bundling our own textmate grammar, perhaps we could use highlight.js?

The renderer is Shiki and Prism is an option. I have no idea what is Prism, but Shiki, if I understand correctly, renders on the server and is kind of built-in. So we could use highlight.js (not sure how, but I'm pretty sure it's possible), but then we don't take advantage of the built-in solution (and I guess it would involve using JS on the client side). Some details here: https://docs.astro.build/pl/guides/syntax-highlighting/. This also explains why the font is not the same. It's a different renderer and I couldn't find an identical theme among the bundled ones. I would have to write a new one, I guess.

Does the use of Astro mean that the website will work (mostly) without JavaScript?

It depends. The code I've submitted uses exactly zero JavaScript, because everything is rendered during npm run build, even syntax highlighting. So there is no JavaScript needed, unless you opt-in. I'm not sure if highlight.js would involve JS on the client.

@magnus-madsen

Copy link
Copy Markdown
Member

Thanks-- I am on vacation but I will revisit this when i am back (August)

@magnus-madsen magnus-madsen changed the title Rewrite to Astro, to make the website static feat: rewrite to Astro, to make the website static Jul 28, 2026
@magnus-madsen

Copy link
Copy Markdown
Member

Thanks @DLakomy for your write up and hard work. I've looked into Astro and it seems like a good choice, so I would like to proceed towards merging this PR! :-)

What I will do is to review it and give some feedback. I then suggest that some feedback is fixed now and some feedback can be resolved in follow-up PRs.

Are you up for that?

@magnus-madsen magnus-madsen changed the title feat: rewrite to Astro, to make the website static feat: rewrite to Astro Jul 29, 2026
@magnus-madsen

Copy link
Copy Markdown
Member

First things first: I need you to add your name to AUTHORS.md to affirm that you contributions become open source.

@magnus-madsen magnus-madsen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall just a few minor comments and questions.

I will now take a look at the content page-by-page.


---

<div><slot /></div>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand. I think we should just inline components that are single <div>'s. Can we do that?


---

<div class="card-title"><slot /></div>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This we keep as a component right?


---

<div>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this we can inline?

import { Code } from "astro:components";
const { code } = Astro.props;

// TODO write a proper TextMate grammar and contribute upstream

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am OK with this for now, but what are our choices?

We already have Flix support for highlight.js and for linquist. Do either of these help us?

It would be nice not to have yet another grammar to maintain. Links:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explore whether its possible to typeset at compile-time instead of as embedded JavaScript?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Thank you for the links, I wasn't aware what are the currently maintained grammars. I'll look into it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made some research.

Locally I've added src/grammars/flix.tmLanguage.json from the repo you linked. This just works:

import flixGrammar from "../grammars/flix.tmLanguage.json";

in InlineEditor.astro, instead of the inline constant. The only tricky part is getting this file into the repo. We could just copy it from https://raw.githubusercontent.com/flix/textmate/refs/heads/master/syntaxes/flix.tmLanguage.json for now.

In the future I see these options:

  1. Add this to Shiki (native Astro code renderer). See https://github.com/shikijs/textmate-grammars-themes#contribute. I think this would be the best, as long as the maintainers agree that this condition is passed by Flix: For new grammars to be accepted, we typically require the language to be popular and have a significant number of users. The good thing is that Flix is already on the Linguist.
  2. A GitHub action could sync periodically via PR.
  3. The TextMate grammar could be exposed as an NPM package and added here. Actually this is what Shiki does under the hood, according to their ReadMe. And it's been already done this way for https://github.com/flix/highlightjs-flix.

About highlightjs. I can confirm it works with no JS at runtime. After adding highlight.js via npm, the InlineEditor.astro, css via CDN (a CDN for now). would look like this:

---
// whatever is happening between `---` (the frontmatter), happens build-time
const { code } = Astro.props;

import hljs from "highlight.js/lib/core";
import flix from "highlightjs-flix";
hljs.registerLanguage("flix", flix);

const highlighted = hljs.highlight(code, { language: "flix" }).value;
---

<div class="inline-editor-frame">
  <div class="inline-editor-code">
    <pre><code class="hljs language-flix" set:html={highlighted} /></pre>
  </div>
</div>

I've only made a smoke test, but the result is static HTML with hljs classes, so whatever is possible with hljs in general, is possible here. The default colors are bad, but I could find a better theme (or write one), like I did for the native Code (it wasn't easy BTW, everything looked so pale, I think light-plus looked best).

I'm waiting for your decision. IMO the TextMate way is more Astro-friendly, as Shiki is builtin. However, if you prefer highlightjs, it's not difficult to add this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, lets go for the textmate one. Perhaps we can use a git submodule to include the grammar?

(I am not an expert on git though)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or modify the build script to download the file directly?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build script could download directly. The grammar file could be ignored by git and downloaded only if it's not present in src, to avoid unnecessary fetches each time. Not ideal, but simple.

A submodule would track the version of the grammar, which adds some value; however, in my experience, submodules are difficult to use even for experienced developers. One must remember to clone recursively, it's not obvious how to update a submodule and so on.

Do you think it would be difficult to expose it as NPM package, like https://github.com/flix/highlightjs-flix? I've never done that, so I have no idea. It would be slightly better, because it would be an explicit dependency declared in package.json, as opposed to hiding it in a build script.

As I've said, I think the best would be to contribute to Shiki, but I guess it would take some time for the contribution to be approved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest: (1) A manual copy paste with a comment saying where to obtain the file. Or alternatively (2) we download the file from Git assuming a fixed path as part of the build. Probably (2) would be okay. We do that for e.g. play.flix.dev where we pull the examples from the main flix repo.

@@ -0,0 +1,10 @@
---
const { name } = Astro.props;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this idiomatic? I ask because I don't know.

I assume one could also write {Astro.props.name} further down. But perhaps that is mistaken belief.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is idiomatic. I mean I've seen this pattern a lot in different setups (Astro, React, jQuery, vanilla js). It's not apparent when there is only one prop, but in general it's shorter and less error prone to write const { foo, bar, frobnicate } = Astro.props than:

const
  foo = Astro.props.foo,
  bar = Astro.props.bar,
  frobnicate = Astro.props.frobnicate;

Comment thread src/layouts/Layout.astro
</body>
</html>

<style is:global>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is standard- whatever it does :)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well... It was the easiest to do so for now. The default behaviour is scoping css per component, but we would have to invent a proper components library for it to make sense. For now using global css was the easiest choice. Less diff noise.

Comment thread src/pages/blog.astro
@@ -0,0 +1,16 @@
---
import Layout from '../layouts/Layout.astro';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the convention that components are uppercase (e.g. their file names) but a page like this is lowercase?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The path pages/whatever.astro translates to a url flix.dev/whatever/. So if we want the url to be blog and not Blog, the name of the file must be exactly that. I think there are possible rewrites and so on, but this is for fancier cases than the basic one.

Comment thread src/pages/index.astro
import Layout from "../layouts/Layout.astro";
import InlineEditor from "../components/InlineEditor.astro";

// FIXME inline all of it

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean to just put the code literals where they are used, right?

I think that would make sense, if Astro allows it without breaking the formatting

@DLakomy DLakomy Jul 29, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I've totally forgotten about this FIXME (or forgot to remove it after thinking it's good as is :D). I've got no opinion, so if you say inlining makes sense, I'll do so. I think it should work.

EDIT: see next comment

Comment thread src/pages/index.astro
</p>
</div>
<div class="col-md-6">
<InlineEditor code={httpExample} />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Hmm, Perhaps the current solution is also OK?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless you've got another opinion I'd prefer to leave it as is. I think it's more readable when the code is in constants.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, let us leave it as is for now. We can remove the TODO.

Comment thread src/styles/global.css
@@ -1,7 +1,6 @@
body {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume these CSS changes were just to make it look right? Possibly the HTML structure changed slightly?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main changes were due to the code editor change. There were minor HTML changes (mainly simplifications) with CSS compensation, so the webpage remains the same.

TBH I've forgotten why I've removed .btn-group .btn, .btn-xs. I will check. Unless I find a reason, I think I'll revert this part, so there is no confusion why it's changed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks-- sounds good.

@magnus-madsen

Copy link
Copy Markdown
Member

We can update this QA after the merge 😆
CleanShot 2026-07-29 at 08 37 35

@magnus-madsen

Copy link
Copy Markdown
Member

A few more comments:

  • The favicons shifted/slightly changed. Is there a reason for that? And should we perhaps use a npm package instead of CDN?
  • The carousel of VSCode images on the home page is now just a 4x grid. Perhaps that is OK. Otherwise we need JavaScript right? Hmm. Perhaps this: https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Overflow/Carousels or some other Astro component can help us?
  • The code font is slightly off. That would be nice to have fixed (not sure what the issue is).
  • In later PR, we should probably use a dynamic grid/flexbox for the VSCode page.

@magnus-madsen

Copy link
Copy Markdown
Member

Overall this looks great! I don't think much remains to be done before it can be merged. Just chasing a few loose ends.

@DLakomy

DLakomy commented Jul 29, 2026

Copy link
Copy Markdown
Author

Thank you for the review. I plan to to work on it this weekend.

For now, some quick answers (apart from the ones I've answered in the relevant threads; hopefully I've answered all of them, except for inline/not inline cosmetics, I address them here):

  1. About inline vs not inline: I'll do according to your suggestions. I've got no strong opinion and it's purely cosmetic at the moment.
  2. The carousel of VSCode - there is something like that: https://github.com/claudiabdm/astro-carousel. I didn't use that, because I don't know your stance about dependencies likes this. Personally I'd prefer to avoid a carousel on a mostly static page, to avoid fighting with browser compatibility (especially Safari...). Note that the current one seems to be broken 😬 Clinking on the arrows crash the browser (Safari/Chrome). However, it's your webpage, so I can see what I can do. Just let me know if I should avoid js/dependencies.
  3. The favicons shifted/slightly changed - it was very difficult to find some of the brand icons. Maybe a proper frontend-dev would do it effortlessly, but I just took the newest fontawesome, to be able to raise this PR faster. Should I try to match the previous ones? About CDN vs NPM: I chose CDN (and added integrity), because a CDN has been used already. AFAIK there is no consensus among frontend devs, whether NPM or CDN is a better solution.
  4. The code font is slightly off - do you mean color / spaces between the lines / font size? It might be difficult to make it 100% as is on flix.dev now, but will try. I'll get back to this after investigating other code renderers, as it might result in different circumstances.
  5. In later PR, we should probably use a dynamic grid/flexbox for the VSCode page. - when an issue on GitHub is raised, please let me know. Maybe I'll give it a try.

BTW I'm not marking the comments where I've answered as Resolved, in case there are follow ups.

@magnus-madsen

Copy link
Copy Markdown
Member

Thank you for the review. I plan to to work on it this weekend.

And thank you for your efforts.

1. About inline vs not inline: I'll do according to your suggestions. I've got no strong opinion and it's purely cosmetic at the moment.

Great!

2. `The carousel of VSCode` - there is something like that: https://github.com/claudiabdm/astro-carousel. I didn't use that, because I don't know your stance about dependencies likes this. Personally I'd prefer to avoid a carousel on a mostly static page, to avoid fighting with browser compatibility (especially Safari...). 

How about we leave this for later, and just show a single screenshot?

3. `The favicons shifted/slightly changed` - it was very difficult to find some of the brand icons. Maybe a proper frontend-dev would do it effortlessly, but I just took the newest fontawesome, to be able to raise this PR faster. Should I try to match the previous ones? About CDN vs NPM: I chose CDN (and added `integrity`), because a CDN has been used already. AFAIK there is no consensus among frontend devs, whether NPM or CDN is a better solution.

I don't really care so much about the specific icons; I care more about reducing the usage of code we don't control. I am not a webdev, so I am not entirely sure what is best practice here.

4. `The code font is slightly off` - do you mean color / spaces between the lines / font size? It might be difficult to make it 100% as is on flix.dev now, but will try. I'll get back to this after investigating other code renderers, as it might result in different circumstances.

Its not the same font on my machine, but a good question is what font it should actually be. The CSS inspector in firefox shows: font-family: "Monaco", "Menlo", "Ubuntu Mono", "Consolas", "Source Code Pro", "source-code-pro", monospace. Perhaps we could simply try that to start with.

5. `In later PR, we should probably use a dynamic grid/flexbox for the VSCode page.` - when an issue on GitHub is raised, please let me know. Maybe I'll give it a try.

Sounds good. We can create some follow-up issues once this PR is merged.

BTW I'm not marking the comments where I've answered as Resolved, in case there are follow ups.

Thanks and good plan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rewrite in plain HTML

2 participants