cyberai-1 commited on
Commit
6bf9e00
·
1 Parent(s): b5f3cb8

Add traffic sign Flask app

Browse files
.dockerignore ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ .venv
2
+ .codex
3
+ __pycache__
4
+ *.pyc
5
+ instance/*.sqlite3
6
+ static/uploads/*
7
+ Template/assets/...
8
+ Template/assets/index-BN7abppv.js
.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ .codex
5
+ instance/*.sqlite3
6
+ static/uploads/*
7
+ Template/assets/index-BN7abppv.js
Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ ENV PYTHONDONTWRITEBYTECODE=1
4
+ ENV PYTHONUNBUFFERED=1
5
+ ENV PORT=7860
6
+
7
+ WORKDIR /app
8
+
9
+ RUN apt-get update \
10
+ && apt-get install -y --no-install-recommends libglib2.0-0 libgl1 \
11
+ && rm -rf /var/lib/apt/lists/*
12
+
13
+ COPY requirements.txt .
14
+ RUN pip install --no-cache-dir -r requirements.txt
15
+
16
+ COPY . .
17
+
18
+ EXPOSE 7860
19
+
20
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -7,4 +7,47 @@ sdk: docker
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  pinned: false
8
  ---
9
 
10
+ # Traffic Sign Classifier Flask App
11
+
12
+ This project deploys a `traffic_classifier.h5` model as a Flask web app for Hugging Face Spaces with Docker.
13
+
14
+ ## Features
15
+
16
+ - Welcome page based on the provided visual template direction
17
+ - Login and registration
18
+ - Protected traffic sign prediction page
19
+ - SQLite storage inside the container at `instance/traffic_signs.sqlite3`
20
+ - Per-user prediction history
21
+ - True/false feedback for every prediction
22
+ - Dashboard with total predictions, reviewed predictions, true/false counts, and feedback accuracy
23
+
24
+ ## Run Locally
25
+
26
+ ```bash
27
+ python -m venv .venv
28
+ source .venv/bin/activate
29
+ pip install -r requirements.txt
30
+ python app.py
31
+ ```
32
+
33
+ Open `http://localhost:7860`.
34
+
35
+ ## Model
36
+
37
+ Place the trained model in the project root:
38
+
39
+ ```text
40
+ traffic_classifier.h5
41
+ ```
42
+
43
+ The app expects a 43-class traffic sign classifier using 30x30 RGB images, matching the common GTSRB class list.
44
+
45
+ ## Hugging Face Space
46
+
47
+ This Space uses Docker and exposes port `7860`.
48
+
49
+ For production, set a strong secret:
50
+
51
+ ```text
52
+ SECRET_KEY=your-secret-value
53
+ ```
Template/assets/${canvasBackgroundImage} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${canvasOverlayImage} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${cleanedAssetUrl} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${cleanedUrl} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${image.src} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${imageBackgroundInfo.url} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${newSrc} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${newUrl} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${oldSrc} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/${src} ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/... ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/assets/index-CUgQVqrx.css ADDED
The diff for this file is too large to render. See raw diff
 
Template/index.html ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
8
+ />
9
+ <meta
10
+ name="trustpilot-one-time-domain-verification-id"
11
+ content="e7fde8c5-aaf9-473a-b59e-d1f4a8847cd8"
12
+ />
13
+
14
+ <!-- Static SEO for main domain (aura.build) - removed on subdomains/custom domains -->
15
+ <meta
16
+ name="description"
17
+ data-static-seo="true"
18
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
19
+ />
20
+ <title data-static-seo="true">Aura – AI Website Builder</title>
21
+
22
+ <meta property="og:type" content="website" data-static-seo="true" />
23
+ <meta property="og:site_name" content="Aura" data-static-seo="true" />
24
+ <meta
25
+ property="og:title"
26
+ content="Aura – AI Website Builder"
27
+ data-static-seo="true"
28
+ />
29
+ <meta
30
+ property="og:description"
31
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
32
+ data-static-seo="true"
33
+ />
34
+ <meta
35
+ property="og:image"
36
+ content="https://aura.build/share-preview.jpg"
37
+ data-static-seo="true"
38
+ />
39
+ <meta
40
+ property="og:url"
41
+ content="https://aura.build/"
42
+ data-static-seo="true"
43
+ />
44
+ <meta property="og:image:width" content="1200" data-static-seo="true" />
45
+ <meta property="og:image:height" content="630" data-static-seo="true" />
46
+
47
+ <meta
48
+ name="twitter:card"
49
+ content="summary_large_image"
50
+ data-static-seo="true"
51
+ />
52
+ <meta name="twitter:site" content="@AuraBuilds" data-static-seo="true" />
53
+ <meta
54
+ name="twitter:title"
55
+ content="Aura – AI Website Builder"
56
+ data-static-seo="true"
57
+ />
58
+ <meta
59
+ name="twitter:description"
60
+ content="AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma. Trusted by 166,000+ users worldwide."
61
+ data-static-seo="true"
62
+ />
63
+ <meta
64
+ name="twitter:image"
65
+ content="https://aura.build/share-preview.jpg"
66
+ data-static-seo="true"
67
+ />
68
+ <link
69
+ rel="alternate"
70
+ type="text/plain"
71
+ href="https://aura.build/llms.txt"
72
+ data-static-seo="true"
73
+ />
74
+ <script type="application/ld+json" data-static-seo="true">
75
+ {
76
+ "@context": "https://schema.org",
77
+ "@graph": [
78
+ {
79
+ "@type": "Organization",
80
+ "@id": "https://aura.build/#organization",
81
+ "name": "Aura",
82
+ "url": "https://aura.build/",
83
+ "logo": "https://aura.build/logo-aura.svg",
84
+ "sameAs": ["https://twitter.com/mengto"]
85
+ },
86
+ {
87
+ "@type": "WebSite",
88
+ "@id": "https://aura.build/#website",
89
+ "name": "Aura",
90
+ "url": "https://aura.build/",
91
+ "publisher": {
92
+ "@id": "https://aura.build/#organization"
93
+ },
94
+ "potentialAction": {
95
+ "@type": "SearchAction",
96
+ "target": "https://aura.build/assets?q={search_term_string}",
97
+ "query-input": "required name=search_term_string"
98
+ }
99
+ },
100
+ {
101
+ "@type": "SoftwareApplication",
102
+ "@id": "https://aura.build/#software",
103
+ "name": "Aura",
104
+ "applicationCategory": "DesignApplication",
105
+ "operatingSystem": "Web",
106
+ "url": "https://aura.build/",
107
+ "description": "AI landing page builder that creates stunning designs in seconds. No design skills needed. Export to HTML & Figma.",
108
+ "image": "https://aura.build/share-preview.jpg",
109
+ "creator": {
110
+ "@id": "https://aura.build/#organization"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ </script>
116
+
117
+ <!-- Remove Aura SEO/marketing tags on subdomains/custom domains BEFORE page renders -->
118
+ <script>
119
+ (function () {
120
+ var h = location.hostname || "";
121
+ var main = [
122
+ "aura.build",
123
+ "aura.page",
124
+ "aurachat.io",
125
+ "localhost",
126
+ "netlify.app",
127
+ "vercel.app",
128
+ ];
129
+ var isMain = main.some(function (d) {
130
+ return h === d || h.endsWith("." + d);
131
+ });
132
+ var remove = false;
133
+ if (isMain) {
134
+ var parts = h.split(".");
135
+ var isLocal = h.endsWith(".localhost");
136
+ var isPreview =
137
+ h.endsWith(".netlify.app") || h.endsWith(".vercel.app");
138
+ var sub =
139
+ parts.length > 2
140
+ ? parts[0]
141
+ : isLocal && parts.length === 2
142
+ ? parts[0]
143
+ : "";
144
+ remove =
145
+ ((sub && !isPreview) || (sub && isLocal)) &&
146
+ sub.toLowerCase() !== "www";
147
+ } else {
148
+ remove = true;
149
+ }
150
+ if (remove) {
151
+ var els = document.querySelectorAll("[data-static-seo]");
152
+ for (var i = 0; i < els.length; i++)
153
+ els[i].parentNode.removeChild(els[i]);
154
+ }
155
+ })();
156
+ </script>
157
+
158
+ <!-- Google tag (gtag.js) - internal domains only -->
159
+ <script>
160
+ (function () {
161
+ var h = location.hostname || "";
162
+ var internal =
163
+ h === "aura.build" ||
164
+ h === "www.aura.build" ||
165
+ h === "beta--aurachatapp.netlify.app" ||
166
+ h === "localhost" ||
167
+ h.endsWith(".localhost");
168
+ if (!internal) return;
169
+ var s = document.createElement("script");
170
+ s.async = true;
171
+ s.src = "https://www.googletagmanager.com/gtag/js?id=G-2M6V79H761";
172
+ document.head.appendChild(s);
173
+ window.dataLayer = window.dataLayer || [];
174
+ window.gtag =
175
+ window.gtag ||
176
+ function () {
177
+ window.dataLayer.push(arguments);
178
+ };
179
+ window.gtag("js", new Date());
180
+ window.gtag("config", "G-2M6V79H761");
181
+ })();
182
+ </script>
183
+
184
+ <!-- Favicon (removed on subdomains/custom domains where custom favicon takes over) -->
185
+ <link
186
+ rel="icon"
187
+ type="image/png"
188
+ href="/logo-aura-128-light.png"
189
+ media="(prefers-color-scheme: light)"
190
+ data-static-seo="true"
191
+ />
192
+ <link
193
+ rel="icon"
194
+ type="image/png"
195
+ href="/logo-aura-128-dark.png"
196
+ media="(prefers-color-scheme: dark)"
197
+ data-static-seo="true"
198
+ />
199
+ <link
200
+ rel="icon"
201
+ type="image/png"
202
+ href="/logo-aura-128-light.png"
203
+ data-static-seo="true"
204
+ />
205
+ <link
206
+ rel="apple-touch-icon"
207
+ href="/logo-aura-128-light.png"
208
+ data-static-seo="true"
209
+ />
210
+
211
+ <!-- Fonts -->
212
+ <link
213
+ rel="stylesheet"
214
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
215
+ />
216
+
217
+ <!-- Iconify Icon Web Component -->
218
+ <script
219
+ src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
220
+ integrity="sha384-GPb5RlngihS9H0z1D137JsvzmeZ7tCpWEF4t5YDoTZyMsPP8S7h7vFDh4XhheU83"
221
+ crossorigin="anonymous"
222
+ ></script>
223
+ <script type="module" crossorigin src="/assets/index-BN7abppv.js"></script>
224
+ <link rel="stylesheet" crossorigin href="/assets/index-CUgQVqrx.css">
225
+ <link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
226
+ </head>
227
+
228
+ <body>
229
+ <div id="root"></div>
230
+ </body>
231
+ </html>
Template/logo-aura-128-dark.png ADDED
Template/logo-aura-128-light.png ADDED
Template/robots.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ User-agent: *
2
+ Allow: /
3
+
4
+ Sitemap: https://axiom-strategy-72.aura.build/sitemap.xml
Template/sitemap.xml ADDED
@@ -0,0 +1 @@
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>https://axiom-strategy-72.aura.build/</loc><lastmod>2026-05-10T17:55:30.774Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url></urlset>
app.py ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sqlite3
3
+ from datetime import datetime
4
+ from pathlib import Path
5
+ from uuid import uuid4
6
+
7
+ import numpy as np
8
+ from flask import Flask, flash, redirect, render_template, request, session, url_for
9
+ from PIL import Image
10
+ from werkzeug.security import check_password_hash, generate_password_hash
11
+ from werkzeug.utils import secure_filename
12
+
13
+ try:
14
+ from tensorflow.keras.models import load_model
15
+ except Exception:
16
+ load_model = None
17
+
18
+
19
+ BASE_DIR = Path(__file__).resolve().parent
20
+ UPLOAD_DIR = BASE_DIR / "static" / "uploads"
21
+ DATABASE_PATH = BASE_DIR / "instance" / "traffic_signs.sqlite3"
22
+ MODEL_PATH = BASE_DIR / "traffic_classifier.h5"
23
+ ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "webp"}
24
+
25
+ TRAFFIC_SIGN_CLASSES = [
26
+ "Speed limit (20km/h)",
27
+ "Speed limit (30km/h)",
28
+ "Speed limit (50km/h)",
29
+ "Speed limit (60km/h)",
30
+ "Speed limit (70km/h)",
31
+ "Speed limit (80km/h)",
32
+ "End of speed limit (80km/h)",
33
+ "Speed limit (100km/h)",
34
+ "Speed limit (120km/h)",
35
+ "No passing",
36
+ "No passing for vehicles over 3.5 metric tons",
37
+ "Right-of-way at the next intersection",
38
+ "Priority road",
39
+ "Yield",
40
+ "Stop",
41
+ "No vehicles",
42
+ "Vehicles over 3.5 metric tons prohibited",
43
+ "No entry",
44
+ "General caution",
45
+ "Dangerous curve to the left",
46
+ "Dangerous curve to the right",
47
+ "Double curve",
48
+ "Bumpy road",
49
+ "Slippery road",
50
+ "Road narrows on the right",
51
+ "Road work",
52
+ "Traffic signals",
53
+ "Pedestrians",
54
+ "Children crossing",
55
+ "Bicycles crossing",
56
+ "Beware of ice/snow",
57
+ "Wild animals crossing",
58
+ "End of all speed and passing limits",
59
+ "Turn right ahead",
60
+ "Turn left ahead",
61
+ "Ahead only",
62
+ "Go straight or right",
63
+ "Go straight or left",
64
+ "Keep right",
65
+ "Keep left",
66
+ "Roundabout mandatory",
67
+ "End of no passing",
68
+ "End of no passing by vehicles over 3.5 metric tons",
69
+ ]
70
+
71
+
72
+ app = Flask(__name__)
73
+ app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY", "dev-change-me")
74
+ app.config["MAX_CONTENT_LENGTH"] = 8 * 1024 * 1024
75
+ UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
76
+ DATABASE_PATH.parent.mkdir(parents=True, exist_ok=True)
77
+
78
+ model = None
79
+ model_error = None
80
+
81
+
82
+ def get_db():
83
+ conn = sqlite3.connect(DATABASE_PATH)
84
+ conn.row_factory = sqlite3.Row
85
+ return conn
86
+
87
+
88
+ def init_db():
89
+ with get_db() as conn:
90
+ conn.executescript(
91
+ """
92
+ CREATE TABLE IF NOT EXISTS users (
93
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
94
+ name TEXT NOT NULL,
95
+ email TEXT NOT NULL UNIQUE,
96
+ password_hash TEXT NOT NULL,
97
+ created_at TEXT NOT NULL
98
+ );
99
+
100
+ CREATE TABLE IF NOT EXISTS predictions (
101
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
102
+ user_id INTEGER NOT NULL,
103
+ image_path TEXT NOT NULL,
104
+ predicted_class TEXT NOT NULL,
105
+ confidence REAL,
106
+ is_correct INTEGER,
107
+ created_at TEXT NOT NULL,
108
+ FOREIGN KEY (user_id) REFERENCES users(id)
109
+ );
110
+ """
111
+ )
112
+
113
+
114
+ def load_classifier():
115
+ global model, model_error
116
+ if not MODEL_PATH.exists():
117
+ model_error = "traffic_classifier.h5 was not found in the project root."
118
+ return
119
+ if load_model is None:
120
+ model_error = "TensorFlow is not available in this environment."
121
+ return
122
+ try:
123
+ model = load_model(MODEL_PATH)
124
+ model_error = None
125
+ except Exception as exc:
126
+ model_error = f"Model could not be loaded: {exc}"
127
+
128
+
129
+ def current_user():
130
+ user_id = session.get("user_id")
131
+ if not user_id:
132
+ return None
133
+ with get_db() as conn:
134
+ return conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone()
135
+
136
+
137
+ def login_required(view):
138
+ def wrapped(*args, **kwargs):
139
+ if not current_user():
140
+ flash("Please log in to access the classifier.", "warning")
141
+ return redirect(url_for("login"))
142
+ return view(*args, **kwargs)
143
+
144
+ wrapped.__name__ = view.__name__
145
+ return wrapped
146
+
147
+
148
+ def allowed_file(filename):
149
+ return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
150
+
151
+
152
+ def prepare_image(path):
153
+ image = Image.open(path).convert("RGB")
154
+ image = image.resize((30, 30))
155
+ array = np.asarray(image, dtype=np.float32) / 255.0
156
+ return np.expand_dims(array, axis=0)
157
+
158
+
159
+ def predict_sign(path):
160
+ if model is None:
161
+ return "Model unavailable", 0.0
162
+ predictions = model.predict(prepare_image(path), verbose=0)[0]
163
+ class_index = int(np.argmax(predictions))
164
+ confidence = float(np.max(predictions))
165
+ label = TRAFFIC_SIGN_CLASSES[class_index] if class_index < len(TRAFFIC_SIGN_CLASSES) else f"Class {class_index}"
166
+ return label, confidence
167
+
168
+
169
+ @app.context_processor
170
+ def inject_user():
171
+ return {"user": current_user()}
172
+
173
+
174
+ @app.route("/")
175
+ def welcome():
176
+ return render_template("welcome.html")
177
+
178
+
179
+ @app.route("/register", methods=["GET", "POST"])
180
+ def register():
181
+ if request.method == "POST":
182
+ name = request.form.get("name", "").strip()
183
+ email = request.form.get("email", "").strip().lower()
184
+ password = request.form.get("password", "")
185
+ confirm_password = request.form.get("confirm_password", "")
186
+
187
+ if not name or not email or not password:
188
+ flash("All fields are required.", "danger")
189
+ elif password != confirm_password:
190
+ flash("Passwords do not match.", "danger")
191
+ elif len(password) < 6:
192
+ flash("Password must contain at least 6 characters.", "danger")
193
+ else:
194
+ try:
195
+ with get_db() as conn:
196
+ cursor = conn.execute(
197
+ """
198
+ INSERT INTO users (name, email, password_hash, created_at)
199
+ VALUES (?, ?, ?, ?)
200
+ """,
201
+ (name, email, generate_password_hash(password), datetime.utcnow().isoformat()),
202
+ )
203
+ session["user_id"] = cursor.lastrowid
204
+ flash("Account created. Welcome to the classifier.", "success")
205
+ return redirect(url_for("predict"))
206
+ except sqlite3.IntegrityError:
207
+ flash("This email is already registered.", "danger")
208
+
209
+ return render_template("register.html")
210
+
211
+
212
+ @app.route("/login", methods=["GET", "POST"])
213
+ def login():
214
+ if request.method == "POST":
215
+ email = request.form.get("email", "").strip().lower()
216
+ password = request.form.get("password", "")
217
+ with get_db() as conn:
218
+ user = conn.execute("SELECT * FROM users WHERE email = ?", (email,)).fetchone()
219
+ if user and check_password_hash(user["password_hash"], password):
220
+ session["user_id"] = user["id"]
221
+ flash("Connection established.", "success")
222
+ return redirect(url_for("predict"))
223
+ flash("Invalid email or password.", "danger")
224
+ return render_template("login.html")
225
+
226
+
227
+ @app.route("/logout")
228
+ def logout():
229
+ session.clear()
230
+ flash("You have been logged out.", "info")
231
+ return redirect(url_for("welcome"))
232
+
233
+
234
+ @app.route("/predict", methods=["GET", "POST"])
235
+ @login_required
236
+ def predict():
237
+ prediction = None
238
+ if request.method == "POST":
239
+ file = request.files.get("image")
240
+ if not file or file.filename == "":
241
+ flash("Please choose a traffic sign image.", "warning")
242
+ elif not allowed_file(file.filename):
243
+ flash("Upload a PNG, JPG, JPEG, or WEBP image.", "danger")
244
+ else:
245
+ original = secure_filename(file.filename)
246
+ filename = f"{uuid4().hex}_{original}"
247
+ save_path = UPLOAD_DIR / filename
248
+ file.save(save_path)
249
+ label, confidence = predict_sign(save_path)
250
+ image_path = f"uploads/{filename}"
251
+ with get_db() as conn:
252
+ cursor = conn.execute(
253
+ """
254
+ INSERT INTO predictions
255
+ (user_id, image_path, predicted_class, confidence, is_correct, created_at)
256
+ VALUES (?, ?, ?, ?, NULL, ?)
257
+ """,
258
+ (
259
+ session["user_id"],
260
+ image_path,
261
+ label,
262
+ confidence,
263
+ datetime.utcnow().isoformat(),
264
+ ),
265
+ )
266
+ prediction_id = cursor.lastrowid
267
+ prediction = {
268
+ "id": prediction_id,
269
+ "image_path": image_path,
270
+ "predicted_class": label,
271
+ "confidence": confidence,
272
+ }
273
+ if model_error:
274
+ flash(model_error, "warning")
275
+
276
+ history = get_user_history(limit=6)
277
+ return render_template("predict.html", prediction=prediction, history=history, model_error=model_error)
278
+
279
+
280
+ @app.post("/feedback/<int:prediction_id>")
281
+ @login_required
282
+ def feedback(prediction_id):
283
+ value = request.form.get("is_correct")
284
+ if value not in {"0", "1"}:
285
+ flash("Feedback must be true or false.", "danger")
286
+ return redirect(url_for("dashboard"))
287
+ with get_db() as conn:
288
+ conn.execute(
289
+ """
290
+ UPDATE predictions
291
+ SET is_correct = ?
292
+ WHERE id = ? AND user_id = ?
293
+ """,
294
+ (int(value), prediction_id, session["user_id"]),
295
+ )
296
+ flash("Feedback saved for the dashboard history.", "success")
297
+ return redirect(request.form.get("next") or url_for("dashboard"))
298
+
299
+
300
+ @app.route("/dashboard")
301
+ @login_required
302
+ def dashboard():
303
+ history = get_user_history()
304
+ total = len(history)
305
+ reviewed = [row for row in history if row["is_correct"] is not None]
306
+ correct = [row for row in reviewed if row["is_correct"] == 1]
307
+ stats = {
308
+ "total": total,
309
+ "reviewed": len(reviewed),
310
+ "correct": len(correct),
311
+ "incorrect": len(reviewed) - len(correct),
312
+ "accuracy": round((len(correct) / len(reviewed)) * 100, 1) if reviewed else 0,
313
+ }
314
+ return render_template("dashboard.html", history=history, stats=stats)
315
+
316
+
317
+ def get_user_history(limit=None):
318
+ query = """
319
+ SELECT * FROM predictions
320
+ WHERE user_id = ?
321
+ ORDER BY created_at DESC
322
+ """
323
+ params = [session["user_id"]]
324
+ if limit:
325
+ query += " LIMIT ?"
326
+ params.append(limit)
327
+ with get_db() as conn:
328
+ return conn.execute(query, params).fetchall()
329
+
330
+
331
+ init_db()
332
+ load_classifier()
333
+
334
+
335
+ if __name__ == "__main__":
336
+ app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))
login/index.html ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Neon Cyber Login</title>
7
+ <meta name="description" content="Cyberpunk-themed login form with glitch effects, scanline borders and matrix accents.">
8
+ <meta name="author" content="Aigars Silkalns / Colorlib">
9
+ <link rel="canonical" href="https://puikinsh.github.io/login-forms/forms/neon-cyber/">
10
+ <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><circle cx='50' cy='50' r='48' fill='%236366f1'/><text x='50' y='68' font-size='60' text-anchor='middle' fill='white' font-family='system-ui,sans-serif'>L</text></svg>">
11
+ <meta property="og:type" content="website">
12
+ <meta property="og:title" content="Neon Cyber Login Form">
13
+ <meta property="og:description" content="Cyberpunk-themed login form with glitch effects, scanline borders and matrix accents.">
14
+ <meta property="og:url" content="https://puikinsh.github.io/login-forms/forms/neon-cyber/">
15
+ <meta property="og:image" content="https://puikinsh.github.io/login-forms/assets/screenshots/neon-cyber.png">
16
+ <meta name="twitter:card" content="summary_large_image">
17
+ <meta name="twitter:title" content="Neon Cyber Login Form">
18
+ <meta name="twitter:description" content="Cyberpunk-themed login form with glitch effects, scanline borders and matrix accents.">
19
+ <meta name="twitter:image" content="https://puikinsh.github.io/login-forms/assets/screenshots/neon-cyber.png">
20
+ <link rel="stylesheet" href="style.css">
21
+ </head>
22
+ <body>
23
+ <div class="cyber-grid">
24
+ <div class="grid-line grid-h-1"></div>
25
+ <div class="grid-line grid-v-1"></div>
26
+ <div class="grid-line grid-h-2"></div>
27
+ <div class="grid-line grid-v-2"></div>
28
+ <div class="grid-line grid-h-3"></div>
29
+ <div class="cyber-glitch glitch-1"></div>
30
+ <div class="cyber-glitch glitch-2"></div>
31
+ </div>
32
+
33
+ <div class="login-container">
34
+ <div class="cyber-terminal">
35
+ <div class="terminal-header">
36
+ <div class="terminal-buttons">
37
+ <div class="term-btn btn-red"></div>
38
+ <div class="term-btn btn-yellow"></div>
39
+ <div class="term-btn btn-green"></div>
40
+ </div>
41
+ <div class="terminal-title">NEURAL_INTERFACE.exe</div>
42
+ </div>
43
+
44
+ <div class="cyber-content">
45
+ <div class="neon-header">
46
+ <div class="cyber-logo">
47
+ <div class="logo-frame">
48
+ <div class="logo-core">
49
+ <svg width="40" height="40" viewBox="0 0 40 40" fill="none">
50
+ <path d="M20 4L36 12v16L20 36L4 28V12L20 4z" stroke="currentColor" stroke-width="2" fill="none"/>
51
+ <circle cx="20" cy="20" r="6" stroke="currentColor" stroke-width="1.5"/>
52
+ <path d="M14 14l12 12M26 14l-12 12" stroke="currentColor" stroke-width="1"/>
53
+ </svg>
54
+ </div>
55
+ <div class="logo-scanner"></div>
56
+ </div>
57
+ <div class="neon-glow"></div>
58
+ </div>
59
+ <h1 class="cyber-title">
60
+ <span class="title-glitch" data-text="CYPHER_NET">CYPHER_NET</span>
61
+ </h1>
62
+ <p class="access-text">[ SECURE_TERMINAL_ACCESS ]</p>
63
+ </div>
64
+
65
+ <form class="neon-form" id="loginForm" novalidate>
66
+ <div class="cyber-field">
67
+ <div class="field-frame">
68
+ <div class="field-border"></div>
69
+ <input type="email" id="email" name="email" required autocomplete="email">
70
+ <label for="email">&gt; EMAIL_ADDRESS</label>
71
+ <div class="cyber-scanner">
72
+ <div class="scan-line"></div>
73
+ </div>
74
+ </div>
75
+ <span class="cyber-error" id="emailError"></span>
76
+ </div>
77
+
78
+ <div class="cyber-field">
79
+ <div class="field-frame">
80
+ <div class="field-border"></div>
81
+ <input type="password" id="password" name="password" required autocomplete="current-password">
82
+ <label for="password">&gt; ACCESS_CODE</label>
83
+ <button type="button" class="cyber-toggle" id="passwordToggle" aria-label="Toggle password visibility">
84
+ <div class="toggle-frame">
85
+ <svg class="eye-scan" width="18" height="18" viewBox="0 0 18 18" fill="none">
86
+ <path d="M9 3c-4 0-7 3-8 6 1 3 4 6 8 6s7-3 8-6c-1-3-4-6-8-6zm0 10a4 4 0 110-8 4 4 0 010 8zm0-6a2 2 0 100 4 2 2 0 000-4z" fill="currentColor"/>
87
+ </svg>
88
+ <svg class="eye-blocked" width="18" height="18" viewBox="0 0 18 18" fill="none">
89
+ <path d="M3 3l12 12M7 7a3 3 0 003 3m3-3C13 7 10 4 9 4c-1 0-3 1-4 2M9 14c4 0 7-3 8-6-1-1-2-2-3-3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
90
+ </svg>
91
+ </div>
92
+ </button>
93
+ <div class="cyber-scanner">
94
+ <div class="scan-line"></div>
95
+ </div>
96
+ </div>
97
+ <span class="cyber-error" id="passwordError"></span>
98
+ </div>
99
+
100
+ <div class="cyber-options">
101
+ <label class="neon-checkbox">
102
+ <input type="checkbox" id="remember" name="remember">
103
+ <span class="checkbox-matrix">
104
+ <div class="matrix-frame"></div>
105
+ <svg width="10" height="8" viewBox="0 0 10 8" fill="none">
106
+ <path d="M1 4l2.5 2.5L9 1" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
107
+ </svg>
108
+ </span>
109
+ <span class="checkbox-text">MAINTAIN_SESSION</span>
110
+ </label>
111
+ <a href="#" class="cyber-link">RECOVER_ACCESS</a>
112
+ </div>
113
+
114
+ <button type="submit" class="neon-button">
115
+ <div class="btn-matrix"></div>
116
+ <span class="btn-text">[ INITIALIZE_CONNECTION ]</span>
117
+ <div class="btn-loader">
118
+ <div class="matrix-loader">
119
+ <div class="matrix-bar"></div>
120
+ <div class="matrix-bar"></div>
121
+ <div class="matrix-bar"></div>
122
+ <div class="matrix-bar"></div>
123
+ </div>
124
+ </div>
125
+ <div class="btn-glow"></div>
126
+ </button>
127
+ </form>
128
+
129
+ <div class="cyber-divider">
130
+ <div class="divider-grid"></div>
131
+ <span class="divider-text">[ ALT_PROTOCOLS ]</span>
132
+ <div class="divider-grid"></div>
133
+ </div>
134
+
135
+ <div class="matrix-social">
136
+ <button type="button" class="social-matrix">
137
+ <div class="social-frame"></div>
138
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="#00ff41">
139
+ <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
140
+ </svg>
141
+ <span>GITHUB_NODE</span>
142
+ <div class="social-glow"></div>
143
+ </button>
144
+
145
+ <button type="button" class="social-matrix">
146
+ <div class="social-frame"></div>
147
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="#ff0080">
148
+ <path d="M7.12 0c3.94 0 7.12 3.18 7.12 7.12s-3.18 7.12-7.12 7.12S0 11.06 0 7.12C0 3.18 3.18 0 7.12 0zm1.8 5.56c.36 0 .68.14.92.38.24.24.38.56.38.92v3.28c0 .36-.14.68-.38.92-.24.24-.56.38-.92.38H5.64c-.36 0-.68-.14-.92-.38-.24-.24-.38-.56-.38-.92V6.86c0-.36.14-.68.38-.92.24-.24.56-.38.92-.38h3.28z"/>
149
+ </svg>
150
+ <span>DISCORD_NET</span>
151
+ <div class="social-glow"></div>
152
+ </button>
153
+ </div>
154
+
155
+ <div class="matrix-signup">
156
+ <span class="signup-prefix">[ NEW_USER_DETECTED ]</span>
157
+ <a href="#" class="matrix-link">CREATE_PROFILE</a>
158
+ </div>
159
+
160
+ <div class="cyber-success" id="successMessage">
161
+ <div class="success-matrix">
162
+ <div class="matrix-rings">
163
+ <div class="success-ring ring-1"></div>
164
+ <div class="success-ring ring-2"></div>
165
+ <div class="success-ring ring-3"></div>
166
+ </div>
167
+ <div class="success-core">
168
+ <svg width="32" height="32" viewBox="0 0 32 32" fill="none">
169
+ <path d="M10 16l6 6 12-12" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
170
+ </svg>
171
+ </div>
172
+ </div>
173
+ <h3 class="success-title">[ CONNECTION_ESTABLISHED ]</h3>
174
+ <p class="success-desc">Accessing neural interface...</p>
175
+ </div>
176
+ </div>
177
+ </div>
178
+ </div>
179
+
180
+ <script src="../../shared/js/form-utils.js"></script>
181
+ <script src="script.js"></script>
182
+ </body>
183
+ </html>
login/script.js ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Neon Cyber Login Form
2
+ class NeonCyberLoginForm extends FormUtils.LoginFormBase {
3
+ constructor() {
4
+ super({
5
+ submitButtonSelector: '.neon-button',
6
+ formGroupSelector: '.cyber-field',
7
+ cardSelector: '.cyber-terminal',
8
+ hideOnSuccess: ['.matrix-social', '.matrix-signup', '.cyber-divider'],
9
+ validators: {
10
+ email: (v) => {
11
+ if (!v) return { isValid: false, message: '[ ERROR: EMAIL_REQUIRED ]' };
12
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) return { isValid: false, message: '[ ERROR: INVALID_FORMAT ]' };
13
+ return { isValid: true };
14
+ },
15
+ password: (v) => {
16
+ if (!v) return { isValid: false, message: '[ ERROR: ACCESS_CODE_REQUIRED ]' };
17
+ if (v.length < 6) return { isValid: false, message: '[ ERROR: CODE_TOO_SHORT ]' };
18
+ return { isValid: true };
19
+ },
20
+ },
21
+ });
22
+ }
23
+
24
+ decorate() {
25
+ if (!document.getElementById('neon-cyber-keyframes')) {
26
+ const style = document.createElement('style');
27
+ style.id = 'neon-cyber-keyframes';
28
+ style.textContent = `
29
+ @keyframes textGlitch {
30
+ 0%, 100% { transform: translate(0); }
31
+ 20% { transform: translate(-2px, 1px); }
32
+ 40% { transform: translate(2px, -1px); }
33
+ 60% { transform: translate(-1px, 2px); }
34
+ 80% { transform: translate(1px, -2px); }
35
+ }
36
+ `;
37
+ document.head.appendChild(style);
38
+ }
39
+
40
+ // Cyber-scan effect on field focus
41
+ [this.form.querySelector('#email'), this.form.querySelector('#password')].forEach(input => {
42
+ if (!input) return;
43
+ input.setAttribute('placeholder', ' ');
44
+ input.addEventListener('focus', () => {
45
+ const scanner = input.closest('.cyber-field')?.querySelector('.cyber-scanner');
46
+ if (scanner) scanner.style.opacity = '1';
47
+ });
48
+ input.addEventListener('blur', () => {
49
+ const scanner = input.closest('.cyber-field')?.querySelector('.cyber-scanner');
50
+ if (scanner) scanner.style.opacity = '0.3';
51
+ });
52
+ });
53
+
54
+ // Random title glitch using requestAnimationFrame
55
+ const titleGlitch = document.querySelector('.title-glitch');
56
+ if (titleGlitch) {
57
+ let last = 0;
58
+ const tick = (now) => {
59
+ if (!document.body.contains(titleGlitch)) return;
60
+ if (now - last > 2000) {
61
+ last = now;
62
+ if (Math.random() < 0.1) {
63
+ titleGlitch.style.transform = `translate(${Math.random() * 4 - 2}px, ${Math.random() * 4 - 2}px)`;
64
+ titleGlitch.style.filter = `hue-rotate(${Math.random() * 360}deg)`;
65
+ setTimeout(() => {
66
+ titleGlitch.style.transform = '';
67
+ titleGlitch.style.filter = '';
68
+ }, 100);
69
+ }
70
+ }
71
+ requestAnimationFrame(tick);
72
+ };
73
+ requestAnimationFrame(tick);
74
+ }
75
+ }
76
+
77
+ onSuccess() {
78
+ this.form.style.transition = 'all 0.3s ease';
79
+ this.form.style.transform = 'scale(0.9)';
80
+ this.form.style.opacity = '0';
81
+ this.form.style.filter = 'blur(2px)';
82
+
83
+ setTimeout(() => {
84
+ this.form.style.display = 'none';
85
+ this.hideOnSuccess.forEach(sel => {
86
+ const el = document.querySelector(sel);
87
+ if (el) el.style.display = 'none';
88
+ });
89
+ this.successMessage?.classList.add('show');
90
+ setTimeout(() => {
91
+ const successTitle = document.querySelector('.success-title');
92
+ if (successTitle) {
93
+ successTitle.style.animation = 'textGlitch 0.5s ease-in-out';
94
+ successTitle.addEventListener('animationend', () => {
95
+ successTitle.style.animation = '';
96
+ }, { once: true });
97
+ }
98
+ }, 1500);
99
+ }, 300);
100
+ }
101
+ }
102
+
103
+ document.addEventListener('DOMContentLoaded', () => new NeonCyberLoginForm());
login/style.css ADDED
@@ -0,0 +1,979 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Neon Cyber Login Form - Complete & Self-Contained */
2
+
3
+ * {
4
+ margin: 0;
5
+ padding: 0;
6
+ box-sizing: border-box;
7
+ }
8
+
9
+ body {
10
+ font-family: 'Courier New', 'SF Mono', 'Monaco', 'Inconsolata', monospace;
11
+ background: #0a0a0a;
12
+ min-height: 100vh;
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ padding: 20px;
17
+ line-height: 1.4;
18
+ position: relative;
19
+ overflow: hidden;
20
+ }
21
+
22
+ /* Cyber Grid Background */
23
+ .cyber-grid {
24
+ position: fixed;
25
+ top: 0;
26
+ left: 0;
27
+ width: 100%;
28
+ height: 100%;
29
+ z-index: 0;
30
+ pointer-events: none;
31
+ }
32
+
33
+ .grid-line {
34
+ position: absolute;
35
+ background: linear-gradient(90deg, transparent, #00ff41, transparent);
36
+ opacity: 0.1;
37
+ animation: gridPulse 4s ease-in-out infinite;
38
+ }
39
+
40
+ .grid-h-1 {
41
+ top: 20%;
42
+ left: 0;
43
+ width: 100%;
44
+ height: 1px;
45
+ animation-delay: 0s;
46
+ }
47
+
48
+ .grid-h-2 {
49
+ top: 50%;
50
+ left: 0;
51
+ width: 100%;
52
+ height: 1px;
53
+ animation-delay: 1.5s;
54
+ }
55
+
56
+ .grid-h-3 {
57
+ top: 80%;
58
+ left: 0;
59
+ width: 100%;
60
+ height: 1px;
61
+ animation-delay: 3s;
62
+ }
63
+
64
+ .grid-v-1 {
65
+ top: 0;
66
+ left: 25%;
67
+ width: 1px;
68
+ height: 100%;
69
+ background: linear-gradient(0deg, transparent, #00ff41, transparent);
70
+ animation-delay: 0.75s;
71
+ }
72
+
73
+ .grid-v-2 {
74
+ top: 0;
75
+ left: 75%;
76
+ width: 1px;
77
+ height: 100%;
78
+ background: linear-gradient(0deg, transparent, #00ff41, transparent);
79
+ animation-delay: 2.25s;
80
+ }
81
+
82
+ @keyframes gridPulse {
83
+ 0%, 100% { opacity: 0.1; }
84
+ 50% { opacity: 0.3; }
85
+ }
86
+
87
+ .cyber-glitch {
88
+ position: absolute;
89
+ width: 200px;
90
+ height: 2px;
91
+ background: #ff0080;
92
+ opacity: 0;
93
+ animation: glitchFlash 6s ease-in-out infinite;
94
+ }
95
+
96
+ .glitch-1 {
97
+ top: 30%;
98
+ left: 10%;
99
+ animation-delay: 2s;
100
+ }
101
+
102
+ .glitch-2 {
103
+ top: 70%;
104
+ right: 10%;
105
+ animation-delay: 4s;
106
+ }
107
+
108
+ @keyframes glitchFlash {
109
+ 0%, 95%, 100% { opacity: 0; transform: scaleX(0); }
110
+ 96%, 99% { opacity: 0.8; transform: scaleX(1); }
111
+ }
112
+
113
+ .login-container {
114
+ width: 100%;
115
+ max-width: 450px;
116
+ position: relative;
117
+ z-index: 1;
118
+ }
119
+
120
+ .cyber-terminal {
121
+ background: rgba(0, 0, 0, 0.9);
122
+ border: 2px solid #00ff41;
123
+ border-radius: 8px;
124
+ overflow: hidden;
125
+ box-shadow: 0 0 30px rgba(0, 255, 65, 0.3), inset 0 0 0 1px rgba(0, 255, 65, 0.1);
126
+ position: relative;
127
+ }
128
+
129
+ .terminal-header {
130
+ background: linear-gradient(90deg, #1a1a1a, #2a2a2a);
131
+ padding: 12px 16px;
132
+ border-bottom: 1px solid #00ff41;
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: space-between;
136
+ }
137
+
138
+ .terminal-buttons {
139
+ display: flex;
140
+ gap: 8px;
141
+ }
142
+
143
+ .term-btn {
144
+ width: 12px;
145
+ height: 12px;
146
+ border-radius: 50%;
147
+ }
148
+
149
+ .btn-red {
150
+ background: #ff5555;
151
+ box-shadow: 0 0 8px rgba(255, 85, 85, 0.5);
152
+ }
153
+
154
+ .btn-yellow {
155
+ background: #ffff55;
156
+ box-shadow: 0 0 8px rgba(255, 255, 85, 0.5);
157
+ }
158
+
159
+ .btn-green {
160
+ background: #55ff55;
161
+ box-shadow: 0 0 8px rgba(85, 255, 85, 0.5);
162
+ }
163
+
164
+ .terminal-title {
165
+ color: #00ff41;
166
+ font-size: 12px;
167
+ font-weight: bold;
168
+ text-transform: uppercase;
169
+ letter-spacing: 1px;
170
+ }
171
+
172
+ .cyber-content {
173
+ padding: 40px 32px;
174
+ }
175
+
176
+ .neon-header {
177
+ text-align: center;
178
+ margin-bottom: 36px;
179
+ }
180
+
181
+ .cyber-logo {
182
+ position: relative;
183
+ width: 80px;
184
+ height: 80px;
185
+ margin: 0 auto 24px;
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
189
+ }
190
+
191
+ .logo-frame {
192
+ position: relative;
193
+ z-index: 2;
194
+ color: #00ff41;
195
+ border: 2px solid #00ff41;
196
+ width: 60px;
197
+ height: 60px;
198
+ display: flex;
199
+ align-items: center;
200
+ justify-content: center;
201
+ background: rgba(0, 255, 65, 0.05);
202
+ animation: logoScan 3s ease-in-out infinite;
203
+ }
204
+
205
+ @keyframes logoScan {
206
+ 0%, 100% {
207
+ border-color: #00ff41;
208
+ box-shadow: 0 0 10px rgba(0, 255, 65, 0.3);
209
+ }
210
+ 50% {
211
+ border-color: #ff0080;
212
+ box-shadow: 0 0 15px rgba(255, 0, 128, 0.5);
213
+ }
214
+ }
215
+
216
+ .logo-scanner {
217
+ position: absolute;
218
+ top: 0;
219
+ left: -100%;
220
+ width: 100%;
221
+ height: 100%;
222
+ background: linear-gradient(90deg, transparent, rgba(0, 255, 65, 0.6), transparent);
223
+ animation: scanLine 2s linear infinite;
224
+ }
225
+
226
+ @keyframes scanLine {
227
+ 0% { left: -100%; }
228
+ 100% { left: 100%; }
229
+ }
230
+
231
+ .neon-glow {
232
+ position: absolute;
233
+ top: 0;
234
+ left: 0;
235
+ width: 100%;
236
+ height: 100%;
237
+ background: radial-gradient(circle, rgba(0, 255, 65, 0.2) 0%, transparent 70%);
238
+ animation: neonPulse 2s ease-in-out infinite;
239
+ }
240
+
241
+ @keyframes neonPulse {
242
+ 0%, 100% { transform: scale(1); opacity: 0.6; }
243
+ 50% { transform: scale(1.2); opacity: 0.8; }
244
+ }
245
+
246
+ .cyber-title {
247
+ color: #00ff41;
248
+ font-size: 1.75rem;
249
+ font-weight: bold;
250
+ margin-bottom: 8px;
251
+ text-transform: uppercase;
252
+ letter-spacing: 2px;
253
+ position: relative;
254
+ }
255
+
256
+ .title-glitch {
257
+ position: relative;
258
+ display: inline-block;
259
+ animation: textGlitch 4s ease-in-out infinite;
260
+ }
261
+
262
+ @keyframes textGlitch {
263
+ 0%, 90%, 100% {
264
+ transform: translate(0);
265
+ filter: hue-rotate(0deg);
266
+ }
267
+ 91%, 95% {
268
+ transform: translate(-2px, 1px);
269
+ filter: hue-rotate(90deg);
270
+ }
271
+ 96%, 99% {
272
+ transform: translate(1px, -1px);
273
+ filter: hue-rotate(180deg);
274
+ }
275
+ }
276
+
277
+ .access-text {
278
+ color: #ff0080;
279
+ font-size: 13px;
280
+ text-transform: uppercase;
281
+ letter-spacing: 1px;
282
+ }
283
+
284
+ /* Cyber Form Fields */
285
+ .cyber-field {
286
+ position: relative;
287
+ margin-bottom: 28px;
288
+ }
289
+
290
+ .field-frame {
291
+ position: relative;
292
+ background: rgba(0, 0, 0, 0.8);
293
+ border: 1px solid rgba(0, 255, 65, 0.3);
294
+ border-radius: 4px;
295
+ overflow: hidden;
296
+ }
297
+
298
+ .field-border {
299
+ position: absolute;
300
+ top: 0;
301
+ left: 0;
302
+ right: 0;
303
+ bottom: 0;
304
+ border: 1px solid transparent;
305
+ border-radius: 4px;
306
+ background: linear-gradient(45deg, #00ff41, #ff0080) border-box;
307
+ -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
308
+ -webkit-mask-composite: destination-out;
309
+ mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
310
+ mask-composite: exclude;
311
+ opacity: 0;
312
+ transition: opacity 0.3s ease;
313
+ }
314
+
315
+ .cyber-field input {
316
+ width: 100%;
317
+ background: transparent;
318
+ border: none;
319
+ padding: 16px 60px 16px 16px;
320
+ color: #00ff41;
321
+ font-size: 14px;
322
+ font-weight: bold;
323
+ outline: none;
324
+ position: relative;
325
+ z-index: 2;
326
+ font-family: inherit;
327
+ text-transform: uppercase;
328
+ letter-spacing: 1px;
329
+ }
330
+
331
+ .cyber-field input::placeholder {
332
+ color: transparent;
333
+ }
334
+
335
+ .cyber-field label {
336
+ position: absolute;
337
+ left: 16px;
338
+ top: 50%;
339
+ transform: translateY(-50%);
340
+ color: rgba(0, 255, 65, 0.6);
341
+ font-size: 14px;
342
+ font-weight: bold;
343
+ pointer-events: none;
344
+ transition: all 0.3s ease;
345
+ z-index: 3;
346
+ text-transform: uppercase;
347
+ letter-spacing: 1px;
348
+ }
349
+
350
+ .cyber-field input:focus + label,
351
+ .cyber-field input:not(:placeholder-shown) + label {
352
+ top: 8px;
353
+ font-size: 10px;
354
+ color: #00ff41;
355
+ transform: translateY(0);
356
+ }
357
+
358
+ .cyber-field input:focus ~ .field-border {
359
+ opacity: 1;
360
+ }
361
+
362
+ .cyber-scanner {
363
+ position: absolute;
364
+ top: 0;
365
+ left: 0;
366
+ width: 100%;
367
+ height: 100%;
368
+ pointer-events: none;
369
+ z-index: 1;
370
+ }
371
+
372
+ .scan-line {
373
+ position: absolute;
374
+ top: 0;
375
+ left: -100%;
376
+ width: 100%;
377
+ height: 100%;
378
+ background: linear-gradient(90deg, transparent, rgba(0, 255, 65, 0.3), transparent);
379
+ transition: left 0.5s ease;
380
+ }
381
+
382
+ .cyber-field input:focus ~ .cyber-scanner .scan-line {
383
+ left: 100%;
384
+ animation: continuousScan 2s linear infinite;
385
+ }
386
+
387
+ @keyframes continuousScan {
388
+ 0% { left: -100%; }
389
+ 100% { left: 100%; }
390
+ }
391
+
392
+ /* Cyber Toggle */
393
+ .cyber-field:has(.cyber-toggle) input {
394
+ padding-right: 100px;
395
+ }
396
+
397
+ .cyber-toggle {
398
+ position: absolute;
399
+ right: 16px;
400
+ top: 50%;
401
+ transform: translateY(-50%);
402
+ background: none;
403
+ border: none;
404
+ cursor: pointer;
405
+ z-index: 4;
406
+ padding: 4px;
407
+ }
408
+
409
+ .toggle-frame {
410
+ width: 24px;
411
+ height: 24px;
412
+ border: 1px solid rgba(0, 255, 65, 0.5);
413
+ display: flex;
414
+ align-items: center;
415
+ justify-content: center;
416
+ color: #00ff41;
417
+ transition: all 0.3s ease;
418
+ background: rgba(0, 0, 0, 0.8);
419
+ }
420
+
421
+ .cyber-toggle:hover .toggle-frame {
422
+ border-color: #00ff41;
423
+ box-shadow: 0 0 8px rgba(0, 255, 65, 0.3);
424
+ }
425
+
426
+ .eye-blocked {
427
+ display: none;
428
+ }
429
+
430
+ .cyber-toggle.toggle-active .eye-scan {
431
+ display: none;
432
+ }
433
+
434
+ .cyber-toggle.toggle-active .eye-blocked {
435
+ display: block;
436
+ }
437
+
438
+ /* Cyber Options */
439
+ .cyber-options {
440
+ display: flex;
441
+ justify-content: space-between;
442
+ align-items: center;
443
+ margin-bottom: 32px;
444
+ flex-wrap: wrap;
445
+ gap: 16px;
446
+ }
447
+
448
+ .neon-checkbox {
449
+ display: flex;
450
+ align-items: center;
451
+ cursor: pointer;
452
+ font-size: 12px;
453
+ color: #00ff41;
454
+ font-weight: bold;
455
+ text-transform: uppercase;
456
+ letter-spacing: 1px;
457
+ }
458
+
459
+ .neon-checkbox input[type="checkbox"] {
460
+ display: none;
461
+ }
462
+
463
+ .checkbox-matrix {
464
+ width: 20px;
465
+ height: 20px;
466
+ margin-right: 12px;
467
+ position: relative;
468
+ display: flex;
469
+ align-items: center;
470
+ justify-content: center;
471
+ }
472
+
473
+ .matrix-frame {
474
+ width: 100%;
475
+ height: 100%;
476
+ border: 1px solid rgba(0, 255, 65, 0.5);
477
+ background: rgba(0, 0, 0, 0.8);
478
+ transition: all 0.3s ease;
479
+ position: absolute;
480
+ }
481
+
482
+ .checkbox-matrix svg {
483
+ color: transparent;
484
+ transition: color 0.3s ease;
485
+ position: relative;
486
+ z-index: 1;
487
+ }
488
+
489
+ .neon-checkbox input[type="checkbox"]:checked + .checkbox-matrix .matrix-frame {
490
+ background: rgba(0, 255, 65, 0.2);
491
+ border-color: #00ff41;
492
+ box-shadow: 0 0 8px rgba(0, 255, 65, 0.3);
493
+ }
494
+
495
+ .neon-checkbox input[type="checkbox"]:checked + .checkbox-matrix svg {
496
+ color: #00ff41;
497
+ }
498
+
499
+ .cyber-link {
500
+ color: #ff0080;
501
+ text-decoration: none;
502
+ font-size: 12px;
503
+ font-weight: bold;
504
+ text-transform: uppercase;
505
+ letter-spacing: 1px;
506
+ transition: all 0.3s ease;
507
+ position: relative;
508
+ }
509
+
510
+ .cyber-link::after {
511
+ content: '';
512
+ position: absolute;
513
+ bottom: -2px;
514
+ left: 0;
515
+ width: 0;
516
+ height: 1px;
517
+ background: #ff0080;
518
+ transition: width 0.3s ease;
519
+ }
520
+
521
+ .cyber-link:hover::after {
522
+ width: 100%;
523
+ }
524
+
525
+ .cyber-link:hover {
526
+ color: #ff4da6;
527
+ text-shadow: 0 0 5px rgba(255, 0, 128, 0.5);
528
+ }
529
+
530
+ /* Neon Button */
531
+ .neon-button {
532
+ width: 100%;
533
+ background: transparent;
534
+ color: #00ff41;
535
+ border: 2px solid #00ff41;
536
+ border-radius: 4px;
537
+ padding: 0;
538
+ cursor: pointer;
539
+ font-family: inherit;
540
+ font-size: 14px;
541
+ font-weight: bold;
542
+ position: relative;
543
+ margin-bottom: 32px;
544
+ overflow: hidden;
545
+ min-height: 50px;
546
+ display: flex;
547
+ align-items: center;
548
+ justify-content: center;
549
+ text-transform: uppercase;
550
+ letter-spacing: 1px;
551
+ transition: all 0.3s ease;
552
+ }
553
+
554
+ .btn-matrix {
555
+ position: absolute;
556
+ top: 0;
557
+ left: 0;
558
+ right: 0;
559
+ bottom: 0;
560
+ background: rgba(0, 0, 0, 0.9);
561
+ transition: all 0.3s ease;
562
+ }
563
+
564
+ .neon-button:hover {
565
+ border-color: #ff0080;
566
+ color: #ff0080;
567
+ box-shadow: 0 0 15px rgba(255, 0, 128, 0.5);
568
+ }
569
+
570
+ .neon-button:hover .btn-matrix {
571
+ background: rgba(255, 0, 128, 0.1);
572
+ }
573
+
574
+ .neon-button:active {
575
+ transform: scale(0.98);
576
+ }
577
+
578
+ .btn-text {
579
+ position: relative;
580
+ z-index: 2;
581
+ transition: opacity 0.3s ease;
582
+ }
583
+
584
+ .btn-loader {
585
+ position: absolute;
586
+ z-index: 2;
587
+ opacity: 0;
588
+ transition: opacity 0.3s ease;
589
+ }
590
+
591
+ .matrix-loader {
592
+ display: flex;
593
+ gap: 4px;
594
+ }
595
+
596
+ .matrix-bar {
597
+ width: 3px;
598
+ height: 16px;
599
+ background: #00ff41;
600
+ animation: matrixPulse 1.2s ease-in-out infinite;
601
+ }
602
+
603
+ .matrix-bar:nth-child(2) { animation-delay: 0.1s; }
604
+ .matrix-bar:nth-child(3) { animation-delay: 0.2s; }
605
+ .matrix-bar:nth-child(4) { animation-delay: 0.3s; }
606
+
607
+ @keyframes matrixPulse {
608
+ 0%, 80%, 100% { transform: scaleY(0.5); opacity: 0.5; }
609
+ 40% { transform: scaleY(1); opacity: 1; }
610
+ }
611
+
612
+ .neon-button.loading .btn-text {
613
+ opacity: 0;
614
+ }
615
+
616
+ .neon-button.loading .btn-loader {
617
+ opacity: 1;
618
+ }
619
+
620
+ .btn-glow {
621
+ position: absolute;
622
+ top: -2px;
623
+ left: -2px;
624
+ right: -2px;
625
+ bottom: -2px;
626
+ background: #00ff41;
627
+ border-radius: 6px;
628
+ opacity: 0;
629
+ filter: blur(8px);
630
+ transition: opacity 0.3s ease;
631
+ z-index: -1;
632
+ }
633
+
634
+ .neon-button:hover .btn-glow {
635
+ opacity: 0.3;
636
+ }
637
+
638
+ /* Cyber Divider */
639
+ .cyber-divider {
640
+ display: flex;
641
+ align-items: center;
642
+ margin: 32px 0;
643
+ gap: 16px;
644
+ }
645
+
646
+ .divider-grid {
647
+ flex: 1;
648
+ height: 1px;
649
+ background: linear-gradient(90deg, transparent, rgba(0, 255, 65, 0.3), transparent);
650
+ position: relative;
651
+ overflow: hidden;
652
+ }
653
+
654
+ .divider-grid::after {
655
+ content: '';
656
+ position: absolute;
657
+ top: 0;
658
+ left: -100%;
659
+ width: 100%;
660
+ height: 100%;
661
+ background: linear-gradient(90deg, transparent, #00ff41, transparent);
662
+ animation: dividerScan 3s linear infinite;
663
+ }
664
+
665
+ @keyframes dividerScan {
666
+ 0% { left: -100%; }
667
+ 100% { left: 100%; }
668
+ }
669
+
670
+ .divider-text {
671
+ color: rgba(0, 255, 65, 0.7);
672
+ font-size: 11px;
673
+ font-weight: bold;
674
+ text-transform: uppercase;
675
+ letter-spacing: 1px;
676
+ }
677
+
678
+ /* Matrix Social */
679
+ .matrix-social {
680
+ display: flex;
681
+ gap: 12px;
682
+ margin-bottom: 32px;
683
+ }
684
+
685
+ .social-matrix {
686
+ flex: 1;
687
+ background: transparent;
688
+ color: #00ff41;
689
+ border: 1px solid rgba(0, 255, 65, 0.3);
690
+ border-radius: 4px;
691
+ padding: 12px 16px;
692
+ cursor: pointer;
693
+ font-family: inherit;
694
+ font-size: 11px;
695
+ font-weight: bold;
696
+ display: flex;
697
+ align-items: center;
698
+ justify-content: center;
699
+ gap: 8px;
700
+ transition: all 0.3s ease;
701
+ min-height: 44px;
702
+ position: relative;
703
+ overflow: hidden;
704
+ text-transform: uppercase;
705
+ letter-spacing: 1px;
706
+ }
707
+
708
+ .social-frame {
709
+ position: absolute;
710
+ top: 0;
711
+ left: 0;
712
+ right: 0;
713
+ bottom: 0;
714
+ background: rgba(0, 0, 0, 0.9);
715
+ transition: all 0.3s ease;
716
+ }
717
+
718
+ .social-matrix:hover {
719
+ border-color: #00ff41;
720
+ box-shadow: 0 0 10px rgba(0, 255, 65, 0.3);
721
+ }
722
+
723
+ .social-matrix:hover .social-frame {
724
+ background: rgba(0, 255, 65, 0.1);
725
+ }
726
+
727
+ .social-matrix span,
728
+ .social-matrix svg {
729
+ position: relative;
730
+ z-index: 2;
731
+ }
732
+
733
+ .social-glow {
734
+ position: absolute;
735
+ top: -1px;
736
+ left: -1px;
737
+ right: -1px;
738
+ bottom: -1px;
739
+ background: rgba(0, 255, 65, 0.2);
740
+ border-radius: 5px;
741
+ opacity: 0;
742
+ filter: blur(4px);
743
+ transition: opacity 0.3s ease;
744
+ z-index: 0;
745
+ }
746
+
747
+ .social-matrix:hover .social-glow {
748
+ opacity: 1;
749
+ }
750
+
751
+ /* Matrix Signup */
752
+ .matrix-signup {
753
+ text-align: center;
754
+ font-size: 12px;
755
+ color: rgba(0, 255, 65, 0.7);
756
+ text-transform: uppercase;
757
+ letter-spacing: 1px;
758
+ }
759
+
760
+ .matrix-link {
761
+ color: #ff0080;
762
+ text-decoration: none;
763
+ font-weight: bold;
764
+ transition: all 0.3s ease;
765
+ position: relative;
766
+ }
767
+
768
+ .matrix-link::after {
769
+ content: '';
770
+ position: absolute;
771
+ bottom: -2px;
772
+ left: 0;
773
+ width: 0;
774
+ height: 1px;
775
+ background: #ff0080;
776
+ transition: width 0.3s ease;
777
+ }
778
+
779
+ .matrix-link:hover::after {
780
+ width: 100%;
781
+ }
782
+
783
+ .matrix-link:hover {
784
+ color: #ff4da6;
785
+ text-shadow: 0 0 5px rgba(255, 0, 128, 0.5);
786
+ }
787
+
788
+ /* Cyber Error */
789
+ .cyber-error {
790
+ color: #ff0080;
791
+ font-size: 11px;
792
+ font-weight: bold;
793
+ margin-top: 6px;
794
+ opacity: 0;
795
+ transform: translateY(-4px);
796
+ transition: all 0.3s ease;
797
+ position: relative;
798
+ z-index: 5;
799
+ text-transform: uppercase;
800
+ letter-spacing: 1px;
801
+ }
802
+
803
+ .cyber-error.show {
804
+ opacity: 1;
805
+ transform: translateY(0);
806
+ }
807
+
808
+ .cyber-field.error .field-frame {
809
+ border-color: #ff0080;
810
+ }
811
+
812
+ .cyber-field.error .field-border {
813
+ opacity: 1;
814
+ }
815
+
816
+ .cyber-field.error label {
817
+ color: #ff0080;
818
+ }
819
+
820
+ /* Cyber Success */
821
+ .cyber-success {
822
+ display: none;
823
+ text-align: center;
824
+ padding: 40px 20px;
825
+ opacity: 0;
826
+ transform: translateY(20px);
827
+ transition: all 0.4s ease;
828
+ }
829
+
830
+ .cyber-success.show {
831
+ display: block;
832
+ opacity: 1;
833
+ transform: translateY(0);
834
+ }
835
+
836
+ .success-matrix {
837
+ position: relative;
838
+ width: 100px;
839
+ height: 100px;
840
+ margin: 0 auto 24px;
841
+ display: flex;
842
+ align-items: center;
843
+ justify-content: center;
844
+ }
845
+
846
+ .matrix-rings {
847
+ position: absolute;
848
+ top: 0;
849
+ left: 0;
850
+ width: 100%;
851
+ height: 100%;
852
+ }
853
+
854
+ .success-ring {
855
+ position: absolute;
856
+ border: 2px solid #00ff41;
857
+ border-radius: 50%;
858
+ animation: matrixExpand 1.5s ease-out forwards;
859
+ opacity: 0;
860
+ }
861
+
862
+ .ring-1 {
863
+ width: 60px;
864
+ height: 60px;
865
+ top: 20px;
866
+ left: 20px;
867
+ animation-delay: 0s;
868
+ }
869
+
870
+ .ring-2 {
871
+ width: 80px;
872
+ height: 80px;
873
+ top: 10px;
874
+ left: 10px;
875
+ animation-delay: 0.3s;
876
+ }
877
+
878
+ .ring-3 {
879
+ width: 100px;
880
+ height: 100px;
881
+ top: 0;
882
+ left: 0;
883
+ animation-delay: 0.6s;
884
+ }
885
+
886
+ @keyframes matrixExpand {
887
+ 0% { opacity: 0; transform: scale(0); }
888
+ 50% { opacity: 1; transform: scale(1.1); }
889
+ 100% { opacity: 0.8; transform: scale(1); }
890
+ }
891
+
892
+ .success-core {
893
+ position: relative;
894
+ z-index: 2;
895
+ color: #00ff41;
896
+ animation: coreActivate 0.8s ease-out 0.9s forwards;
897
+ opacity: 0;
898
+ }
899
+
900
+ @keyframes coreActivate {
901
+ 0% { opacity: 0; transform: scale(0); }
902
+ 100% { opacity: 1; transform: scale(1); }
903
+ }
904
+
905
+ .success-title {
906
+ color: #00ff41;
907
+ font-size: 1.25rem;
908
+ font-weight: bold;
909
+ margin-bottom: 8px;
910
+ text-transform: uppercase;
911
+ letter-spacing: 2px;
912
+ }
913
+
914
+ .success-desc {
915
+ color: rgba(0, 255, 65, 0.7);
916
+ font-size: 12px;
917
+ text-transform: uppercase;
918
+ letter-spacing: 1px;
919
+ }
920
+
921
+ /* Mobile Responsive */
922
+ @media (max-width: 480px) {
923
+ body {
924
+ padding: 16px;
925
+ }
926
+
927
+ .cyber-terminal {
928
+ border-radius: 4px;
929
+ }
930
+
931
+ .cyber-content {
932
+ padding: 32px 24px;
933
+ }
934
+
935
+ .cyber-title {
936
+ font-size: 1.5rem;
937
+ }
938
+
939
+ .cyber-logo {
940
+ width: 60px;
941
+ height: 60px;
942
+ }
943
+
944
+ .logo-frame {
945
+ width: 50px;
946
+ height: 50px;
947
+ }
948
+
949
+ .cyber-options {
950
+ flex-direction: column;
951
+ align-items: flex-start;
952
+ gap: 16px;
953
+ }
954
+
955
+ .matrix-social {
956
+ flex-direction: column;
957
+ }
958
+
959
+ .grid-line {
960
+ opacity: 0.05;
961
+ }
962
+ }
963
+ /* === Accessibility: keyboard focus indicators === */
964
+ /* Restores visible focus rings for keyboard users without affecting mouse interaction. */
965
+ :focus-visible {
966
+ outline: 2px solid currentColor;
967
+ outline-offset: 2px;
968
+ border-radius: 4px;
969
+ }
970
+
971
+ /* Reduced motion: respect user preference. Animations defined per form will tone down. */
972
+ @media (prefers-reduced-motion: reduce) {
973
+ *, *::before, *::after {
974
+ animation-duration: 0.01ms !important;
975
+ animation-iteration-count: 1 !important;
976
+ transition-duration: 0.01ms !important;
977
+ scroll-behavior: auto !important;
978
+ }
979
+ }
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ Flask==3.0.3
2
+ numpy==1.26.4
3
+ Pillow==10.4.0
4
+ tensorflow==2.16.1
5
+ Werkzeug==3.0.3
static/css/app.css ADDED
@@ -0,0 +1,680 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --bg: #090d10;
3
+ --panel: rgba(9, 16, 18, 0.92);
4
+ --panel-strong: #10191d;
5
+ --line: rgba(89, 255, 177, 0.24);
6
+ --text: #ecfff7;
7
+ --muted: #9bb6ac;
8
+ --green: #35f28c;
9
+ --pink: #ff4f9a;
10
+ --amber: #ffd166;
11
+ --blue: #54b7ff;
12
+ --danger: #ff5b6e;
13
+ }
14
+
15
+ * {
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ body {
20
+ margin: 0;
21
+ min-height: 100vh;
22
+ color: var(--text);
23
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
24
+ background:
25
+ radial-gradient(circle at 12% 12%, rgba(53, 242, 140, 0.14), transparent 28%),
26
+ radial-gradient(circle at 88% 18%, rgba(255, 79, 154, 0.11), transparent 30%),
27
+ linear-gradient(135deg, #080a0c, #10191d 48%, #080d10);
28
+ }
29
+
30
+ a {
31
+ color: inherit;
32
+ text-decoration: none;
33
+ }
34
+
35
+ code {
36
+ color: var(--green);
37
+ }
38
+
39
+ .road-grid {
40
+ position: fixed;
41
+ inset: 0;
42
+ pointer-events: none;
43
+ opacity: 0.45;
44
+ background-image:
45
+ linear-gradient(rgba(53, 242, 140, 0.08) 1px, transparent 1px),
46
+ linear-gradient(90deg, rgba(84, 183, 255, 0.07) 1px, transparent 1px);
47
+ background-size: 64px 64px;
48
+ mask-image: linear-gradient(to bottom, black, transparent 78%);
49
+ }
50
+
51
+ .road-grid span {
52
+ position: absolute;
53
+ left: 50%;
54
+ width: 2px;
55
+ height: 100%;
56
+ background: linear-gradient(to bottom, transparent, rgba(255, 209, 102, 0.5), transparent);
57
+ transform: perspective(400px) rotateX(58deg) translateX(-50%);
58
+ }
59
+
60
+ .road-grid span:nth-child(2) {
61
+ left: 22%;
62
+ }
63
+
64
+ .road-grid span:nth-child(3) {
65
+ left: 78%;
66
+ }
67
+
68
+ .topbar {
69
+ position: sticky;
70
+ top: 0;
71
+ z-index: 5;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: space-between;
75
+ gap: 20px;
76
+ padding: 18px clamp(18px, 4vw, 56px);
77
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
78
+ background: rgba(8, 12, 14, 0.82);
79
+ backdrop-filter: blur(14px);
80
+ }
81
+
82
+ .brand,
83
+ .nav {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: 12px;
87
+ }
88
+
89
+ .brand {
90
+ font-weight: 800;
91
+ letter-spacing: 0.2px;
92
+ }
93
+
94
+ .brand-mark {
95
+ display: inline-grid;
96
+ width: 38px;
97
+ height: 38px;
98
+ place-items: center;
99
+ border: 1px solid var(--green);
100
+ border-radius: 8px;
101
+ color: var(--green);
102
+ box-shadow: 0 0 18px rgba(53, 242, 140, 0.24);
103
+ font-family: "Courier New", monospace;
104
+ }
105
+
106
+ .nav a {
107
+ color: var(--muted);
108
+ font-size: 0.95rem;
109
+ }
110
+
111
+ .nav a:hover,
112
+ .nav .nav-cta {
113
+ color: var(--text);
114
+ }
115
+
116
+ .nav-cta {
117
+ border: 1px solid var(--line);
118
+ border-radius: 8px;
119
+ padding: 9px 12px;
120
+ }
121
+
122
+ main {
123
+ position: relative;
124
+ z-index: 1;
125
+ width: min(1160px, calc(100% - 32px));
126
+ margin: 0 auto;
127
+ padding: 42px 0 64px;
128
+ }
129
+
130
+ .flash-stack {
131
+ display: grid;
132
+ gap: 10px;
133
+ margin-bottom: 20px;
134
+ }
135
+
136
+ .flash {
137
+ border: 1px solid var(--line);
138
+ border-radius: 8px;
139
+ padding: 12px 14px;
140
+ background: rgba(16, 25, 29, 0.9);
141
+ color: var(--text);
142
+ }
143
+
144
+ .flash.danger {
145
+ border-color: rgba(255, 91, 110, 0.55);
146
+ }
147
+
148
+ .flash.success {
149
+ border-color: rgba(53, 242, 140, 0.55);
150
+ }
151
+
152
+ .hero {
153
+ display: grid;
154
+ grid-template-columns: minmax(0, 1.08fr) minmax(320px, 0.92fr);
155
+ align-items: center;
156
+ gap: clamp(28px, 5vw, 72px);
157
+ min-height: calc(100vh - 170px);
158
+ }
159
+
160
+ .eyebrow {
161
+ margin: 0 0 12px;
162
+ color: var(--green);
163
+ font-family: "Courier New", monospace;
164
+ font-size: 0.83rem;
165
+ font-weight: 700;
166
+ letter-spacing: 1.6px;
167
+ text-transform: uppercase;
168
+ }
169
+
170
+ h1,
171
+ h2,
172
+ p {
173
+ margin-top: 0;
174
+ }
175
+
176
+ h1 {
177
+ max-width: 780px;
178
+ margin-bottom: 18px;
179
+ font-size: clamp(2.4rem, 7vw, 5.8rem);
180
+ line-height: 0.96;
181
+ letter-spacing: 0;
182
+ }
183
+
184
+ h2 {
185
+ margin-bottom: 10px;
186
+ }
187
+
188
+ .lead,
189
+ .panel-copy {
190
+ color: var(--muted);
191
+ font-size: 1.08rem;
192
+ line-height: 1.7;
193
+ }
194
+
195
+ .hero-actions,
196
+ .feedback-row,
197
+ .section-heading,
198
+ .dashboard-head {
199
+ display: flex;
200
+ align-items: center;
201
+ gap: 12px;
202
+ flex-wrap: wrap;
203
+ }
204
+
205
+ .button,
206
+ .feedback,
207
+ .neon-button {
208
+ border: 0;
209
+ border-radius: 8px;
210
+ padding: 12px 16px;
211
+ font-weight: 800;
212
+ cursor: pointer;
213
+ }
214
+
215
+ .button.primary {
216
+ background: var(--green);
217
+ color: #04100a;
218
+ }
219
+
220
+ .button.secondary {
221
+ border: 1px solid var(--line);
222
+ background: rgba(255, 255, 255, 0.04);
223
+ color: var(--text);
224
+ }
225
+
226
+ .signal-panel,
227
+ .tool-panel,
228
+ .result-panel,
229
+ .table-panel,
230
+ .cyber-terminal,
231
+ .stats-grid article,
232
+ .history-card,
233
+ .feature-band article {
234
+ border: 1px solid var(--line);
235
+ border-radius: 8px;
236
+ background: var(--panel);
237
+ box-shadow: 0 24px 80px rgba(0, 0, 0, 0.28);
238
+ }
239
+
240
+ .signal-head,
241
+ .terminal-header {
242
+ display: flex;
243
+ align-items: center;
244
+ gap: 8px;
245
+ padding: 12px 16px;
246
+ border-bottom: 1px solid var(--line);
247
+ color: var(--muted);
248
+ font-family: "Courier New", monospace;
249
+ font-size: 0.8rem;
250
+ }
251
+
252
+ .dot,
253
+ .term-btn {
254
+ width: 11px;
255
+ height: 11px;
256
+ border-radius: 50%;
257
+ }
258
+
259
+ .red,
260
+ .btn-red {
261
+ background: var(--danger);
262
+ }
263
+
264
+ .amber,
265
+ .btn-yellow {
266
+ background: var(--amber);
267
+ }
268
+
269
+ .green,
270
+ .btn-green {
271
+ background: var(--green);
272
+ }
273
+
274
+ .signal-body {
275
+ display: grid;
276
+ gap: 14px;
277
+ padding: 22px;
278
+ }
279
+
280
+ .workflow-step {
281
+ display: grid;
282
+ grid-template-columns: 48px 1fr;
283
+ gap: 14px;
284
+ align-items: center;
285
+ }
286
+
287
+ .workflow-step span {
288
+ display: grid;
289
+ height: 48px;
290
+ place-items: center;
291
+ border: 1px solid rgba(255, 209, 102, 0.45);
292
+ border-radius: 8px;
293
+ color: var(--amber);
294
+ font-family: "Courier New", monospace;
295
+ }
296
+
297
+ .workflow-step p,
298
+ .feature-band p,
299
+ .empty,
300
+ small {
301
+ margin: 0;
302
+ color: var(--muted);
303
+ }
304
+
305
+ .feature-band {
306
+ display: grid;
307
+ grid-template-columns: repeat(3, 1fr);
308
+ gap: 16px;
309
+ margin-top: -18px;
310
+ }
311
+
312
+ .feature-band article,
313
+ .stats-grid article,
314
+ .history-card {
315
+ padding: 18px;
316
+ }
317
+
318
+ .auth-shell {
319
+ display: grid;
320
+ min-height: calc(100vh - 170px);
321
+ place-items: center;
322
+ }
323
+
324
+ .cyber-terminal {
325
+ width: min(460px, 100%);
326
+ overflow: hidden;
327
+ }
328
+
329
+ .terminal-buttons {
330
+ display: flex;
331
+ gap: 8px;
332
+ }
333
+
334
+ .terminal-title,
335
+ .access-text,
336
+ .matrix-signup {
337
+ color: var(--green);
338
+ font-family: "Courier New", monospace;
339
+ letter-spacing: 1px;
340
+ text-transform: uppercase;
341
+ }
342
+
343
+ .cyber-content {
344
+ padding: 32px;
345
+ }
346
+
347
+ .neon-header {
348
+ text-align: center;
349
+ }
350
+
351
+ .cyber-logo {
352
+ position: relative;
353
+ display: grid;
354
+ width: 78px;
355
+ height: 78px;
356
+ margin: 0 auto 20px;
357
+ place-items: center;
358
+ }
359
+
360
+ .logo-frame {
361
+ position: relative;
362
+ display: grid;
363
+ width: 58px;
364
+ height: 58px;
365
+ place-items: center;
366
+ overflow: hidden;
367
+ border: 2px solid var(--green);
368
+ border-radius: 8px;
369
+ color: var(--green);
370
+ font-weight: 900;
371
+ box-shadow: 0 0 18px rgba(53, 242, 140, 0.28);
372
+ }
373
+
374
+ .logo-scanner {
375
+ position: absolute;
376
+ inset: 0;
377
+ transform: translateX(-100%);
378
+ background: linear-gradient(90deg, transparent, rgba(53, 242, 140, 0.5), transparent);
379
+ animation: scan 2.8s linear infinite;
380
+ }
381
+
382
+ .neon-glow {
383
+ position: absolute;
384
+ inset: 0;
385
+ border-radius: 50%;
386
+ background: rgba(53, 242, 140, 0.14);
387
+ filter: blur(16px);
388
+ }
389
+
390
+ @keyframes scan {
391
+ to {
392
+ transform: translateX(100%);
393
+ }
394
+ }
395
+
396
+ .cyber-title {
397
+ font-size: 2rem;
398
+ line-height: 1.05;
399
+ }
400
+
401
+ .neon-form {
402
+ display: grid;
403
+ gap: 16px;
404
+ margin-top: 28px;
405
+ }
406
+
407
+ .cyber-field {
408
+ display: grid;
409
+ gap: 8px;
410
+ color: var(--muted);
411
+ font-size: 0.82rem;
412
+ font-weight: 800;
413
+ letter-spacing: 1px;
414
+ text-transform: uppercase;
415
+ }
416
+
417
+ .cyber-field input,
418
+ .upload-box,
419
+ table {
420
+ width: 100%;
421
+ }
422
+
423
+ .cyber-field input,
424
+ .upload-box {
425
+ border: 1px solid var(--line);
426
+ border-radius: 8px;
427
+ padding: 14px;
428
+ background: rgba(0, 0, 0, 0.35);
429
+ color: var(--text);
430
+ }
431
+
432
+ .neon-button {
433
+ margin-top: 8px;
434
+ border: 2px solid var(--green);
435
+ background: rgba(53, 242, 140, 0.08);
436
+ color: var(--green);
437
+ font-family: "Courier New", monospace;
438
+ letter-spacing: 1px;
439
+ }
440
+
441
+ .matrix-signup {
442
+ margin-top: 22px;
443
+ text-align: center;
444
+ font-size: 0.78rem;
445
+ }
446
+
447
+ .matrix-signup a {
448
+ color: var(--pink);
449
+ font-weight: 900;
450
+ }
451
+
452
+ .page-grid {
453
+ display: grid;
454
+ grid-template-columns: minmax(0, 1fr) 380px;
455
+ gap: 20px;
456
+ align-items: start;
457
+ }
458
+
459
+ .tool-panel,
460
+ .result-panel {
461
+ padding: 24px;
462
+ }
463
+
464
+ .tool-panel h1,
465
+ .dashboard-head h1 {
466
+ font-size: clamp(2rem, 5vw, 3.8rem);
467
+ }
468
+
469
+ .model-warning {
470
+ margin: 18px 0;
471
+ border: 1px solid rgba(255, 209, 102, 0.48);
472
+ border-radius: 8px;
473
+ padding: 12px;
474
+ background: rgba(255, 209, 102, 0.08);
475
+ color: var(--amber);
476
+ }
477
+
478
+ .upload-form {
479
+ display: grid;
480
+ gap: 14px;
481
+ max-width: 520px;
482
+ }
483
+
484
+ .upload-box {
485
+ display: grid;
486
+ gap: 10px;
487
+ color: var(--muted);
488
+ }
489
+
490
+ .result-image {
491
+ width: 100%;
492
+ max-height: 280px;
493
+ object-fit: contain;
494
+ border: 1px solid rgba(255, 255, 255, 0.08);
495
+ border-radius: 8px;
496
+ background: rgba(255, 255, 255, 0.04);
497
+ }
498
+
499
+ .prediction-result {
500
+ display: grid;
501
+ gap: 8px;
502
+ margin: 16px 0;
503
+ }
504
+
505
+ .prediction-result span,
506
+ .stats-grid span {
507
+ color: var(--muted);
508
+ font-size: 0.82rem;
509
+ text-transform: uppercase;
510
+ }
511
+
512
+ .prediction-result strong {
513
+ font-size: 1.35rem;
514
+ }
515
+
516
+ .feedback {
517
+ min-width: 78px;
518
+ color: #07100c;
519
+ }
520
+
521
+ .feedback.true {
522
+ background: var(--green);
523
+ }
524
+
525
+ .feedback.false {
526
+ background: var(--pink);
527
+ color: white;
528
+ }
529
+
530
+ .history-strip,
531
+ .table-panel,
532
+ .stats-grid {
533
+ margin-top: 24px;
534
+ }
535
+
536
+ .section-heading {
537
+ justify-content: space-between;
538
+ }
539
+
540
+ .section-heading a {
541
+ color: var(--green);
542
+ font-weight: 800;
543
+ }
544
+
545
+ .history-grid {
546
+ display: grid;
547
+ grid-template-columns: repeat(3, 1fr);
548
+ gap: 16px;
549
+ }
550
+
551
+ .history-card {
552
+ display: grid;
553
+ gap: 10px;
554
+ }
555
+
556
+ .history-card img {
557
+ width: 100%;
558
+ aspect-ratio: 4 / 3;
559
+ object-fit: contain;
560
+ border-radius: 8px;
561
+ background: rgba(255, 255, 255, 0.04);
562
+ }
563
+
564
+ .dashboard-head {
565
+ justify-content: space-between;
566
+ }
567
+
568
+ .stats-grid {
569
+ display: grid;
570
+ grid-template-columns: repeat(5, 1fr);
571
+ gap: 14px;
572
+ }
573
+
574
+ .stats-grid strong {
575
+ display: block;
576
+ margin-top: 8px;
577
+ font-size: 2rem;
578
+ }
579
+
580
+ .table-panel {
581
+ overflow-x: auto;
582
+ }
583
+
584
+ table {
585
+ border-collapse: collapse;
586
+ min-width: 760px;
587
+ }
588
+
589
+ th,
590
+ td {
591
+ padding: 14px;
592
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
593
+ text-align: left;
594
+ }
595
+
596
+ th {
597
+ color: var(--muted);
598
+ font-size: 0.78rem;
599
+ text-transform: uppercase;
600
+ }
601
+
602
+ .thumb {
603
+ width: 58px;
604
+ height: 58px;
605
+ object-fit: contain;
606
+ border-radius: 8px;
607
+ background: rgba(255, 255, 255, 0.06);
608
+ }
609
+
610
+ .status {
611
+ display: inline-flex;
612
+ border-radius: 8px;
613
+ padding: 6px 9px;
614
+ font-size: 0.78rem;
615
+ font-weight: 900;
616
+ }
617
+
618
+ .status.true {
619
+ background: rgba(53, 242, 140, 0.14);
620
+ color: var(--green);
621
+ }
622
+
623
+ .status.false {
624
+ background: rgba(255, 79, 154, 0.16);
625
+ color: #ff9bc2;
626
+ }
627
+
628
+ .status.pending {
629
+ background: rgba(255, 209, 102, 0.14);
630
+ color: var(--amber);
631
+ }
632
+
633
+ .compact {
634
+ gap: 8px;
635
+ }
636
+
637
+ .compact .feedback {
638
+ min-width: 58px;
639
+ padding: 8px 10px;
640
+ }
641
+
642
+ @media (max-width: 860px) {
643
+ .hero,
644
+ .page-grid,
645
+ .feature-band,
646
+ .stats-grid {
647
+ grid-template-columns: 1fr;
648
+ }
649
+
650
+ .history-grid {
651
+ grid-template-columns: repeat(2, 1fr);
652
+ }
653
+ }
654
+
655
+ @media (max-width: 620px) {
656
+ .topbar {
657
+ align-items: flex-start;
658
+ flex-direction: column;
659
+ }
660
+
661
+ .nav {
662
+ width: 100%;
663
+ overflow-x: auto;
664
+ padding-bottom: 4px;
665
+ }
666
+
667
+ h1 {
668
+ font-size: 2.45rem;
669
+ }
670
+
671
+ .history-grid {
672
+ grid-template-columns: 1fr;
673
+ }
674
+
675
+ .cyber-content,
676
+ .tool-panel,
677
+ .result-panel {
678
+ padding: 20px;
679
+ }
680
+ }
templates/auth.html ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <section class="auth-shell">
5
+ <div class="cyber-terminal">
6
+ <div class="terminal-header">
7
+ <div class="terminal-buttons">
8
+ <span class="term-btn btn-red"></span>
9
+ <span class="term-btn btn-yellow"></span>
10
+ <span class="term-btn btn-green"></span>
11
+ </div>
12
+ <div class="terminal-title">{% block terminal_title %}{% endblock %}</div>
13
+ </div>
14
+
15
+ <div class="cyber-content">
16
+ <div class="neon-header">
17
+ <div class="cyber-logo">
18
+ <div class="logo-frame">
19
+ <span>AI</span>
20
+ <div class="logo-scanner"></div>
21
+ </div>
22
+ <div class="neon-glow"></div>
23
+ </div>
24
+ <h1 class="cyber-title">{% block auth_heading %}{% endblock %}</h1>
25
+ <p class="access-text">{% block auth_subtitle %}{% endblock %}</p>
26
+ </div>
27
+
28
+ {% block auth_form %}{% endblock %}
29
+ </div>
30
+ </div>
31
+ </section>
32
+ {% endblock %}
templates/base.html ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>{% block title %}Traffic Sign Classifier{% endblock %}</title>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/app.css') }}">
8
+ </head>
9
+ <body>
10
+ <div class="road-grid" aria-hidden="true">
11
+ <span></span><span></span><span></span>
12
+ </div>
13
+
14
+ <header class="topbar">
15
+ <a class="brand" href="{{ url_for('welcome') }}">
16
+ <span class="brand-mark">TS</span>
17
+ <span>Traffic Sign AI</span>
18
+ </a>
19
+ <nav class="nav">
20
+ <a href="{{ url_for('welcome') }}">Home</a>
21
+ {% if user %}
22
+ <a href="{{ url_for('predict') }}">Predict</a>
23
+ <a href="{{ url_for('dashboard') }}">History</a>
24
+ <a href="{{ url_for('logout') }}">Logout</a>
25
+ {% else %}
26
+ <a href="{{ url_for('login') }}">Login</a>
27
+ <a class="nav-cta" href="{{ url_for('register') }}">Register</a>
28
+ {% endif %}
29
+ </nav>
30
+ </header>
31
+
32
+ <main>
33
+ {% with messages = get_flashed_messages(with_categories=true) %}
34
+ {% if messages %}
35
+ <div class="flash-stack">
36
+ {% for category, message in messages %}
37
+ <div class="flash {{ category }}">{{ message }}</div>
38
+ {% endfor %}
39
+ </div>
40
+ {% endif %}
41
+ {% endwith %}
42
+
43
+ {% block content %}{% endblock %}
44
+ </main>
45
+ </body>
46
+ </html>
templates/dashboard.html ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}History Dashboard | Traffic Sign Classifier{% endblock %}
4
+
5
+ {% block content %}
6
+ <section class="dashboard-head">
7
+ <div>
8
+ <p class="eyebrow">Historique</p>
9
+ <h1>Prediction dashboard</h1>
10
+ <p class="panel-copy">Review predictions, mark them true or false, and track feedback quality.</p>
11
+ </div>
12
+ <a class="button primary" href="{{ url_for('predict') }}">New prediction</a>
13
+ </section>
14
+
15
+ <section class="stats-grid">
16
+ <article><span>Total</span><strong>{{ stats.total }}</strong></article>
17
+ <article><span>Reviewed</span><strong>{{ stats.reviewed }}</strong></article>
18
+ <article><span>True</span><strong>{{ stats.correct }}</strong></article>
19
+ <article><span>False</span><strong>{{ stats.incorrect }}</strong></article>
20
+ <article><span>Feedback accuracy</span><strong>{{ stats.accuracy }}%</strong></article>
21
+ </section>
22
+
23
+ <section class="table-panel">
24
+ <table>
25
+ <thead>
26
+ <tr>
27
+ <th>Image</th>
28
+ <th>Prediction</th>
29
+ <th>Confidence</th>
30
+ <th>Feedback</th>
31
+ <th>Action</th>
32
+ </tr>
33
+ </thead>
34
+ <tbody>
35
+ {% for row in history %}
36
+ <tr>
37
+ <td><img class="thumb" src="{{ url_for('static', filename=row.image_path) }}" alt="Traffic sign"></td>
38
+ <td>{{ row.predicted_class }}</td>
39
+ <td>{{ "%.1f"|format((row.confidence or 0) * 100) }}%</td>
40
+ <td>
41
+ {% if row.is_correct == 1 %}
42
+ <span class="status true">True</span>
43
+ {% elif row.is_correct == 0 %}
44
+ <span class="status false">False</span>
45
+ {% else %}
46
+ <span class="status pending">Pending</span>
47
+ {% endif %}
48
+ </td>
49
+ <td>
50
+ <form class="feedback-row compact" method="post" action="{{ url_for('feedback', prediction_id=row.id) }}">
51
+ <input type="hidden" name="next" value="{{ url_for('dashboard') }}">
52
+ <button name="is_correct" value="1" class="feedback true" type="submit">True</button>
53
+ <button name="is_correct" value="0" class="feedback false" type="submit">False</button>
54
+ </form>
55
+ </td>
56
+ </tr>
57
+ {% else %}
58
+ <tr>
59
+ <td colspan="5" class="empty">No prediction history yet.</td>
60
+ </tr>
61
+ {% endfor %}
62
+ </tbody>
63
+ </table>
64
+ </section>
65
+ {% endblock %}
templates/login.html ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "auth.html" %}
2
+
3
+ {% block title %}Login | Traffic Sign Classifier{% endblock %}
4
+ {% block terminal_title %}traffic_login.exe{% endblock %}
5
+ {% block auth_heading %}Secure Login{% endblock %}
6
+ {% block auth_subtitle %}[ CLASSIFIER_ACCESS ]{% endblock %}
7
+
8
+ {% block auth_form %}
9
+ <form class="neon-form" method="post" action="{{ url_for('login') }}">
10
+ <label class="cyber-field">
11
+ <span>Email address</span>
12
+ <input type="email" name="email" required autocomplete="email" placeholder="you@example.com">
13
+ </label>
14
+
15
+ <label class="cyber-field">
16
+ <span>Password</span>
17
+ <input type="password" name="password" required autocomplete="current-password" placeholder="Enter password">
18
+ </label>
19
+
20
+ <button type="submit" class="neon-button">
21
+ <span>[ INITIALIZE_CONNECTION ]</span>
22
+ </button>
23
+ </form>
24
+
25
+ <div class="matrix-signup">
26
+ <span>[ NEW_USER_DETECTED ]</span>
27
+ <a href="{{ url_for('register') }}">CREATE_PROFILE</a>
28
+ </div>
29
+ {% endblock %}
templates/predict.html ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Predict | Traffic Sign Classifier{% endblock %}
4
+
5
+ {% block content %}
6
+ <section class="page-grid">
7
+ <div class="tool-panel">
8
+ <p class="eyebrow">Classifier</p>
9
+ <h1>Upload a traffic sign image</h1>
10
+ <p class="panel-copy">The prediction is saved automatically to your personal history.</p>
11
+
12
+ {% if model_error %}
13
+ <div class="model-warning">{{ model_error }}</div>
14
+ {% endif %}
15
+
16
+ <form class="upload-form" method="post" enctype="multipart/form-data">
17
+ <label class="upload-box">
18
+ <span>Choose image</span>
19
+ <input type="file" name="image" accept="image/png,image/jpeg,image/webp" required>
20
+ </label>
21
+ <button class="button primary" type="submit">Classify sign</button>
22
+ </form>
23
+ </div>
24
+
25
+ <aside class="result-panel">
26
+ <h2>Latest result</h2>
27
+ {% if prediction %}
28
+ <img class="result-image" src="{{ url_for('static', filename=prediction.image_path) }}" alt="Uploaded traffic sign">
29
+ <div class="prediction-result">
30
+ <span>Predicted class</span>
31
+ <strong>{{ prediction.predicted_class }}</strong>
32
+ <small>Confidence: {{ "%.1f"|format(prediction.confidence * 100) }}%</small>
33
+ </div>
34
+ <form class="feedback-row" method="post" action="{{ url_for('feedback', prediction_id=prediction.id) }}">
35
+ <input type="hidden" name="next" value="{{ url_for('predict') }}">
36
+ <button name="is_correct" value="1" class="feedback true" type="submit">True</button>
37
+ <button name="is_correct" value="0" class="feedback false" type="submit">False</button>
38
+ </form>
39
+ {% else %}
40
+ <p class="empty">Your next prediction will appear here.</p>
41
+ {% endif %}
42
+ </aside>
43
+ </section>
44
+
45
+ <section class="history-strip">
46
+ <div class="section-heading">
47
+ <h2>Recent history</h2>
48
+ <a href="{{ url_for('dashboard') }}">Open dashboard</a>
49
+ </div>
50
+ <div class="history-grid">
51
+ {% for row in history %}
52
+ <article class="history-card">
53
+ <img src="{{ url_for('static', filename=row.image_path) }}" alt="Traffic sign prediction">
54
+ <strong>{{ row.predicted_class }}</strong>
55
+ <small>{{ "%.1f"|format((row.confidence or 0) * 100) }}% confidence</small>
56
+ </article>
57
+ {% else %}
58
+ <p class="empty">No predictions yet.</p>
59
+ {% endfor %}
60
+ </div>
61
+ </section>
62
+ {% endblock %}
templates/register.html ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "auth.html" %}
2
+
3
+ {% block title %}Register | Traffic Sign Classifier{% endblock %}
4
+ {% block terminal_title %}traffic_registration.exe{% endblock %}
5
+ {% block auth_heading %}Create Profile{% endblock %}
6
+ {% block auth_subtitle %}[ NEW_OPERATOR_REGISTRATION ]{% endblock %}
7
+
8
+ {% block auth_form %}
9
+ <form class="neon-form" method="post" action="{{ url_for('register') }}">
10
+ <label class="cyber-field">
11
+ <span>Full name</span>
12
+ <input type="text" name="name" required autocomplete="name" placeholder="Your name">
13
+ </label>
14
+
15
+ <label class="cyber-field">
16
+ <span>Email address</span>
17
+ <input type="email" name="email" required autocomplete="email" placeholder="you@example.com">
18
+ </label>
19
+
20
+ <label class="cyber-field">
21
+ <span>Password</span>
22
+ <input type="password" name="password" required autocomplete="new-password" placeholder="Minimum 6 characters">
23
+ </label>
24
+
25
+ <label class="cyber-field">
26
+ <span>Confirm password</span>
27
+ <input type="password" name="confirm_password" required autocomplete="new-password" placeholder="Repeat password">
28
+ </label>
29
+
30
+ <button type="submit" class="neon-button">
31
+ <span>[ CREATE_PROFILE ]</span>
32
+ </button>
33
+ </form>
34
+
35
+ <div class="matrix-signup">
36
+ <span>[ PROFILE_EXISTS ]</span>
37
+ <a href="{{ url_for('login') }}">LOGIN_NOW</a>
38
+ </div>
39
+ {% endblock %}
templates/welcome.html ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Welcome | Traffic Sign Classifier{% endblock %}
4
+
5
+ {% block content %}
6
+ <section class="hero">
7
+ <div class="hero-copy">
8
+ <p class="eyebrow">Flask + CNN deployment</p>
9
+ <h1>Traffic sign recognition with user feedback history.</h1>
10
+ <p class="lead">
11
+ Upload a traffic sign image, classify it with <strong>traffic_classifier.h5</strong>,
12
+ and keep every prediction linked to the authenticated user.
13
+ </p>
14
+ <div class="hero-actions">
15
+ <a class="button primary" href="{{ url_for('register') }}">Create account</a>
16
+ <a class="button secondary" href="{{ url_for('login') }}">Login</a>
17
+ </div>
18
+ </div>
19
+
20
+ <div class="signal-panel" aria-label="Application workflow">
21
+ <div class="signal-head">
22
+ <span class="dot red"></span>
23
+ <span class="dot amber"></span>
24
+ <span class="dot green"></span>
25
+ <span>deployment.plan</span>
26
+ </div>
27
+ <div class="signal-body">
28
+ <div class="workflow-step">
29
+ <span>01</span>
30
+ <p>Register or login before using the model.</p>
31
+ </div>
32
+ <div class="workflow-step">
33
+ <span>02</span>
34
+ <p>Upload a sign image and receive the predicted class.</p>
35
+ </div>
36
+ <div class="workflow-step">
37
+ <span>03</span>
38
+ <p>Mark predictions as true or false for later analysis.</p>
39
+ </div>
40
+ <div class="workflow-step">
41
+ <span>04</span>
42
+ <p>Review your dashboard and history inside the container database.</p>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </section>
47
+
48
+ <section class="feature-band">
49
+ <article>
50
+ <h2>Authentication</h2>
51
+ <p>Each user has an account, a protected classifier page, and a private prediction history.</p>
52
+ </article>
53
+ <article>
54
+ <h2>Model Ready</h2>
55
+ <p>The app loads <code>traffic_classifier.h5</code> from the project root during startup.</p>
56
+ </article>
57
+ <article>
58
+ <h2>Feedback Loop</h2>
59
+ <p>True/false labels are saved with predictions so the dashboard can show reviewed accuracy.</p>
60
+ </article>
61
+ </section>
62
+ {% endblock %}
traffic_classifier.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:864e84abd1a2ab5245b805d1366cad8691cb1315ada45cf58c46d669195c8b84
3
+ size 19561904