afront 1.0.18 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/build-prod/index.html +1 -1
  2. package/build-prod/offline.html +1024 -0
  3. package/build-prod/service-worker.js +1 -0
  4. package/build-prod/static/css/main-b7c0f6b3ea505263e9a2.css +1 -0
  5. package/build-prod/static/js/3-b7f6c4256e55d2c173ac.js +1 -0
  6. package/build-prod/static/js/41-d729186c867a4a7f5f49.js +1 -0
  7. package/build-prod/static/js/525-506bbc7da1b98d130181.js +1 -0
  8. package/build-prod/static/js/573-8fcda455788ea4aa45cd.js +1 -0
  9. package/build-prod/static/js/99-ccf46a26c15904ecb674.js +1 -0
  10. package/build-prod/static/js/main-34c866ebbc6fbc291b85.js +1 -0
  11. package/build-prod-ssr/3.ssr.prod.js +1 -1
  12. package/build-prod-ssr/41.ssr.prod.js +1 -1
  13. package/build-prod-ssr/525.ssr.prod.js +1 -0
  14. package/build-prod-ssr/573.ssr.prod.js +1 -1
  15. package/build-prod-ssr/ssr.prod.js +1 -1
  16. package/build-prod-ssr/static/css/main-b7c0f6b3ea505263e9a2.css +1 -0
  17. package/build-prod-static/index.html +1 -1
  18. package/build-prod-static/offline.html +1024 -0
  19. package/build-prod-static/service-worker.js +1 -0
  20. package/build-prod-static/static/css/main-b7c0f6b3ea505263e9a2.css +1 -0
  21. package/build-prod-static/static/js/23-c9124d3cac34021e3406.js +1 -0
  22. package/build-prod-static/static/js/303-0d29064b1a912a7441ef.js +1 -0
  23. package/build-prod-static/static/js/636-adf7ca5d4e262a755df3.js +1 -0
  24. package/build-prod-static/static/js/863-2c35feb0663baeecb6f8.js +1 -0
  25. package/build-prod-static/static/js/main-02c8c189d5bec6c0a7f1.js +1 -0
  26. package/install.js +2 -2
  27. package/package.json +6 -5
  28. package/server.js +2 -0
  29. package/src/ARoutes/AFRoutes.js +22 -5
  30. package/src/Api/api.config.js +266 -0
  31. package/src/Api/login.service.js +44 -0
  32. package/src/App.js +10 -9
  33. package/src/Components/Loading/LoadingIndicator.js +12 -0
  34. package/src/Components/Loading/LoadingIndicator.module.css +34 -0
  35. package/src/Components/Loading/LoadingSpinner.js +27 -0
  36. package/src/Components/Loading/LoadingSpinner.module.css +100 -0
  37. package/src/Components/RequireAuth.js +30 -0
  38. package/src/PageNotFound.js +1 -1
  39. package/src/Pages/Signup.js +230 -0
  40. package/src/Routes/ARoutes.js +47 -6
  41. package/src/Routes/ARoutesStatic.js +83 -0
  42. package/src/Static/appStatic.js +10 -20
  43. package/src/Static/indexStatic.js +3 -0
  44. package/src/Utils/LoadingContext.js +5 -0
  45. package/src/index.js +0 -4
  46. package/webpack.build-prod.js +13 -0
  47. package/webpack.dev.js +18 -0
  48. package/webpack.prod.js +11 -2
  49. package/webpack.ssr.prod.js +4 -0
  50. package/build-prod/static/css/main-7f7c4e72ce002df48179.css +0 -1
  51. package/build-prod/static/js/3-985f8801e97b3b2025e2.js +0 -1
  52. package/build-prod/static/js/41-a66fae84fd39cfb1e349.js +0 -1
  53. package/build-prod/static/js/573-f7791eb491c75b0ccfb7.js +0 -1
  54. package/build-prod/static/js/main-1cbe42ef1eb3d942625c.js +0 -1
  55. package/build-prod-ssr/static/css/main-7f7c4e72ce002df48179.css +0 -1
  56. package/build-prod-static/static/css/main-7f7c4e72ce002df48179.css +0 -1
  57. package/build-prod-static/static/js/23-9e69ffb20f982ca1ba75.js +0 -1
  58. package/build-prod-static/static/js/303-1b6136e5efb4925c5f98.js +0 -1
  59. package/build-prod-static/static/js/636-7f7bf68f9765bc200b86.js +0 -1
  60. package/build-prod-static/static/js/main-6c6f40c44813930620ed.js +0 -1
