Custom Web Framework

I've always been drawn to frameworks that get out of your way and let you build rather than make you feel like you're shipping more framework than application. So I built Newtron: a PHP framework that's super simple on the surface but thoughtfully designed underneath.

The Problem

Modern frameworks are amazing, but they often fall into two camps: either they're incredibly feature-rich (and heavy), or they're small micro-frameworks that leave you building everything yourself. I wanted something in between, a framework that handles the boring stuff automatically while staying lightweight and letting you focus on building features.

Take forms for example. Handling a contact form means:

  • Setting up CSRF protection
  • Writing validation rules
  • Handling the validation errors
  • Repopulating fields on error
  • Displaying error messages
  • Handling file uploads separately

That's a lot of boilerplate for something we do constantly.

My Solution

Newtron is built around the idea of "embarrassingly simple" APIs. Here's that entire contact form in Newtron:

1$form = Form::new('contact')->fields( 2 new TextField('name')->required()->minLength(2), 3 new TextField('email')->required()->email(), 4 new TextareaField('message')->required()->minLength(10), 5 new FileField('attachment')->maxSize(5120) 6); 7 8if ($form->submitted() && $form->validate()) { 9 ContactService::send($form->data()); 10}

That's it. Just a few lines of code handling CSRF protection, validation, file uploads, error display, field repopulation, and progressive enhancement. The form just works.

Progressive Enhancement with Flux

One of my favorite things in Newtron is its built-in reactive UI system called Flux. Inspired by frameworks like Remix, it uses standard HTML forms that work perfectly without JavaScript:

1<form method="POST" action="/todos" data-flux> 2 <input type="text" name="title" required> 3 <button type="submit">Add Todo</button> 4</form>

Without JavaScript: Standard form submission, page reload, everything works.

With JavaScript: Flux intercepts the form, submits via fetch, and swaps the response into the DOM. No page reload, but if JavaScript fails, nothing breaks.

Technical Challenges

One interesting challenge was building the development server with live reload. I wanted it to work without requiring Node.js or any JavaScript tooling, and I didn't want to reinvent the wheel. My solution was to wrap PHP's built-in development server:

  • The php reactor serve command spins up PHP's built-in server with a custom router script
  • The router script handles framework bootstrapping and automatically injects a lightweight polling script into HTML responses
  • A file watcher monitors project files (app/, resources/, routes/, public/, etc) and generates a hash from file modification times
  • When files change, the browser's polling script detects the new hash and triggers a reload
  • Zero external dependencies, zero build steps. Just PHP

This approach gave me the best of both worlds: the reliability and simplicity of PHP's built-in server, plus the developer experience of live reload.

Another challenge was designing the routing system to support two different modes based on developer preference:

File-based routing (like Next.js) - Drop a file in app/routes/blog/post.php and it's automatically available at /blog/post.

Declarative routing (traditional) - Define routes explicitly in routes/web.php (or another file) with full control.

I worked hard to ensure both modes have feature parity. They support the same middleware, parameters, HTTP methods, everything. It's purely about preference and workflow, not functional trade-offs. Rather than forcing everyone into one approach, Newtron lets you pick the routing mode that fits how you think about organizing your application.

What's Under the Hood

Newtron follows some core design principles:

  • Zero configuration by default: Smart conventions that can be overridden when needed
  • Progressive enhancement first: Everything works without JavaScript
  • HTML and HTTP as the foundation: Use the web platform's strengths
  • Developer experience matters: Less typing, more building

The framework includes a CLI tool called reactor (keeping with the atomic/physics theme) that handles running the dev server and other common tasks.

Lessons Learned

This project reinforced something I already believed: complexity is easy, simplicity is hard. The challenge wasn't building a framework with lots of features, it was deciding what not to include and making the remaining features intuitive enough to feel magical.

Every time I want to add a feature, I ask: "Can I make this work with zero configuration? Can it fail gracefully? Will this still make sense in six months?" Those constraints push me to think harder about API design and developer experience.

I'm still actively developing Newtron, and it's been a fantastic learning experience in framework architecture, API design, and thinking deeply about what developers actually need versus what they think they need.