Update project structure
3
.gitignore
vendored
@@ -46,6 +46,3 @@ Thumbs.db
|
||||
.vscode/
|
||||
project.nimcache/
|
||||
|
||||
# Files without extensions (propably binaries)
|
||||
**/[^./]*
|
||||
!**/[^./]*/
|
||||
|
||||
11
README.md
@@ -7,19 +7,18 @@ Luxtools is a minimal-but-complete scaffold for a retro-styled web application b
|
||||
- **Nim**: Nim's ahead-of-time compilation and small standard library make it ideal for producing a single self-contained binary. Its async HTTP primitives provide great performance with minimal boilerplate.
|
||||
- **HTMX**: HTMX keeps the frontend simple by embracing hypermedia. We can ship almost entirely server-rendered HTML snippets, allowing Nim to stay in control without a bulky SPA build step.
|
||||
- **TUI.CSS**: This lightweight CSS framework offers a retro terminal aesthetic with zero JavaScript and a tiny footprint—perfect for a nostalgic interface while remaining easy to customize.
|
||||
- **Single binary delivery**: HTML templates and the entire `static/` tree of vendored assets are embedded at compile time via `staticRead`, so the server ships with everything it needs. The compiled binary serves those resources directly from an in-memory table, while a separate `www/` directory remains available for user-provided uploads.
|
||||
- **Single binary delivery**: HTML templates and the entire `src/static/` tree of vendored assets are embedded at compile time via `staticRead`, so the server ships with everything it needs. The compiled binary serves those resources directly from an in-memory table, while a separate `assets/` directory remains available for user-provided uploads.
|
||||
|
||||
## Project layout
|
||||
|
||||
```
|
||||
luxtools/
|
||||
├── bin/ # Output directory for release binaries
|
||||
├── static/ # Vendored assets compiled into the binary static table
|
||||
├── src/
|
||||
│ └── luxtools.nim # Main server entrypoint
|
||||
├── templates/
|
||||
│ └── index.html # HTMX-powered landing page (compiled into the binary)
|
||||
├── www/ # Runtime asset directory served from disk
|
||||
│ ├── luxtools.nim # Main server entrypoint
|
||||
│ ├── static/ # Vendored assets compiled into the binary static table
|
||||
│ └── templates/ # HTMX-powered landing page (compiled into the binary)
|
||||
├── assets/ # Runtime asset directory served from disk
|
||||
├── tests/
|
||||
│ └── test_rendering.nim# Lightweight regression tests for HTML helpers
|
||||
├── luxtools.nimble # Nimble manifest with build/test tasks
|
||||
|
||||
@@ -13,7 +13,7 @@ task build, "Build the optimized standalone binary":
|
||||
exec "nim c -d:release --opt:speed -o:bin/luxtools src/luxtools.nim"
|
||||
|
||||
task run, "Start the development server with hot rebuild":
|
||||
exec "nim c -r src/luxtools.nim"
|
||||
exec "nim c -o:bin/luxtools -r src/luxtools.nim"
|
||||
|
||||
task test, "Execute the lightweight test suite":
|
||||
exec "nim c -r --path:src tests/test_rendering.nim"
|
||||
exec "nim c -r --path:src -o:bin/test_rendering tests/test_rendering.nim"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import std/[asynchttpserver, asyncdispatch, os, strformat, strutils, tables, times]
|
||||
|
||||
const
|
||||
indexPage = staticRead("../templates/index.html")
|
||||
indexPage = staticRead("templates/index.html")
|
||||
|
||||
type
|
||||
StaticFile = tuple[content: string, contentType: string]
|
||||
@@ -33,7 +33,7 @@ proc guessContentType(path: string): string =
|
||||
else:
|
||||
defaultContentType
|
||||
|
||||
const staticRootDir = parentDir(currentSourcePath()) / ".." / "static"
|
||||
const staticRootDir = parentDir(currentSourcePath()) / "static"
|
||||
|
||||
const staticFileEntries: seq[(string, StaticFile)] = block:
|
||||
var entries: seq[(string, StaticFile)] = @[]
|
||||
@@ -59,7 +59,7 @@ proc findStaticFile(path: string; asset: var StaticFile): bool =
|
||||
false
|
||||
|
||||
proc assetsRoot(): string =
|
||||
absolutePath(joinPath(getAppDir(), "..", "www"))
|
||||
absolutePath(joinPath(getAppDir(), "..", "assets"))
|
||||
|
||||
var clickCount = 0
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
|
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
@@ -1,7 +1,7 @@
|
||||
import std/[os, strutils, unittest]
|
||||
import ../src/luxtools
|
||||
|
||||
const indexTemplate = staticRead("../templates/index.html")
|
||||
const indexTemplate = staticRead("../src/templates/index.html")
|
||||
|
||||
suite "rendering helpers":
|
||||
test "counter markup references hx attributes":
|
||||
@@ -19,6 +19,6 @@ suite "rendering helpers":
|
||||
check not indexTemplate.contains("unpkg.com/htmx")
|
||||
check not indexTemplate.contains("unpkg.com/tui-css")
|
||||
|
||||
test "demo asset lives in www directory":
|
||||
let assetPath = joinPath(getAppDir(), "..", "www", "demo.txt")
|
||||
test "demo asset lives in assets directory":
|
||||
let assetPath = joinPath(getAppDir(), "..", "assets", "demo.txt")
|
||||
check fileExists(assetPath)
|
||||
|
||||