Metadata-Version: 2.4
Name: WebForge
Version: 2.0.0
Summary: A simple and elegant Python web framework – forge your site in minutes.
Author: WebForge Contributors
License: MIT
Keywords: web,framework,http,server,routing
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: requests; extra == "dev"
Dynamic: author
Dynamic: requires-python

# 🔥 WebForge

> A simple, elegant Python web framework. Forge your site in minutes.

```bash
pip install WebForge
webforge new mysite
cd mysite && python backend/server/forge.py
```

---

## Project Structure

```
mysite/
├── backend/
│   ├── requirements.txt
│   └── server/
│       └── forge.py          ← your app code
└── public/
    ├── pages/
    │   └── index.html        ← HTML templates
    ├── script/
    │   └── app.js            ← JavaScript
    └── service/
        └── style.css         ← CSS & static assets
```

---

## Quick Start

```python
# backend/server/forge.py
from WebForge import env as web

password = web.env("PASSWORD")   # read from environment (like os.getenv)
ip = "192.168.1.123"

@web.app("/")
def index():
    web.route("style", "/public/service/style.css")
    web.route("script", "/public/script/app.js")
    return web.render("index.html")

@web.app("/login")
def login():
    return web.render("login.html")

@web.security("/")
def protect_index():
    web.passwordlock(password)

if __name__ == "__main__":
    web.runapp(debug=True, port=5000, host="0.0.0.0")
```

---

## API Reference

### `web.env(key, default=None)`
Read an environment variable.
```python
db_url = web.env("DATABASE_URL", "sqlite:///app.db")
```

### `@web.app(path, methods=None)`
Register a route handler.
```python
@web.app("/users", methods=["GET", "POST"])
def users():
    return web.json({"users": []})
```

### `web.route(name, filepath)`
Inject a static asset (CSS/JS) into the rendered template.  
Call this **inside** a route handler before `web.render()`.
```python
@web.app("/")
def index():
    web.route("style", "/public/service/style.css")
    return web.render("index.html")
```

### `web.render(template, context={})`
Render an HTML file from `public/pages/`.  
Supports `{{ variable }}` substitution.
```python
return web.render("profile.html", {"username": "Alice"})
```

### `web.json(data, status=200)`
Return a JSON response.
```python
return web.json({"ok": True})
```

### `web.redirect(location, status=302)`
Return a redirect response.
```python
return web.redirect("/login")
```

### `@web.security(path)`
Attach security rules to a route.
```python
@web.security("/admin")
def protect_admin():
    web.passwordlock(web.env("ADMIN_PASSWORD"))
```

### `web.runapp(host, port, debug)`
Start the development server.
```python
web.runapp(debug=True, port=5000, host="0.0.0.0")
```

### `@web.before_request` / `@web.after_request`
Request lifecycle hooks.
```python
@web.before_request
def log_request(request):
    print(f"{request.method} {request.path}")

@web.after_request
def add_cors(request, response):
    response.set_header("Access-Control-Allow-Origin", "*")
```

### `@web.errorhandler(code)`
Custom error pages.
```python
@web.errorhandler(404)
def not_found(request):
    return web.render("404.html")
```

---

## Security Utilities

```python
# Hash a password
hashed = web.hash_password("secret", salt="mysalt")

# Verify a password
ok = web.verify_password("secret", hashed, salt="mysalt")

# Generate a random token
token = web.generate_token(32)
```

---

## CLI

```bash
webforge new <project-name>   # scaffold a new project
webforge run                   # run backend/server/forge.py
webforge version               # print version
```

---

## License

MIT © WebForge Contributors