@@ -0,0 +1,230 @@
1
+ import React, { useState } from "react";
2
+ import { useNavigate } from "react-router";
3
+ import auth from "../Api/login.service";
4
+
5
+ function Signup() {
6
+ const navigate = useNavigate();
7
+ const [step, setStep] = useState(1);
8
+ const [email, setEmail] = useState("");
9
+ const [password, setPassword] = useState("");
10
+ const [name, setName] = useState("");
11
+ const [accountType, setAccountType] = useState("personal"); // personal/creator or business
12
+ const [companyName, setCompanyName] = useState("");
13
+ const [loading, setLoading] = useState(false);
14
+ const [error, setError] = useState(null);
15
+
16
+ const validateStep = () => {
17
+ setError(null);
18
+ if (step === 1) {
19
+ if (!email) return "Email is required";
20
+ // basic email regex
21
+ const emailRegex = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
22
+ if (!emailRegex.test(email)) return "Enter a valid email address";
23
+ if (!password) return "Password is required";
24
+ if (password.length < 8) return "Password must be at least 8 characters";
25
+ }
26
+ if (step === 2) {
27
+ if (!name || name.trim().length === 0) return "Full name is required";
28
+ }
29
+ if (step === 3) {
30
+ if (!accountType) return "Select account type";
31
+ if (
32
+ accountType === "business" &&
33
+ (!companyName || companyName.trim().length === 0)
34
+ )
35
+ return "Brand / Company Name is required for business accounts";
36
+ }
37
+ return null;
38
+ };
39
+
40
+ const handleNext = (e) => {
41
+ (async () => {
42
+ if (e) e.preventDefault();
43
+ const err = validateStep();
44
+ if (err) return setError(err);
45
+ setError(null);
46
+ // On step 1, call backend to check email (exists/disposable)
47
+ if (step === 1) {
48
+ try {
49
+ const res = await auth.checkSignup({ email });
50
+ if (!res || !res.ok) {
51
+ setError(
52
+ (res && res.data && (res.data.error || res.data.message)) ||
53
+ "Check failed"
54
+ );
55
+ return;
56
+ }
57
+ if (res.data.disposable) {
58
+ setError("Disposable email addresses are not allowed");
59
+ return;
60
+ }
61
+ if (res.data.exists) {
62
+ setError("An account already exists with this email");
63
+ return;
64
+ }
65
+ } catch (err) {
66
+ setError("Email check failed");
67
+ return;
68
+ }
69
+ }
70
+ setStep((s) => Math.min(3, s + 1));
71
+ })();
72
+ };
73
+
74
+ const handleBack = (e) => {
75
+ if (e) e.preventDefault();
76
+ setError(null);
77
+ setStep((s) => Math.max(1, s - 1));
78
+ };
79
+
80
+ const handleSubmit = async (e) => {
81
+ if (e) e.preventDefault();
82
+ const err = validateStep();
83
+ if (err) return setError(err);
84
+ setLoading(true);
85
+ setError(null);
86
+ try {
87
+ const payload = {
88
+ email,
89
+ password,
90
+ name,
91
+ accountType,
92
+ companyName: accountType === "business" ? companyName : undefined,
93
+ };
94
+ const res = await auth.signup(payload);
95
+ if (!res || !res.ok) {
96
+ setError(
97
+ (res && res.data && (res.data.error || res.data.message)) ||
98
+ "Registration failed"
99
+ );
100
+ setLoading(false);
101
+ return;
102
+ }
103
+
104
+ try {
105
+ localStorage.setItem("auth-event", String(Date.now()));
106
+ } catch (e) {}
107
+ window.dispatchEvent(new Event("auth-changed"));
108
+ navigate("/");
109
+ } catch (err) {
110
+ setError("Registration failed");
111
+ } finally {
112
+ setLoading(false);
113
+ }
114
+ };
115
+
116
+ return (
117
+ <div className="page auth-page signup-page">
118
+ <h2>Sign up</h2>
119
+ {error && <div className="auth-error">{error}</div>}
120
+ <form
121
+ className="auth-form"
122
+ onSubmit={step === 3 ? handleSubmit : handleNext}>
123
+ {step === 1 && (
124
+ <>
125
+ <label>
126
+ Email Address (required)
127
+ <input
128
+ type="email"
129
+ value={email}
130
+ onChange={(e) => setEmail(e.target.value)}
131
+ disabled={loading}
132
+ />
133
+ </label>
134
+ {/* Work/personal choice removed — backend tracks only personal emails */}
135
+ <label>
136
+ Password (required, min 8 characters)
137
+ <input
138
+ type="password"
139
+ value={password}
140
+ onChange={(e) => setPassword(e.target.value)}
141
+ disabled={loading}
142
+ />
143
+ </label>
144
+ <div className="form-actions">
145
+ <button type="button" onClick={handleNext} disabled={loading}>
146
+ Next
147
+ </button>
148
+ </div>
149
+ </>
150
+ )}
151
+
152
+ {step === 2 && (
153
+ <>
154
+ <label>
155
+ Full Name (required)
156
+ <input
157
+ value={name}
158
+ onChange={(e) => setName(e.target.value)}
159
+ disabled={loading}
160
+ />
161
+ </label>
162
+ <div className="form-actions">
163
+ <button type="button" onClick={handleBack} disabled={loading}>
164
+ Back
165
+ </button>
166
+ <button type="button" onClick={handleNext} disabled={loading}>
167
+ Next
168
+ </button>
169
+ </div>
170
+ </>
171
+ )}
172
+
173
+ {step === 3 && (
174
+ <>
175
+ <label>
176
+ Account Type (required)
177
+ <div>
178
+ <label>
179
+ <input
180
+ type="radio"
181
+ name="accountType"
182
+ value="personal"
183
+ checked={accountType === "personal"}
184
+ onChange={() => setAccountType("personal")}
185
+ disabled={loading}
186
+ />
187
+ Personal / Creator
188
+ </label>
189
+ <label>
190
+ <input
191
+ type="radio"
192
+ name="accountType"
193
+ value="business"
194
+ checked={accountType === "business"}
195
+ onChange={() => setAccountType("business")}
196
+ disabled={loading}
197
+ />
198
+ Business / Brand / Company
199
+ </label>
200
+ </div>
201
+ </label>
202
+ {accountType === "business" && (
203
+ <label>
204
+ Brand / Company Name (required for business)
205
+ <input
206
+ value={companyName}
207
+ onChange={(e) => setCompanyName(e.target.value)}
208
+ disabled={loading}
209
+ />
210
+ </label>
211
+ )}
212
+
213
+ {error && <div className="auth-error">{error}</div>}
214
+
215
+ <div className="form-actions">
216
+ <button type="button" onClick={handleBack} disabled={loading}>
217
+ Back
218
+ </button>
219
+ <button type="submit" disabled={loading}>
220
+ {loading ? "Signing up..." : "Sign up"}
221
+ </button>
222
+ </div>
223
+ </>
224
+ )}
225
+ </form>
226
+ </div>
227
+ );
228
+ }
229
+
230
+ export default Signup;
@@ -1,24 +1,65 @@
1
- import React, { Suspense } from "react";
1
+ import React, { Suspense, useContext } from "react";
2
2
  import { Route, Routes } from "react-router";
