SingleFile lets you build and serve beautiful, fast web apps from a single file.
Add a route
get '/' do
erb 'home'
endStart the server
ruby singlefile.rbWhat you need to build beautiful, fast web apps:
- Design defaults and consistency for common frontend UI elements.
- Established patterns for keeping a handle on your CSS.
- Established patterns for simple and complex frontend interactivity.
- A way to interact with your database (optional).
- A simple way to handle routing & templating.
What you don't need to build beautiful, fast web apps
- A heavy framework or meta framework
- Knowledge of complicated, esoteric framework-dependent patterns
- Lots of javascript
- A build step
- HTML First: We leverage what the web platform is capable of, adding minor enhancements that extend existing patterns instead of creating an entirely new language on top of it (cough React).
- Portable: Lack of build step & no platform dependencies make hosting on any platform or running locally completely painless.
- Readable: No need to piece together context from dozens of files or bundled libraries. Easily digestable by both humans & LLMs.
- LLM Friendly - Simple syntax. Few moving parts. Low file count. Comprehensive copy-paste-able documentation. No Build Step Complexity.
- View Source Friendly We embrace locality of behaviour and only add libraries that don't hide their behaviour several layers deep. Once you learn a few simple patterns, you won't have to go diving through external docs sites and Github repos to figure out what's happening.
- No Experience Necessary - A smart developer with zero pre-existing knowledge can become proficient enough to read and write our patterns in an hour.
- Low Floor, High Ceiling: Build a simple web page with html and some tailwind, make it interactive with mini attributes, or level up and build components.
- Designed For Codebase Longevity: Zero frontend dependencies. Minimal backend dependencies. Designed to be still be modifiable in 20 years.
We've taken some liberties with our definition. What we're aiming for is:
- Application: A single file that outlines all routes and backend behaviour (singlefile.rb).
- Documentation: A single file that covers all patterns (With inline slide-outs where necessary).
- Layout: A single file to understand all additions beyond basic html.
Make It Yours
- Add your
favicon.icoin the/assets/iconsfolder - Update the site metadata in
/helpers.rb - Modify the 4 core CSS defaults in
styles.css
--ui-font-family:
--ui-font-family-headings:Add a new route
Create a new file at /views/home.erb then add a route for it.
get '/' do
erb 'home'
endAdd A Link
<a href="/about">About</a>Include a partial
<%= erb :"partials/_sidebar" %>Styling With Tailwind
Use any of the 50,000+ Tailwind classes available through Litewind. We recommend using Tailwind primarily for layout.
<div class="flex justify-center">
</div>Styling Forms
Add .ui-form to any form to make all of the input elements inside of it look beautiful and consistent.
<form class="ui-form"></form>Styling Prose
Wrap the .ui-styled-text class around any html designed to render articles, markdown, or prose.
<div class="ui-styled-text">
<%= markdown_file_to_html("readme.md") %>
</div>Buttons
Add the .ui-button class to any <button> or <a> element. (Read More about Base Styles buttons)
<button class="ui-button">Do Stuff</button>Boxes
Use the .ui-box class to create a section of elevated content. (Read More about Base Styles boxes).
<div class="ui-box"></div>Titles
Add the .ui-title class to any title, or create a .ui-titlepair for a title with a tagline.
<h3 class="ui-title">Coffee</h3><div class="ui-titlepair">
<h3 class="--title ">Coffee</h3>
<p class="--description">Size: Xl</p>
</div>Chips
Display a list of tags using the .ui-chip class. (Read More about Base Styles chips).
<div class="ui-chip">Default</div>Tooltips
Add an aria-label to an element alongside the .ui-tooltip class to get clean animated plain text tooltips.
<a href="#" class="ui-tooltip--top" aria-label="Use the ui-tooltip--top class">
Tooltip Top
</a>Dropdowns
Use popover elements wrapped in a .ui-dropdown to create customizable, styled dropdowns. (Read More about Base Styles Dropdowns).
<div class="ui-dropdown">
<button class="--trigger" popovertarget="dropdown-content">
Click To Open
</button>
<div class="--drawer --bottom p-1 " id="dropdown-content" popover>
<a class="ui-button --minimal">
Google.com
</a>
</div>
</div>Modals
Use commandfor and add the .ui-modal class to your dialog element. (Read More about Base Styles modals).
<button commandfor="confirm-dialog" command="show-dialog">
Delete Record
</button>
<dialog class="ui-modal" id="confirm-dialog" closedby="any" >
<p>Are you sure? This action cannot be undone</p>
<button class="ui-button">Continue</button>
</dialog>Make an element dynamic, define some simple state, and render the value
<ui-state message="Hello World!">
<div ui-text="message"></div>
</ui-state>
Use javascript to update state from user interaction
<ui-state count="0">
<button ui-click="count++">Increment</button>
<div ui-text="count"></div>
</ui-state>
React to changes in input values
Use this.value to get the current value of the form input, and ui-change to listen for changes.
<ui-state name="">
<input type="text" ui-change="name = this.value" />
<span ui-text="name"></span>
</ui-state>More Useful Info
- There are 20+ mini attributes. See the full list here.
- State variables get converted from dash case to camel case (
first-namebecomesfirstName)
Render dynamic content inside your html
Use the <%= %> syntax inside your html files (Read More about Embedded Ruby).
<%= Time.now %>Forms
<form action="">
</form>Helpers
Use any of ActiveSupport's 100+ methods. (Read More about ActiveSupport).
<%= 'dublin'.capitalize %>
- Install Ruby
- Run
bundle install - Run
ruby singlefile.rb
Isn't this just Sinatra?
Sort of, yes. The codebase uses Sinatra, which is designed to be a single file framework. We use it as a shell to provide some simple patterns (routing, templating) and act as glue to bring together several other frameworks that we've built. If you'd like to port this to your language of choice, we'd love to feature you.
How did you decide on what libraries to include?
We've spent a lot of time thinking about patterns for working effectively with HTML, in a way that goes with the grain of the web, and isn't tighly coupled to any particular framework. Base Styles was built to solve our own problems internally (effortless style and consistency), and Mini Js was similar. Both have been refined in production for 3 years across dozens of projects and codebases. We've evolved our approach and syntax over time and landed somewhere that we think is a good balance between simplicity and power.