From 2c992a89148a082d95e7dde6f93cdbabd1f0aec3 Mon Sep 17 00:00:00 2001 From: M Venkatesh Date: Sun, 7 Dec 2025 06:52:43 +0000 Subject: [PATCH 01/35] wip: implement landing page and sidebar UI Add public landing page and PenguinUI sidebar navigation. Still needs browser cache clearing and layout fixes. Partial implementation of #19 --- nano_press/hooks.py | 2 +- nano_press/public/images/nano-press.png | Bin 0 -> 17261 bytes .../components/landing/features.html | 100 ++++++++++++++++++ .../templates/components/landing/hero.html | 60 +++++++++++ nano_press/templates/includes/sidebar.html | 80 ++++++++++++++ nano_press/templates/layout.html | 37 +++---- nano_press/templates/layout_public.html | 38 +++++++ nano_press/www/index.html | 36 +++++++ nano_press/www/index.py | 6 ++ 9 files changed, 337 insertions(+), 22 deletions(-) create mode 100644 nano_press/public/images/nano-press.png create mode 100644 nano_press/templates/components/landing/features.html create mode 100644 nano_press/templates/components/landing/hero.html create mode 100644 nano_press/templates/includes/sidebar.html create mode 100644 nano_press/templates/layout_public.html create mode 100644 nano_press/www/index.html create mode 100644 nano_press/www/index.py diff --git a/nano_press/hooks.py b/nano_press/hooks.py index c8dc295..5328ebc 100644 --- a/nano_press/hooks.py +++ b/nano_press/hooks.py @@ -68,7 +68,7 @@ # ---------- # application home page (will override Website Settings) -# home_page = "login" +home_page = "index" # website user home page (by Role) # role_home_page = { diff --git a/nano_press/public/images/nano-press.png b/nano_press/public/images/nano-press.png new file mode 100644 index 0000000000000000000000000000000000000000..b0a612ae0edd24784f35c8cd0592097829e681a3 GIT binary patch literal 17261 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 literal 0 HcmV?d00001 diff --git a/nano_press/templates/components/landing/features.html b/nano_press/templates/components/landing/features.html new file mode 100644 index 0000000..db2d2c2 --- /dev/null +++ b/nano_press/templates/components/landing/features.html @@ -0,0 +1,100 @@ +
+
+
+

+ Why Choose Nano Press? +

+

+ Built for developers who value simplicity, speed, and complete control over their infrastructure. +

+
+ +
+
+
+ + + +
+

Lightning Fast

+

+ Deploy Frappe sites in minutes, not hours. Automated Docker-based deployments with zero manual configuration. From code to production in 5 minutes. +

+
+ +
+
+ + + +
+

Full Control

+

+ Your infrastructure, your rules. Deploy on any server with SSH access. No vendor lock-in, no hidden costs. Complete ownership of your data and deployment. +

+
+ +
+
+ + + +
+

100% Open Source

+

+ Built on Frappe, powered by BWH. Transparent codebase, no black boxes. Contribute, customize, and extend as you see fit. Freedom to innovate. +

+
+
+ +
+
+
+ + + +
+
+

Custom App Support

+

Deploy sites with custom app combinations. Mix and match ERPNext, HRMS, and your custom apps.

+
+
+ +
+
+ + + +
+
+

SSL Out of the Box

+

Automatic SSL certificates with Let's Encrypt. Secure connections configured automatically via Traefik.

+
+
+ +
+
+ + + +
+
+

Real time Logs

+

Track deployments with live Ansible logs. Debug issues with complete visibility into the deployment process.

+
+
+ +
+
+ + + +
+
+

Custom Domain

+

Add custom domain without hassle. Seamless integration with DNS providers.

+
+
+
+
+
diff --git a/nano_press/templates/components/landing/hero.html b/nano_press/templates/components/landing/hero.html new file mode 100644 index 0000000..ffdc49c --- /dev/null +++ b/nano_press/templates/components/landing/hero.html @@ -0,0 +1,60 @@ +
+
+
+
+ +
+
+

+ Introducing Nano Press +

+ +

+ Deploy Frappe sites instantly with your own infrastructure. + Full control, complete transparency. +