3
3
  import routes from "../ARoutes/AFRoutes.js";
4
- import LoadingFallback from "../LoadingFallback.js";
4
+ import RequireAuth from "../Components/RequireAuth.js";
5
+ import LoadingIndicator from "../Components/Loading/LoadingIndicator.js";
6
+ import Header from "../Components/Header/Header.js";
7
+ import Footer from "../Components/Footer/Footer.js";
8
+ import LoadingContext from "../Utils/LoadingContext.js";
5
9
 
6
10
 
11
+ const Layout = ({ children }) => (
12
+ <>
13
+ <Header />
14
+ {children}
15
+ <Footer />
16
+ </>
17
+ );
18
+
7
19
  const ARoutes = ({ context }) => {
20
+ const { setLoading } = useContext(LoadingContext);
8
21
  return (
9
- <Suspense fallback={<LoadingFallback />}>
10
22
  <Routes>
11
23
  {/* Pages Routes */}
12
- {routes.map(({ path, element: Element }, index) => (
24
+ {routes.map(({ path, element: Element, withHeaderFooter, protected: isProtected }, index) => (
13
25
  <Route
14
26
  key={index}
15
27
  path={path}
16
- element={<Element context={context} />}
28
+ element={
29
+ withHeaderFooter ? (
30
+ <Layout>
31
+ <Suspense
32
+ fallback={<LoadingIndicator />}
33
+ onPromiseStart={() => setLoading(true)}
34
+ onPromiseEnd={() => setLoading(false)}>
35
+ {isProtected ? (
36
+ <RequireAuth>
37
+ <Element context={context} />
38
+ </RequireAuth>
39
+ ) : (
40
+ <Element context={context} />
41
+ )}
42
+ </Suspense>
43
+ </Layout>
44
+ ) : (
45
+ <Suspense
46
+ fallback={<LoadingIndicator />}
47
+ onPromiseStart={() => setLoading(true)}
48
+ onPromiseEnd={() => setLoading(false)}>
49
+ {isProtected ? (
50
+ <RequireAuth>
51
+ <Element context={context} />
52
+ </RequireAuth>
53
+ ) : (
54
+ <Element context={context} />
55
+ )}
56
+ </Suspense>
57
+ )
58
+ }
17
59
  />
18
60
  ))}
19
61
  {/* Pages Routes */}
20
62
  </Routes>
21
- </Suspense>
22
63
  );
23
64
  };
24
65
 
@@ -0,0 +1,83 @@
1
+ /*
2
+ * File Name: ARoutesStatic.js
3
+ *
4
+ * Description: This file handles the logic for Handling Header and Footer to be visible or not for the every specific page for single page application (Static Page).
5
+ *
6
+ *
7
+ * Author: Mark Sea.
8
+ *
9
+ * Created: 14/Dec/2024
10
+ *
11
+ * Dependencies: {react-router}
12
+ *
13
+ * Assumptions: This file is used in appStatic.js
14
+ */
15
+
16
+ import React, { Suspense, useContext } from "react";
17
+ import { Route, Routes } from "react-router";
18
+ import routes from "../ARoutes/AFRoutes.js";
19
+ import RequireAuth from "../Components/RequireAuth.js";
20
+ import LoadingIndicator from "../Components/Loading/LoadingIndicator.js";
21
+ import Header from "../Components/Header/Header.js";
22
+ import Footer from "../Components/Footer/Footer.js";
23
+ import LoadingContext from "../Utils/LoadingContext.js";
24
+
25
+ const Layout = ({ children }) => (
26
+ <>
27
+ <Header />
28
+ {children}
29
+ <Footer />
30
+ </>
31
+ );
32
+
33
+ const ARoutesStatic = ({ context }) => {
34
+ const { setLoading } = useContext(LoadingContext);
35
+ return (
36
+ <Routes>
37
+ {routes.map(
38
+ (
39
+ { path, element: Element, withHeaderFooter, protected: isProtected },
40
+ index
41
+ ) => (
42
+ <Route
43
+ key={index}
44
+ path={path}
45
+ element={
46
+ withHeaderFooter ? (
47
+ <Layout>
48
+ <Suspense
49
+ fallback={<LoadingIndicator />}
50
+ onPromiseStart={() => setLoading(true)}
51
+ onPromiseEnd={() => setLoading(false)}>
52
+ {isProtected ? (
53
+ <RequireAuth>
54
+ <Element context={context} />
55
+ </RequireAuth>
56
+ ) : (
57
+ <Element context={context} />
58
+ )}
59
+ </Suspense>
60
+ </Layout>
61
+ ) : (
62
+ <Suspense
63
+ fallback={<LoadingIndicator />}
64
+ onPromiseStart={() => setLoading(true)}
65
+ onPromiseEnd={() => setLoading(false)}>
66
+ {isProtected ? (
67
+ <RequireAuth>
68
+ <Element context={context} />
69
+ </RequireAuth>
70
+ ) : (
71
+ <Element context={context} />
72
+ )}
73
+ </Suspense>
74
+ )
75
+ }
76
+ />
77
+ )
78
+ )}
79
+ </Routes>
80
+ );
81
+ };
82
+
83
+ export default ARoutesStatic;
@@ -1,26 +1,16 @@
1
- import React, { Suspense } from "react";
2
- import { BrowserRouter as Router, Route, Routes } from "react-router";
3
- import routes from "../ARoutes/AFRoutes.js";
4
- import LoadingFallback from "../LoadingFallback.js";
1
+ import React, { useState } from "react";
2
+ import ARoutesStatic from "../Routes/ARoutesStatic.js";
3
+ import LoadingContext from "../Utils/LoadingContext.js";
4
+ import LoadingIndicator from "../Components/Loading/LoadingIndicator.js";
5
5
 
6
- import Header from "../Components/Header/Header.js";
7
- import Footer from "../Components/Footer/Footer.js";
8
6
 
9
- function appStatic() {
7
+ function appStatic({ context }) {
8
+ const [loading, setLoading] = useState(false);
10
9
  return (
11
- <Router>
12
- <Suspense fallback={<LoadingFallback />}>
13
- <Header />
14
- <Routes>
15
- {/* Pages Routes */}
16
- {routes.map(({ path, element: Element }, index) => (
17
- <Route key={index} path={path} element={<Element />} />
18
- ))}
19
- {/* Pages Routes */}
20
- </Routes>
21
- <Footer />
22
- </Suspense>
23
- </Router>
10
+ <LoadingContext.Provider value={{ loading, setLoading }}>
11
+ {loading && <LoadingIndicator />}
12
+ <ARoutesStatic context={context} />
13
+ </LoadingContext.Provider>
24
14
  );
25
15
  }
26
16
  export default appStatic;
@@ -1,10 +1,13 @@
1
1
  import React from "react";
2
2
  import ReactDOM from "react-dom/client";
3
+ import { BrowserRouter } from "react-router";
3
4
  import App from "./appStatic";
4
5
 
5
6
  const asggen = ReactDOM.createRoot(document.getElementById("asggen"));
6
7
  asggen.render(
7
8
  <React.StrictMode>
9
+ <BrowserRouter>
8
10
  <App />
11
+ </BrowserRouter>
9
12
  </React.StrictMode>
10
13
  );
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react";
2
+
3
+ const LoadingContext = createContext();
4
+
5
+ export default LoadingContext;
package/src/index.js CHANGED
@@ -12,18 +12,14 @@ if (process.env.NODE_ENV === "production") {
12
12
  // Use `hydrateRoot` for production
13
13
  hydrateRoot(
14
14
  container,
15
- <React.StrictMode>
16
15
  <BrowserRouter>
17
16
  <App />
18
17
  </BrowserRouter>
19
- </React.StrictMode>
20
18
  );
21
19
  } else {
22
20
  root.render(
23
- <React.StrictMode>
24
21
  <BrowserRouter>
25
22
  <App />
26
23
  </BrowserRouter>
27
- </React.StrictMode>
28
24
  );
29
25
  }
@@ -13,6 +13,7 @@ module.exports = {
13
13
  output: {
14
14
  filename: "static/js/[name]-[contenthash].js",
15
15
  path: path.resolve(__dirname, "build-prod-static"),
16
+ publicPath: "/",
16
17
  clean: true,
17
18
  },
18
19
  module: {
@@ -39,6 +40,7 @@ module.exports = {
39
40
  modules: {
40
41
  localIdentName: "asggen-[hash:base64:7]",
41
42
  },
43
+ sourceMap: true,
42
44
  },
43
45
  },
44
46
  ],
@@ -70,6 +72,9 @@ module.exports = {
70
72
  minimizer: [
71
73
  new TerserWebpackPlugin({
72
74
  terserOptions: {
75
+ compress: {
76
+ drop_console: false,
77
+ },
73
78
  format: {
74
79
  comments: false, // Remove all comments
75
80
  },
@@ -85,6 +90,12 @@ module.exports = {
85
90
  template: "./dev/index.html",
86
91
  buildTag: `prod-[contenthash]`,
87
92
  hash: true,
93
+ minify: {
94
+ removeComments: true,
95
+ collapseWhitespace: true,
96
+ minifyCSS: true,
97
+ minifyJS: true,
98
+ },
88
99
  templateParameters: (compilation, options) => {
89
100
  const hash = crypto.createHash("sha1");
90
101
  hash.update(compilation.hash);
@@ -110,6 +121,8 @@ module.exports = {
110
121
  { from: "dev/manifest.json", to: "manifest.json" }, // Copy manifest
111
122
  { from: "dev/style.css", to: "style.css" },
112
123
  { from: "dev/robots.txt", to: "robots.txt" },
124
+ { from: "dev/service-worker.js", to: "service-worker.js" },
125
+ { from: "dev/offline.html", to: "offline.html" },
113
126
  ],
114
127
  }),
115
128
  ],
package/webpack.dev.js CHANGED
@@ -3,10 +3,12 @@ const path = require("path");
3
3
  const MiniCssExtractPlugin = require("mini-css-extract-plugin");
4
4
  const TerserWebpackPlugin = require("terser-webpack-plugin");
5
5
  const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
6
+ const crypto = require("crypto");
6
7
 
7
8
  module.exports = {
8
9
  mode: "development",
9
10
  entry: "./src/index.js",
11
+ devtool: "cheap-module-source-map",
10
12
  devServer: {
11
13
  static: {
12
14
  directory: path.join(__dirname, "dev"),
@@ -18,6 +20,7 @@ module.exports = {
18
20
  output: {
19
21
  filename: "[name].bundle.js",
20
22
  path: `${__dirname}/dev`,
23
+ publicPath: "/",
21
24
  clean: true,
22
25
  },
23
26
  module: {
@@ -89,6 +92,21 @@ module.exports = {
89
92
  new htmlWebpackPlugin({
90
93
  title: "AFront",
91
94
  template: `${__dirname}/dev/index.html`,
95
+ filename: "index.html",
96
+ hash: true, // This will add the hash in the injected scripts
97
+ templateParameters: (compilation) => {
98
+ const hash = crypto.createHash("sha1");
99
+ hash.update(compilation.hash);
100
+ const sha1Hash = hash.digest("hex");
101
+ return {
102
+ htmlWebpackPlugin: {
103
+ options: {
104
+ title: "AFront",
105
+ buildTag: `dev-${sha1Hash}`, // Set the build tag with the hash for dev
106
+ },
107
+ },
108
+ };
109
+ },
92
110
  }),
93
111
  ],
94
112
  };
package/webpack.prod.js CHANGED
@@ -12,6 +12,7 @@ module.exports = {
12
12
  output: {
13
13
  filename: "static/js/[name]-[contenthash].js",
14
14
  path: path.resolve(__dirname, "build-prod"),
15
+ publicPath: "/",
15
16
  clean: true,
16
17
  },
17
18
  module: {
@@ -72,6 +73,9 @@ module.exports = {
72
73
  minimizer: [
73
74
  new TerserWebpackPlugin({
74
75
  terserOptions: {
76
+ compress: {
77
+ drop_console: false,
78
+ },
75
79
  format: {
76
80
  comments: false,
77
81
  },
@@ -80,6 +84,9 @@ module.exports = {
80
84
  }),
81
85
  new CssMinimizerPlugin(),
82
86
  ],
87
+ splitChunks: {
88
+ chunks: "all", // Automatically split vendor and app code
89
+ },
83
90
  },
84
91
  plugins: [
85
92
  new HtmlWebpackPlugin({
@@ -90,6 +97,8 @@ module.exports = {
90
97
  minify: {
91
98
  removeComments: true,
92
99
  collapseWhitespace: true,
100
+ minifyCSS: true,
101
+ minifyJS: true,
93
102
  },
94
103
  templateParameters: (compilation) => {
95
104
  const hash = crypto.createHash("sha1");
@@ -116,12 +125,12 @@ module.exports = {
116
125
  { from: "dev/manifest.json", to: "manifest.json" },
117
126
  { from: "dev/style.css", to: "style.css" },
118
127
  { from: "dev/robots.txt", to: "robots.txt" },
128
+ { from: "dev/service-worker.js", to: "service-worker.js" },
129
+ { from: "dev/offline.html", to: "offline.html" },
119
130
  ],
120
131
  }),
121
132
  ],
122
133
  performance: {
123
134
  hints: "warning",
124
- maxEntrypointSize: 400000,
125
- maxAssetSize: 400000,
126
135
  },
127
136
  };
@@ -10,6 +10,7 @@ module.exports = {
10
10
  output: {
11
11
  path: path.resolve(__dirname, "build-prod-ssr"),
12
12
  filename: "ssr.prod.js",
13
+ publicPath: "/",
13
14
  clean: true,
14
15
  libraryTarget: "commonjs2",
15
16
  },
@@ -72,6 +73,9 @@ module.exports = {
72
73
  minimizer: [
73
74
  new TerserWebpackPlugin({
74
75
  terserOptions: {
76
+ compress: {
77
+ drop_console: false,
78
+ },
75
79
  format: {
76
80
  comments: false,
77
81
  },
@@ -1 +0,0 @@
1
- @import url(https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600;700&display=swap);.asggen-khZCOtF{align-items:center;display:flex;height:100vh;justify-content:center}.asggen-DnF_4DH{height:auto;width:150px}:root{--light:#fff;--dark:#000;--color-white-100:#fff;--color-white-200:#e4e6e7;--color-white-300:#c9cccf;--color-white-400:#a1a6aa;--color-white-500:#798086;--color-black-100:#14191f;--color-black-200:#101419;--color-black-300:#0c0f13;--color-black-400:#0c0f13;--color-black-500:#080a0c;--color-black-600:#060709;--color-black-700:#040506;--color-black-800:#020303;--color-blue-100:#dcebfe;--color-blue-200:#bedbfe;--color-blue-300:#91c3fd;--color-blue-400:#61a6fa;--color-blue-500:#3c83f6;--color-blue-600:#2463eb;--color-blue-700:#1d4fd7;--color-blue-800:#1e3fae;--color-blue-900:#1e3b8a;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 16px 32px -16px rgba(0,0,0,.1),0 0 0 1px rgba(0,0,0,.1);--base__color-2__rgb:32,32,32;--shadow-small:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);--shadow-medium:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--shadow-large:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05)}*,:after,:before{box-sizing:border-box;list-style:none;list-style-type:none;margin:0;padding:0;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}html{box-sizing:inherit;font-size:100%;scroll-behavior:smooth}body,html{height:-webkit-fill-available}body{font-family:Rubik,sans-serif;font-size:clamp(1rem,2vw,1.125rem);font-weight:400;line-height:1.5;min-width:320px}main{overflow:hidden}a,button{background:none;border:none;box-shadow:none;cursor:pointer;outline:none;text-decoration:none;user-select:none}a{color:var(--color-black-400)}img,video{display:block;height:auto;max-width:100%;object-fit:cover}.asggen-vCnhqcW{margin:0 auto;padding:6rem 0 8rem}.asggen-yYmSvug{height:auto;margin:0 auto;max-width:75rem}.asggen-k7ux6uU{margin-bottom:1rem;text-align:center;vertical-align:middle}.asggen-GSXjAs2{font-size:clamp(2.648rem,6vw,4.241rem)}.asggen-GSXjAs2,.asggen-I9IojjR{font-family:inherit;font-weight:700;letter-spacing:-1px;line-height:1.15}.asggen-I9IojjR{font-size:clamp(2.179rem,5vw,3.176rem)}.asggen-FDKWcrI{font-family:inherit;font-size:clamp(1.794rem,4vw,2.379rem);font-weight:700;letter-spacing:-1px;line-height:1.25}.asggen-SbGaSDq{font-size:clamp(1.476rem,3vw,1.782rem);font-weight:600}.asggen-SbGaSDq,.asggen-kc5w7ZM{font-family:inherit;line-height:1.5}.asggen-kc5w7ZM{font-size:clamp(1.215rem,2vw,1.335rem);font-weight:500}.asggen-ypntYRK{font-family:inherit;font-size:clamp(1rem,2vw,1.125rem);text-wrap:balance}.asggen-XT_r9I4{border:none;border-radius:.75rem;display:inline-block;font-family:inherit;font-size:1rem;font-weight:500;line-height:1.5;outline:none;text-align:center;text-transform:unset;user-select:none;vertical-align:middle;white-space:nowrap}.asggen-ik053am{align-items:center;column-gap:.5rem;display:inline-flex;justify-content:center}.asggen-e3fixws.asggen-YFITMpr{align-items:center;background-color:var(--color-black-200);border-bottom:none;display:flex;height:2.7rem;justify-content:center;line-height:0;margin-left:0;padding:.75rem 2rem}.asggen-bremE3g{fill:#fff;height:1rem;margin-left:1rem}.asggen-e3fixws.asggen-YFITMpr:hover{border-bottom:2px solid var(--color-blue-600)}.asggen-iNmPF4j{background-color:var(--color-white-100);box-shadow:var(--shadow-medium);color:var(--color-black-500);padding:.75rem 2rem}.asggen-FaJ4Ou8{height:auto;left:0;margin:0 auto;position:fixed;top:0;transition:all .3s ease;width:100%;z-index:100}.asggen-FaJ4Ou8.asggen-zfxwI26{background:var(--light);background-color:rgba(var(--light),.2);box-shadow:var(--shadow-medium)}.asggen-FaJ4Ou8.asggen-zfxwI26,.asggen-QfNYU76{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--color-blue-800)}.asggen-QfNYU76{background-color:rgba(#ffffff,.2);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.asggen-b2RQ1kV{align-items:center;column-gap:1.25rem;display:flex;flex-direction:row;height:4.25rem;justify-content:flex-start;margin:0 auto;width:100%}.asggen-EVWqcuk{font-family:inherit;font-size:1.6rem;font-weight:600;letter-spacing:-1px;line-height:1.5;margin-bottom:0}.asggen-b2RQ1kV.asggen-yYmSvug{margin-bottom:0;padding:0 1.25rem}.asggen-b2RQ1kV.asggen-yYmSvug a:hover{border-bottom:2px solid var(--color-black-800)}.asggen-DIqmOCa.asggen-uIPgGK7{padding:.5rem 1.5rem}.asggen-DIqmOCa.asggen-uIPgGK7:hover{background-color:rgba(35,39,47,.05);border-bottom:none!important;border-radius:3rem}.asggen-F6t44Vy{background-color:var(--light);box-shadow:var(--shadow-medium);height:auto;left:0;position:fixed;top:-100%;width:100%}.asggen-F6t44Vy.asggen-E8o0IXn{border-top:1px solid var(--color-blue-800);height:100vh;top:68px;width:100%}.asggen-F6t44Vy.asggen-E8o0IXn .asggen-yMiHRly{border-bottom:.75px solid #000;gap:.2rem;padding:1rem}.asggen-F6t44Vy.asggen-hcpN3fG{opacity:0;transition:opacity .4s ease-in-out;visibility:hidden}.asggen-yMiHRly{display:flex;justify-content:space-around;overflow-x:auto;row-gap:1.25rem;-ms-overflow-style:none;scrollbar-width:none}.asggen-yMiHRly::-webkit-scrollbar{display:none}.asggen-DIqmOCa{font-size:1rem;line-height:1.5;text-transform:uppercase}.asggen-DIqmOCa,.asggen-YFITMpr{font-family:inherit;font-weight:500;margin-bottom:0}.asggen-YFITMpr{background-color:var(--color-blue-600);border-radius:.75rem;box-shadow:var(--shadow-medium);color:var(--light);display:inline-block;font-size:.875rem;line-height:1.25;margin-left:auto;padding:.65rem 1.5rem;text-align:center;text-transform:capitalize;user-select:none;white-space:nowrap}@media only screen and (min-width:48rem){.asggen-F6t44Vy{background:none;box-shadow:none;height:auto;margin-left:auto;padding:0;position:relative;top:0;transition:none;width:auto}.asggen-F6t44Vy.asggen-hcpN3fG{opacity:1;transition:opacity .4s ease-in-out;visibility:visible}.asggen-yMiHRly{column-gap:2rem;display:flex;flex-direction:row;margin:0 auto}.asggen-DIqmOCa{text-transform:capitalize}.asggen-YFITMpr{margin-left:2rem}}.asggen-LsM7ZjZ{background:none;border:none;cursor:pointer;display:block;height:1.15rem;order:-1;outline:none;position:relative;transform:rotate(0deg);transition:.35s ease;user-select:none;visibility:visible;width:1.6rem;z-index:10}@media only screen and (min-width:48rem){.asggen-LsM7ZjZ{display:none;visibility:hidden}}.asggen-_Tz4jNZ{background-color:var(--color-black-800);border:none;border-radius:1rem;display:block;height:2px;left:0;opacity:1;outline:none;position:absolute;transform:rotate(0deg);transition:.25s ease-in-out;width:100%}.asggen-_Tz4jNZ:first-child{top:0}.asggen-_Tz4jNZ:nth-child(2){top:.5rem;width:70%}.asggen-_Tz4jNZ:nth-child(3){top:1rem}.asggen-LsM7ZjZ.asggen-E8o0IXn .asggen-_Tz4jNZ:first-child{top:.5rem;transform:rotate(135deg)}.asggen-LsM7ZjZ.asggen-E8o0IXn .asggen-_Tz4jNZ:nth-child(2){opacity:0;visibility:hidden}.asggen-LsM7ZjZ.asggen-E8o0IXn .asggen-_Tz4jNZ:nth-child(3){top:.5rem;transform:rotate(-135deg)}.asggen-Y2cbpWB{align-items:center;display:grid;padding:0 1rem;position:relative;row-gap:3rem}@media only screen and (min-width:48rem){.asggen-Y2cbpWB{grid-template-columns:repeat(2,minmax(0,1fr));justify-content:center}}@media only screen and (min-width:64rem){.asggen-Y2cbpWB{column-gap:4rem;grid-template-columns:1fr max-content;margin-top:3rem}}@keyframes asggen-tnBiLe1{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.asggen-lxgipYD{display:block;height:18rem;justify-self:center;margin-top:2rem;max-width:18rem;object-fit:cover}@media only screen and (min-width:48rem){.asggen-lxgipYD{height:20rem;max-width:20rem;order:1}}@media only screen and (min-width:64rem){.asggen-lxgipYD{height:25rem;margin-right:1rem;max-width:25rem}}.asggen-Dz7DCBs{align-items:flex-start;display:flex;flex-direction:column;row-gap:1.75rem}.asggen-vOcQaWi{background-color:#fff;color:#333;overflow:hidden;padding:2.5rem 0;position:relative}.asggen-vOcQaWi:before{color:rgba(0,0,0,.05);content:"AFront";font-size:20rem;left:50%;pointer-events:none;position:absolute;top:70%;transform:translate(-50%,-50%);white-space:nowrap;z-index:0}.asggen-Kou5AQf{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:space-between;margin:0 auto;max-width:75rem;padding:0 1.25rem;position:relative;z-index:1}.asggen-qKHdMcH{flex:1;margin-bottom:2rem}.asggen-slMjjDc{color:var(--color-black-400);font-size:1.5rem;font-weight:700;text-decoration:none}.asggen-cazhRP1{color:#8b8b8b;font-size:.875rem;margin-top:.625rem}.asggen-a78uDCQ{display:flex;flex:2;flex-wrap:wrap;justify-content:space-between}.asggen-_UtUx79{flex:1;margin-bottom:2rem;min-width:12rem}.asggen-N07cS94{color:#777;font-size:1rem;margin-bottom:.625rem}.asggen-vfO0fUG{list-style:none;padding:0}.asggen-iRs41ng{color:#909090;display:block;font-size:.875rem;margin-bottom:.5rem;text-decoration:none;transition:color .3s ease}.asggen-iRs41ng:hover{color:#3a3a3a}.asggen-w3fUm2Q{color:#777;font-size:.875rem;margin-top:2.5rem;text-align:center}.asggen-FTFjC4T{margin-bottom:.625rem}.asggen-HczpTuP{display:flex;flex-wrap:wrap;justify-content:center}.asggen-rUwKNuA{color:#909090;font-size:1.125rem;margin:0 .625rem;text-decoration:none;transition:color .3s ease}.asggen-rUwKNuA:hover{color:#3a3a3a}@media (max-width:768px){.asggen-Kou5AQf,.asggen-a78uDCQ{align-items:center;flex-direction:column}.asggen-a78uDCQ{text-align:center}.asggen-_UtUx79{margin-bottom:1.5rem}.asggen-FTFjC4T{font-size:.75rem}.asggen-HczpTuP{margin-top:1rem}.asggen-rUwKNuA{font-size:1rem;margin:0 .5rem}.asggen-vOcQaWi:before{content:"AFront";font-size:5rem;top:82%}}
@@ -1 +0,0 @@
1
- (self.webpackChunkafront=self.webpackChunkafront||[]).push([[3],{572:(e,t,a)=>{const{useEffect:n}=a(540);function s(e,t){if(t){let a=document.querySelector(`meta[name="${e}"]`);a?a.setAttribute("content",t):(a=document.createElement("meta"),a.setAttribute("name",e),a.setAttribute("content",t),document.head.appendChild(a))}}e.exports=function({title:e,description:t,keywords:a,context:r}){n((()=>{"undefined"!=typeof document&&(document.title=e,s("title",e),s("description",t),s("keywords",a))}),[e,t,a]),r&&(r.title=e,r.description=t,r.keywords=a)}},210:(e,t,a)=>{"use strict";a.d(t,{A:()=>r});var n=a(540),s="asggen-UsaK2zv";const r=function(e){var t=e.children;return n.createElement("div",{className:"asggen-y0_CWMe"},n.createElement("div",{className:"asggen-wv3xAF6"},n.createElement("div",{className:"".concat(s," ").concat("asggen-F7uI_Qg")}),n.createElement("div",{className:"".concat(s," ").concat("asggen-HPCM5Cq")}),n.createElement("div",{className:"".concat(s," ").concat("asggen-oGWLGVI")}),n.createElement("div",{className:"".concat(s," ").concat("asggen-hpj3_CH")})),t)}},3:(e,t,a)=>{"use strict";a.r(t),a.d(t,{default:()=>m});var n=a(540),s=a(572),r=a.n(s),c="asggen-fs7zTHj",o="asggen-kTCHPjF",l="asggen-ZHWXW17",i=a(210);const m=function(e){var t=e.context;return r()({title:"Support - AFront",description:"Get support for AFront, a front-end JavaScript library for seamless server-side rendering.",keywords:"support, AFront, server-side rendering, JavaScript",context:t}),n.createElement(i.A,null,n.createElement("div",{className:"asggen-kJBmVCe"},n.createElement("h1",{className:"asggen-xhjDCMD"},"Need Assistance?"),n.createElement("p",{className:"asggen-RwTbVGb"},"AFront is a cutting-edge front-end JavaScript library designed for seamless server-side rendering (SSR). We're committed to providing you with top-notch support to ensure your experience is smooth and productive."),n.createElement("div",{className:"asggen-_9xGCTU"},n.createElement("div",{className:c},n.createElement("h2",{className:l},"Technical Assistance"),n.createElement("p",{className:o},"Our dedicated technical support team is available around the clock to resolve any issues you may face with AFront. Connect with us through email or our support portal for prompt assistance.")),n.createElement("div",{className:c},n.createElement("h2",{className:l},"Product Information"),n.createElement("p",{className:o},"Curious about AFront’s capabilities? Reach out to our sales team for detailed insights on features, benefits, and how our library can enhance your web development projects.")),n.createElement("div",{className:c},n.createElement("h2",{className:l},"Community and Forums"),n.createElement("p",{className:o},"Join our vibrant community forums to discuss AFront with fellow developers, exchange tips, and troubleshoot common issues collaboratively."))),n.createElement("div",{className:"asggen-pmghQyO"},n.createElement("h2",{className:l},"Frequently Asked Questions"),n.createElement("ul",{className:"asggen-F8poZey"},n.createElement("li",null,"What is AFront and how does it work?"),n.createElement("li",null,"How do I get started with AFront?"),n.createElement("li",null,"Where can I find documentation and tutorials?"),n.createElement("li",null,"How can I report a bug or request a feature?"))),n.createElement("a",{href:"/",className:"asggen-cwDmzqU"},"Back to Homepage")))}}}]);
@@ -1 +0,0 @@
1
- (self.webpackChunkafront=self.webpackChunkafront||[]).push([[41],{572:(e,t,n)=>{const{useEffect:a}=n(540);function c(e,t){if(t){let n=document.querySelector(`meta[name="${e}"]`);n?n.setAttribute("content",t):(n=document.createElement("meta"),n.setAttribute("name",e),n.setAttribute("content",t),document.head.appendChild(n))}}e.exports=function({title:e,description:t,keywords:n,context:s}){a((()=>{"undefined"!=typeof document&&(document.title=e,c("title",e),c("description",t),c("keywords",n))}),[e,t,n]),s&&(s.title=e,s.description=t,s.keywords=n)}},210:(e,t,n)=>{"use strict";n.d(t,{A:()=>s});var a=n(540),c="asggen-UsaK2zv";const s=function(e){var t=e.children;return a.createElement("div",{className:"asggen-y0_CWMe"},a.createElement("div",{className:"asggen-wv3xAF6"},a.createElement("div",{className:"".concat(c," ").concat("asggen-F7uI_Qg")}),a.createElement("div",{className:"".concat(c," ").concat("asggen-HPCM5Cq")}),a.createElement("div",{className:"".concat(c," ").concat("asggen-oGWLGVI")}),a.createElement("div",{className:"".concat(c," ").concat("asggen-hpj3_CH")})),t)}},488:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var a=n(540),c=n(210);const s=n.p+"static/media/52f06bb716d4ecad087a.png",r=n.p+"static/media/adeaead125c45715106d.svg";var l=n(572),o=n.n(l),m=n(833);const i=function(e){var t=e.context;return o()({title:"AFront by Asggen Inc.",description:"Home for all AFront products and services.",keywords:"Home, Afront, help",context:t}),a.createElement(c.A,null,a.createElement("main",null,a.createElement("section",{className:m.uW},a.createElement("div",{className:"".concat(m.kL," ").concat(m.vd)},a.createElement("img",{className:m._e,src:s,alt:"banner"}),a.createElement("div",{className:m.B4},a.createElement("h1",{className:m.nX},"Empower Your Front-End with AFront"),a.createElement("p",{className:m.FY},"AFront streamlines front-end development with robust tools and",a.createElement("b",null," seamless server-side rendering (SSSR)"),". Build dynamic, high-performance web experiences effortlessly."),a.createElement("div",null,a.createElement("a",{href:"/",className:"".concat(m.OK," ").concat(m.DG)},"Get Started"," ",a.createElement("img",{className:m.h_,src:r}))))))))}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunkafront=self.webpackChunkafront||[]).push([[573],{573:(e,a,s)=>{s.r(a),s.d(a,{default:()=>n});var t=s(540);const n=function(){return t.createElement("div",{className:"asggen-CTEvvlo"},t.createElement("h2",{className:"asggen-FVOWslk"},"Oops! The page you're looking for doesn't exist."),t.createElement("p",{className:"asggen-Bk8OzYB"},"It seems you’ve taken a wrong turn. Let’s get you back on track!"),t.createElement("a",{href:"/",className:"asggen-wbWn6vo"},"Go to Homepage"))}}}]);