Skip to content

πŸ«™ A server-side web framework that deploys to Vercel.

Notifications You must be signed in to change notification settings

healeycodes/jar

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

42 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

CI

Jar πŸ«™

My blog post: My Own Python Web Framework


Jar is a toy Python web framework, implemented in about 200 lines of code (see cli.py).

I built it to explore some ideas around framework APIs. Please don't actually use it.

It deploys to Vercel via the Build Output API.

It's called Jar because it has almost no features and you need to fill it up yourself!

Docs

https://jar-docs.vercel.app (built with Jar obviously!)

Features

Jar uses file-system routing.

Pages are Python files that render content. They're put in the pages directory.

Public files (like CSS and other media files) go in the public directory and are served from the root path.

Checkout the source for the kitchen sink example, or the docs website.

A typical project is structured like this:

project/
β”œβ”€ pages/
β”‚  β”œβ”€ index.py
β”œβ”€ public/
β”‚  β”œβ”€ favicon.ico

Build pages

Generated once at build time. Served as a static file.

import time

def render(data):
    return f"<h1>{data['text']} I was built at {data['time']}</h1>", {}

def data():
    return {
        "text": "Hello, World!",
        "time": time.time(),
    }

Fresh pages

Generated for each request. Similar to Server-Side Rendering (SSR).

import json
import time


def render(data):
    content = f"<h1>Fresh Page rendered at {data['time']}</h1>"
    content += f"<code>{data['request']}</code>"
    return content, {}


def data(request):
    return {
        "time": time.time(),
        "request": json.dumps({
            "method": request.method,
            "path": request.path,
            "headers": request.headers,
            "body": request.body
        }, indent=4)
    }


def config():
    return {
        "fresh": {}
    }

Regenerated Pages

Similar to Next.js's Incremental Static Regeneration.

import time


def render(data):
    return f"<h1>Regenerated Page, last rendered at {data['time']}</h1>", {}

def data(request=None):
    return {
        "time": time.time(),
    }

def config():
    return {
        "regenerate": {
            "every": 5
        }
    }

More on the API

The data and config functions are optional. The properties that config returns defines the type of page. The default page is a build page.

Build pages don't have access to a request object.

The response that render returns is a tuple of body, meta where meta can have status_code: int and/or headers: dict keys e.g. {"status_code": 200, "headers": {"some":"header"}}.

More on Packages

If you are using packages (i.e. something you install with pip) you have to install them locally inside your project before building the project with the CLI.

e.g. with pip you can run pip3 install -r requirements.txt --target . at the project's root.

See how the docs website is deployed for an example of this (deploy-docs.sh).

Tests

  • pip3 install -r framework/requirements.txt
  • pytest

Deploy Docs

./deploy-docs.sh

Deploy Kitchen Sink

  • pip3 install -r framework/requirements.txt
  • python3 framework/cli.py build examples/kitchensink
  • cd build && vercel --prebuilt

Releases

No releases published

Packages

No packages published