+ + + +
+
+
+
+
+
+
+
+
nano-press
+
+
+
$ nano-press deploy
+
→ Server IP: 192.168.1.100
+
→ Apps: frappe, erpnext, hrms
+
→ Domain: mysite.com
+
✓ Site deployed successfully!
+
→ URL: https://mysite.com
+
+ +
+
+
+
+
+
+
diff --git a/nano_press/templates/includes/sidebar.html b/nano_press/templates/includes/sidebar.html new file mode 100644 index 0000000..078e99b --- /dev/null +++ b/nano_press/templates/includes/sidebar.html @@ -0,0 +1,80 @@ +{% set user_image = frappe.db.get_value("User", frappe.session.user, "user_image") or "/assets/frappe/images/default-avatar.png" %} +{% set full_name = frappe.utils.get_fullname(frappe.session.user) if frappe.utils.get_fullname else frappe.session.user %} + +
+ skip to the main content + + + + + +
+ + +
diff --git a/nano_press/templates/layout.html b/nano_press/templates/layout.html index c2ecc60..38c858e 100644 --- a/nano_press/templates/layout.html +++ b/nano_press/templates/layout.html @@ -6,8 +6,7 @@ {{_("Nano Press")}} - - + {% if metatags %} {% for name, content in metatags.items() %} @@ -20,7 +19,6 @@ - @@ -38,41 +36,38 @@ - - {% include "templates/includes/header.html" %} - -
-
- - {% block body %} {% endblock %} + {% include "templates/includes/sidebar.html" %} + +
+
+ {% block body %} {% endblock %} +
+
+ {% block uncontained_body %}{% endblock %} +
+ {% include "templates/includes/toast-teleport.html" %} + + {% include "templates/includes/footer.html" %} +
+
-
- {% block uncontained_body %}{% endblock %} - -
- {% include "templates/includes/toast-teleport.html" %} - - - {% include "templates/includes/footer.html" %} +
{% block script %} {% endblock %} diff --git a/nano_press/templates/layout_public.html b/nano_press/templates/layout_public.html new file mode 100644 index 0000000..7e58694 --- /dev/null +++ b/nano_press/templates/layout_public.html @@ -0,0 +1,38 @@ + + + + + + + {% block page_title %}Nano Press{% endblock %} + + + {% if metatags %} + {% for name, content in metatags.items() %} + + {% endfor %} + {% else %} + + {% endif %} + + + + + {% block head %} {% endblock %} + + + + + +
+ {% block body %} {% endblock %} +
+ + {% include "templates/includes/footer.html" %} + +{% block script %} {% endblock %} + diff --git a/nano_press/www/index.html b/nano_press/www/index.html new file mode 100644 index 0000000..004685e --- /dev/null +++ b/nano_press/www/index.html @@ -0,0 +1,36 @@ +{% extends "templates/layout_public.html" %} + +{% block page_title %}Nano Press - Self-Hosted Frappe Sites{% endblock %} + +{% block body %} +{% include "templates/components/landing/hero.html" %} + +{% include "templates/components/landing/features.html" %} + +
+
+

Ready to Deploy Your First Site?

+

+ Get started in minutes with your own infrastructure. +

