SingleFile

One File. Batteries Included. No Build Steps

SingleFile lets you build and serve beautiful, fast web apps from a single file.

Add a route

get '/' do
  erb 'home'
end

Start the server

ruby singlefile.rb


Everything you need. Nothing you don't

What 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


Principles

  • 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.


The Single File Philosophy

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.


Basics

Make It Yours

  • Add your favicon.ico in the /assets/icons folder
  • 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'
end

Add 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>


Simple Frontend Interactivity

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-name becomes firstName)


More Snippets

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 %>


Setup

  • Install Ruby
  • Run bundle install
  • Run ruby singlefile.rb


Further Reading


FAQ

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.