Deserve with DVE: file-based routes, server-side templates, session auth, form validation.
- Routes = files. One file in routes becomes one URL. No config.
- DVE templates. Server-side views with variables, conditionals, loops, partials.
- Shared layout. Head, nav, footer as partials. Reuse everywhere.
- Session auth. Signed cookies guard the account page and switch the navbar.
- Form validation. Contracts check signup and login before the handler runs.
- Static assets. CSS and images in public folder, served at /assets.
- Deno only. No Node or bundler. UI from Bootstrap CDN.
Clone and run:
git clone https://github.com/NeaByteLab/Deserve-VE.git
cd Deserve-VE
deno installRun the server:
deno task startOpen http://localhost:8000. All pages are server-rendered with DVE.
Development (watch):
deno task devRestarts when main.ts or routes/ change. For view/CSS changes, refresh the
browser.
Tip
Set SESSION_SECRET to a 32-character string in production. A development
fallback is used when the variable is unset.
Every file in routes/ exports HTTP method handlers and maps to one URL.
| Method | Path | Auth | What it does |
|---|---|---|---|
| GET | / |
public | Home page |
| GET | /about |
public | About page with conditional content |
| GET | /dashboard |
public | Stats, table, and list |
| GET | /items |
public | List rendered with #each |
| GET | /hello |
public | Minimal single-variable page |
| GET | /signup |
public | Sign up form |
| POST | /signup |
public | Validate the form, show the created summary |
| GET | /login |
public | Login form |
| POST | /login |
public | Validate, open a session, redirect to account |
| GET | /account |
session | Account page, redirects guests to login |
| POST | /logout |
session | Clear the session, redirect home |
main.ts registers session middleware once, so every handler reaches the
session through context state:
router.use(Mware.session({ cookieSecret }))- Read the current session with
ctx.getState('session'). It isnullfor guests. - Open a session with
ctx.getState('setSession'), called after a valid login. - Clear a session with
ctx.getState('clearSession'), called on logout.
The navbar reads session to switch between Login/Sign Up and Account/Logout,
and /account redirects to /login when no session exists.
Contracts live in schemas/ and run inside the POST handler with
Validator.check. A failing contract throws, and the handler reads the reasons
off error.cause to re-render the form with messages:
import { Validator } from '@neabyte/deserve'
import { loginContract } from '@schemas/login.ts'
// Throws when the form fails a rule
const data = Validator.check(loginContract, body as FormData)| Contract | Checks |
|---|---|
signupContract |
Name min 2 chars, email contains @, password min 8 chars |
loginContract |
Email required and valid, password required |
Deserve-VE/
├── main.ts # Router, session, static, serve
├── deno.json # Tasks, import aliases
├── public/
│ └── css/
│ └── style.css # Sticky footer + overrides
├── schemas/
│ ├── login.ts # Login form contract
│ └── signup.ts # Sign up form contract
├── routes/
│ ├── index.ts # Home
│ ├── about.ts # About (conditional content)
│ ├── dashboard.ts # Stats, table, list (complex DVE)
│ ├── items.ts # List with #each
│ ├── hello.ts # Minimal DVE
│ ├── signup.ts # GET form, POST validate
│ ├── login.ts # GET form, POST validate + session
│ ├── account.ts # Session-guarded page
│ └── logout.ts # POST clears session
└── views/
├── home.dve
├── about.dve
├── dashboard.dve
├── items.dve
├── hello.dve
├── signup.dve
├── login.dve
├── account.dve
└── partials/
├── head.dve # Meta, title, CSS
├── header.dve # Navbar (session-aware)
└── footer.dve # Copyright (year from route)
| Page | DVE use |
|---|---|
| Home | Variables, partials |
| About | {{#if showExtra}} |
| Items | {{#each items as item}}, @index |
| Dashboard | Multiple #each, #if, nested data |
| Hello | Single variable |
| Login | {{#if hasErrors}}, error list |
| Signup | {{#if created}}, error list |
| Account | Session variable |
Templates use Bootstrap 5 (CDN) for layout and components; narrative copy is lorem ipsum.
deno.json maps three folders so imports stay short:
| Alias | Folder |
|---|---|
@routes/ |
./routes/ |
@schemas/ |
./schemas/ |
@views/ |
./views/ |
| Task | Description |
|---|---|
deno task start |
Run server (no watch) |
deno task dev |
Run server with file watch |
- Deserve (JSR) - HTTP server, file-based routing, DVE rendering, session, validation, static middleware
- Deserve docs - Router, views,
ctx.render(), session, validation, static
This project is licensed under the MIT license. See the LICENSE file for details.
