Building a Site - FOSL
Creating a website from scratch for Friends of the Sumas Library (FOSL), a local nonprofit organization.
posted
NOTE: This artical is incomplete as I rethink my approach. Nothing wrong with what I wrote here, I just keep trying new things. I will revisit this and complete the article once some ideas settle.
This is part project writeup, part tutorial, part conjecture. Fair warning, this is a long post and getting longer. I assume I am the only one looking at my site so I am writing this for me. If you find any of it useful or have questions, hit me up.
What am I building?
I am creating a new website for Friends of the Sumas Library (FOSL), a community focused non-profit supporting my small town in Washington state. Full disclosure, I am currently serving on the FOSL board of directors as the secretary. Also, I made the previous two iterations of their website at friendsofthesumaslibrary.org.
Why am I building it?
I am making my way into web development and view this as a chance to practice making websites for clients. Nobody else on FOSL is technical (in an IT sense) so I need to make sure that whatever I build can be edited later by others. That means a content management system of some kind with a reasonably nice editing experience.
I have a few new web-dev toys I am playing with, namely Tailwind and Starwind UI. Combine that with Astro v6 recently releasing, and it seems like a good chance for a fresh crack at the FOSL website. The current version is a bit cobbled together.
The Stack
The FOSL website will be hand coded by me, created and deployed using the following tools:
- Astro: web development framework
- Starwind UI: Astro components and blocks
- Tailwind CSS: style the website and combo off of Starwind
- TinaCMS: headless content management system
- GitHub: cloud code repository
- Netlify: web host
As a small non-profit with limited funds running on volunteer power, it is important that we keep this low cost. Every piece in the stack is either entirely free or has a generous free tier. Everything is also modular, with any piece able to be swapped out when its associated company inevitably turns evil or sells out.
Excluding the yearly cost to register our domain, the cost for this site is $0. There is no charge to get up and running and no monthly fees to keep things running. That isn’t to say this is “free”. I am spending a lot of my time and energy on this, and it will take effort to keep content up to date over what I hope is years of use.
Astro
https://astro.build - free, open-source
The core of my website is Astro, a “web framework for content-driven websites” (think blogs and their cousins). Astro is like React but way more focused on the HTML+CSS over the JS. This works out great because I legitimately enjoy writing HTML and CSS, and fumble my way through JS.
Another huge perk of Astro is markdown. Every page can be a vanilla html file, the native .astro file, or even a simple .md file. I take notes during the FOSL meetings in markdown on my laptop. I don’t have to do anything to prep that to go live, that note file IS my site page!
At this point in my life, if there is something I am making for the web, I want to make it in Astro.
Starwind UI
https://starwind.dev - free, open-source 1
Across the years I have looked into a few component systems, but most aren’t geared toward Astro. Plus I like to tinker so importing things I don’t fully control isn’t much fun. Across most things I am more interested in dissecting a template or component to pull approaches I like than use them as-is.
Recently I came across Starwind UI as an Astro-specific library of components inspired by shadcn/ui. This scratches two itches. First, it is Astro native. Second, all components and blocks created by Starwind are fully brought into my project as editable code. I can use them as-is, wrap them up inside of my own custom components, or fully customize them line by line. Nice!
I am still figuring out how to effectively use Starwind. My current approach is to make use of the components where I can, and take heavy inspiration from the pre-made blocks. Even though I paid for a pro license to use all blocks, rarely is something off the shelf going to work exactly how you want it. At some point you will want to customize or adjust something.
I plan to import all Starwind components, and use the blocks as reference to see how Starwind themselves combo their components together. Even without the components, the Starwind blocks are super interesting to see how somebody with a much bigger “developer” hat makes production-ready Astro code.
Tailwind CSS
https://tailwindcss.com - free, open-source
Look, I’m a vanilla CSS boy. I like thinking over CSS interactions and seeing how the pieces fit together. I love the puzzle of responsive design. Because of that, I have actively avoided Tailwind since I got deep enough into the web-dev rabbit hole to know what Tailwind was.
When I first started playing with the Starwind components, I was disappointed to see it went heavily at Tailwind. I didn’t really want to commit to learning it, so my intention was to live in the hybrid land where Starwind pieces got styled internally by Tailwind and I would override and set global styles with traditional CSS.
That plan changed when Jessican Chan (aka Coder Coder) dropped a hott new YouTube video Tailwind CSS v4 for Beginners . A 2 hour crash course seemed worth the investment. I don’t know that I will be won over, but now that I have some base understanding of Tailwind I want to put it to the test here.
TinaCMS
https://tina.io - free, open-source 2
If it is just me, I don’t need or want a content management system. If I have code work to do, I am working with local files in my code editor of choice (currently Zed). If I am writing content, I am again working with local files now in my markdown editor of choice (currently Typora). A content management system has me working through the Internet to edit files in a browser-based editor, removing many quality of life features my code and markdown editors give me.
That works for me, but what about when I am no longer the FOSL secretary and somebody else needs to enter notes or make event pages? Enter WordPress. Never mind, WordPress is the worst.
For my needs, TinaCMS is my best bet for a non-technical editing experience of the website. It is “headless”, meaning Astro still controls the structure, style, and layout while Tina is a gateway into the content files and some basic site settings. Tina is git-based and powered by markdown. That keeps source code readable, files understandable, and all content lives directly with the code on the cloud repo. Tina can be self-hosted, or TinaCloud provides a decent free plan. We are going for the free plan limited to 2 users. I will need to be the admin user, but this gives a second seat that can shift to others as the need arises.
I have also used DecapCMS in the past. Decap works well and has many of the same perks as Tina. In the end, I think the content editing experience is cleaner with Tina so I went with that here.
GitHub
https://github.com - free, proprietary 3
For my own personal use, I have largely abandoned GitHub and am instead using Codeberg. I wrote about this move and other similar ones in my post Breaking up with Micro$oft. However, TinaCMS and Netlify both work nicely with GitHub so I am using that here. At least for now, personal projects = Codeberg and client projects = GitHub.
Netlify
https://www.netlify.com - free, proprietary 4
GitHub stores the code, and Netlify turns it into a site that others can go to.
When I work on this site, I work on a local clone of the GitHub repo. I save, commit my changes, and push stuff back to the main storage in GitHub. When others edit the content through TinaCMS, those changes get similarly saved, committed, and pushed back to GitHub. The only difference is I have to know what git is, while the TinaCMS side gets to press a button that says “save”.
Netlify is connected to the GitHub repo. Whether the change happens from me or from TinaCMS, when the GitHub files change Netlify gets flagged and rebuilds the site to account for the new content.
The Build
Step 1: Set up Astro
I have recently been using bun instead of npm. If I am honest, I barely know the difference. But bun seems to go through the same steps much quicker so I keep using it.
To start things off, I fired up the ol’ terminal and summoned the mighty Astro to create my projects with bun create astro. Nothing too fancy, picking the “A basic, helpful starter project” template. Having an index and base layout already there makes it easier to hook everything up even if it’s all going to get changed.
Within my project, I had a few basic first steps to take. I added the mdx and sitemap integrations with bunx astro add mdx sitemap. The sitemap integration automatically maps out all pages and helps with search engine optimization. The mdx integration allows me to get a bit fancy in my markdown, essentially acting like a hybrid between an .astro file and a .md file allowing me to use variables and components.
I finished up step 1 by adding information about my live site domain (friendsofthesumaslibrary.org) into the Astro configuration file, my site head, and in a freshly created basic robots.txt file. The Astro docs on the mdx and sitemap integrations walk through this process.
Step 2: Set up Starwind UI & Tailwind
The Starwind Pro setup guide includes a CLI setup run with bunx starwind@latest init --pro. This sets everything up for the Starwind components, blocks (both free and pro licensed), and Tailwind CSS. The setup guides you through everything. My only change was installing the dependencies manually with bunx instead of npx. The CLI setup tells you which ones you need.
Starwind also has a Theme Designer. I’ll come back to this later but for now I snagged the built-in “Nature” theme to get some quick custom styles. Pasting that into the starwind.css file created during the CLI setup gave me a solid Tailwind base to customize later.
Last, I installed every current Starwind component using bunx starwind@latest add --all. These install to a dedicated “starwind” folder under my components. My intention is to never alter these files directly, instead using them within my own Astro components and layouts. If any need to be altered, I can copy/paste the Starwind component source code into my own custom component, slicing and dicing to my heart’s content. That’s half the reason I chose Starwind!
Step 3: Create Astro content collections, pages, and layouts
Now I need to set some things up. The plan is to have basic site settings and page content all be editable through TinaCMS. Content collections are used for chunks of content that share a similar structure. Static pages are the core pages I expect site visitors to go to. Dynamic pages are created on demand. When a new event, meeting, or blog post gets submitted, it needs a page to live on. If somebody decides a year form now they want a new page talking about donation processes, they need a way to generate that page.
-
Content collections
- Site settings (postponed)
- Pages
- Blog
- Events
- Meetings
- Board of Directors
-
Static pages
- Home
- About
- Events
- Blog
- Contact
- 404
-
Dynamic pages
- Additional pages created by TinaCMS editors
- Blog posts
- Meeting reports
- Event pages
For now I am just getting functional pieces set up, putting actually content on those pages will come later. The content collections will be set up to use md or mdx files, knowing I will almost exclusively use basic markdown there. The static pages will be mdx files supported by astro layouts and components. The layouts allow me to define the overall structure for each page (and content collection), no matter how complex it gets. Components let me create reusable blocks customized for specific use cases or content types. Then the mdx pages themselves can make use of my layouts and components while keeping the main content as readable markdown.
Starting with the content collections, I followed the Astro docs on Content Collections to create the content.config.ts file and define my content collection schema. Since this is not my first time making a FOSL website, I am reusing a lot of the old schema. I didn’t get too hung up on this as it will likely evolve as I build. I took a best guess and pulled inspiration from the Astro docs.
I added a few sample content files into each collection so I could verify everything was set up correctly. I also created minimal pages for all static pages, a few simple layouts for each anticipated type of page I will need, and dynamic pages for all collections. I can’t describe how to do it any better than the Astro docs, so read the docs to know how to set all that up.
The site is now basic, boring, and fully functional. The only remaining technical piece to implement is TinaCMS. When I do that, I will need to redundantly define my content collection schema on the Tina side, duplicating the effort for all future schema changes. I anticipate the schema will change a bit as I figure out components so I am saving Tina implementation until things are a bit more established.
Step 4: Build Site Components
For now I am leaving the layouts as the basic placeholders they are. I want things to be prettier, more functional, and most custom.
Primary Navigation
I really like the navigation blocks provided by the Starwind library, but have no interest in using a mobile “hamburger” menu. On the development side, it adds complexity and a need to define drastically different desktop vs mobile nav styles. On the user side, I personally don’t like clicking on a button to open navigation options. It hides my screen and any sort of delay feels like an eternity. I like my navigation like I like my [insert something appropriate] — always fully exposed.5
Kevin Powell is one of my favorite references for CSS approaches, so I am taking some inspiration from his website at https://www.kevinpowell.co. When wide enough, the home nav link will be on the left and all other nav links pushed to the right. When screens get smaller, just smash it all together into a responsive list centered on the page.
One thing I just noticed now on his site was the use of sticky nav. When on the wider desktop view, his navigation sticks to the top of the page, making it always visible. As soon as things get tight enough that we go smash-mode, the sticky nav is turned off and you must scroll to the top of the page to view. I like this. Sticky nav is super useful, but it takes up room on what might be a small screen. On a desktop, I got room to spare so love having toolbars and taskbars for ease of use.
I am intentionally keeping things simple so I am making my own custom navigation, but took heavy inspiration from Starwind’s “Navbar 1 - Centered” block.
Primary Footer
For now my footer will be quite simple, and may stay that way. A line with the name of the organization, a line with our address (the library’s address), and an email link to contact FOSL. I might update this with a more complete site map or other links down the road, but for now just some centered text.
I also created a quick “made by crossinguard.dev”. Might as well call out my own work!
…to be continued
Footnotes
-
Starwind UI components are free and open source. The creator also sells licenses (one-time purchase) for Starwind Pro ↩
-
TinaCMS is free and open source. In production, TinaCMS requires a backend which can be self-hosted or set up through TinaCloud, which includes a free tier. ↩
-
GitHub has a generous free tier, but there are limitations. Additional paid tiers with extra features and higher limits are available. ↩
-
Netlify has a generous free tier, but there are limitations. Additional paid tiers with extra features and higher limits are available. ↩
-
human-written em-dash! I had to use a character map to know how to type it… ↩