+ +
+
+ +{% endblock %} diff --git a/nano_press/www/index.py b/nano_press/www/index.py new file mode 100644 index 0000000..c115975 --- /dev/null +++ b/nano_press/www/index.py @@ -0,0 +1,6 @@ +no_cache = 1 + + +def get_context(context): + context.no_cache = 1 + return context From 37a5298d1b681b2b69f0380b164ff48e6cd785c7 Mon Sep 17 00:00:00 2001 From: M Venkatesh Date: Thu, 25 Dec 2025 14:57:04 +0000 Subject: [PATCH 02/35] feat: implement Penguin UI sidebar and fix width issue (#19) --- nano_press/public/css/theme.css | 27 ++++- .../public/js/vendor/alpinejs/plugins/mask.js | 1 + nano_press/templates/includes/sidebar.html | 98 +++++++++++-------- nano_press/templates/layout.html | 3 +- 4 files changed, 87 insertions(+), 42 deletions(-) create mode 100644 nano_press/public/js/vendor/alpinejs/plugins/mask.js diff --git a/nano_press/public/css/theme.css b/nano_press/public/css/theme.css index 5fa0294..d6007d9 100644 --- a/nano_press/public/css/theme.css +++ b/nano_press/public/css/theme.css @@ -9,7 +9,32 @@ /* Colors */ - + /* Penguin UI Design Tokens */ + --color-primary: oklch(45.56% 0.237 264.05); + --color-primary-dark: oklch(70% 0.2 264.05); + + /* Surface colors */ + --color-surface: oklch(100% 0 0); + --color-surface-alt: oklch(98% 0 0); + --color-surface-dark: oklch(23% 0.011 285.82); + --color-surface-dark-alt: oklch(20% 0.011 285.82); + + /* Text colors */ + --color-on-surface: oklch(40% 0.019 285.88); + --color-on-surface-strong: oklch(20% 0.019 285.88); + --color-on-surface-dark: oklch(90% 0.005 285.82); + --color-on-surface-dark-strong: oklch(100% 0 0); + --color-on-primary: oklch(100% 0 0); + --color-on-primary-dark: oklch(20% 0.019 285.88); + + /* Border colors */ + --color-outline: oklch(85% 0.005 285.82); + --color-outline-dark: oklch(30% 0.011 285.82); + + /* Border radius */ + --radius: 0.5rem; + + /* font size */ --text-xxs: 10px; --text-3xs: 8px; diff --git a/nano_press/public/js/vendor/alpinejs/plugins/mask.js b/nano_press/public/js/vendor/alpinejs/plugins/mask.js new file mode 100644 index 0000000..6b5caa5 --- /dev/null +++ b/nano_press/public/js/vendor/alpinejs/plugins/mask.js @@ -0,0 +1 @@ +(()=>{function b(n){n.directive("mask",(e,{value:t,expression:u},{effect:f,evaluateLater:a,cleanup:r})=>{let l=()=>u,o="";queueMicrotask(()=>{if(["function","dynamic"].includes(t)){let i=a(u);f(()=>{l=d=>{let g;return n.dontAutoEvaluateFunctions(()=>{i(c=>{g=typeof c=="function"?c(d):c},{scope:{$input:d,$money:w.bind({el:e})}})}),g},s(e,!1)})}else s(e,!1);if(e._x_model){if(e._x_model.get()===e.value||e._x_model.get()===null&&e.value==="")return;e._x_model.set(e.value)}});let p=new AbortController;r(()=>{p.abort()}),e.addEventListener("input",()=>s(e),{signal:p.signal,capture:!0}),e.addEventListener("blur",()=>s(e,!1),{signal:p.signal});function s(i,d=!0){let g=i.value,c=l(g);if(!c||c==="false")return!1;if(o.length-i.value.length===1)return o=i.value;let v=()=>{o=i.value=h(g,c)};d?k(i,c,()=>{v()}):v()}function h(i,d){if(i==="")return"";let g=m(d,i);return x(d,g)}}).before("model")}function k(n,e,t){let u=n.selectionStart,f=n.value;t();let a=f.slice(0,u),r=x(e,m(e,a)).length;n.setSelectionRange(r,r)}function m(n,e){let t=e,u="",f={9:/[0-9]/,a:/[a-zA-Z]/,"*":/[a-zA-Z0-9]/},a="";for(let r=0;r{let s="",h=0;for(let i=o.length-1;i>=0;i--)o[i]!==p&&(h===3?(s=o[i]+p+s,h=0):s=o[i]+s,h++);return s},a=n.startsWith("-")?"-":"",r=n.replaceAll(new RegExp(`[^0-9\\${e}]`,"g"),""),l=Array.from({length:r.split(e)[0].length}).fill("9").join("");return l=`${a}${f(l,t)}`,u>0&&n.includes(e)&&(l+=`${e}`+"9".repeat(u)),queueMicrotask(()=>{this.el.value.endsWith(e)||this.el.value[this.el.selectionStart-1]===e&&this.el.setSelectionRange(this.el.selectionStart-1,this.el.selectionStart-1)}),l}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(b)});})(); diff --git a/nano_press/templates/includes/sidebar.html b/nano_press/templates/includes/sidebar.html index 078e99b..29963d6 100644 --- a/nano_press/templates/includes/sidebar.html +++ b/nano_press/templates/includes/sidebar.html @@ -1,80 +1,98 @@ {% set user_image = frappe.db.get_value("User", frappe.session.user, "user_image") or "/assets/frappe/images/default-avatar.png" %} {% set full_name = frappe.utils.get_fullname(frappe.session.user) if frappe.utils.get_fullname else frappe.session.user %} -
+
+ skip to the main content - + + -