@rellcodes16/devkit 1.0.0

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.
@@ -0,0 +1,172 @@
1
+ export function reactAppJsx(appname, options) {
2
+ const imports = [];
3
+ const routerImport = options.router
4
+ ? `import { BrowserRouter, Routes, Route } from "react-router-dom";`
5
+ : "";
6
+
7
+ if (routerImport) imports.push(routerImport);
8
+
9
+ const homeComponent = `
10
+ function Home() {
11
+ return (
12
+ <div className="min-h-screen bg-gray-50 flex items-center justify-center">
13
+ <div className="text-center">
14
+ <h1 className="text-4xl font-bold text-gray-900 mb-2">${appname}</h1>
15
+ <p className="text-gray-500">Your app is ready. Start building.</p>
16
+ </div>
17
+ </div>
18
+ );
19
+ }`;
20
+
21
+ const simpleBody = `
22
+ return (
23
+ <div className="min-h-screen bg-gray-50 flex items-center justify-center">
24
+ <div className="text-center">
25
+ <h1 className="text-4xl font-bold text-gray-900 mb-2">${appname}</h1>
26
+ <p className="text-gray-500">Your app is ready. Start building.</p>
27
+ </div>
28
+ </div>
29
+ );`;
30
+
31
+ const routerBody = `
32
+ return (
33
+ <BrowserRouter>
34
+ <Routes>
35
+ <Route path="/" element={<Home />} />
36
+ </Routes>
37
+ </BrowserRouter>
38
+ );`;
39
+
40
+ const body = options.router ? routerBody : simpleBody;
41
+ const extras = options.router ? homeComponent : "";
42
+
43
+ return `${imports.join("\n")}
44
+ ${extras}
45
+ export default function App() {${body}
46
+ }
47
+ `;
48
+ }
49
+
50
+ export function reactIndexCss() {
51
+ return `@import "tailwindcss";
52
+
53
+ /* Custom base styles */
54
+ *, *::before, *::after {
55
+ box-sizing: border-box;
56
+ }
57
+
58
+ body {
59
+ margin: 0;
60
+ font-family: Inter, system-ui, -apple-system, sans-serif;
61
+ -webkit-font-smoothing: antialiased;
62
+ -moz-osx-font-smoothing: grayscale;
63
+ }
64
+ `;
65
+ }
66
+
67
+ export function reactViteConfig() {
68
+ return `import { defineConfig } from "vite";
69
+ import react from "@vitejs/plugin-react";
70
+ import tailwindcss from "@tailwindcss/vite";
71
+
72
+ export default defineConfig({
73
+ plugins: [react(), tailwindcss()],
74
+ });
75
+ `;
76
+ }
77
+
78
+ export function reactGitignore() {
79
+ return `node_modules/
80
+ dist/
81
+ .env
82
+ .env.local
83
+ *.log
84
+ .DS_Store
85
+ `;
86
+ }
87
+
88
+ export function reactEnv() {
89
+ return `VITE_API_URL=http://localhost:3000/api
90
+ `;
91
+ }
92
+
93
+ export function reactApiUtil() {
94
+ return `import axios from "axios";
95
+
96
+ const api = axios.create({
97
+ baseURL: import.meta.env.VITE_API_URL,
98
+ headers: {
99
+ "Content-Type": "application/json",
100
+ },
101
+ });
102
+
103
+ // Request interceptor — attach auth tokens, etc.
104
+ api.interceptors.request.use(
105
+ (config) => {
106
+ // const token = localStorage.getItem("token");
107
+ // if (token) config.headers.Authorization = \`Bearer \${token}\`;
108
+ return config;
109
+ },
110
+ (error) => Promise.reject(error)
111
+ );
112
+
113
+ // Response interceptor — handle global errors
114
+ api.interceptors.response.use(
115
+ (response) => response,
116
+ (error) => {
117
+ if (error.response?.status === 401) {
118
+ // Handle unauthorized — e.g. redirect to login
119
+ }
120
+ return Promise.reject(error);
121
+ }
122
+ );
123
+
124
+ export default api;
125
+ `;
126
+ }
127
+
128
+ export function reactReadme(appname, options) {
129
+ const stackLines = [
130
+ "- React + Vite",
131
+ "- Tailwind CSS v4",
132
+ "- Lucide React (icons)",
133
+ "- clsx",
134
+ ];
135
+ if (options.router) stackLines.push("- React Router DOM");
136
+ if (options.axios) stackLines.push("- Axios (pre-configured client)");
137
+
138
+ return `# ${appname}
139
+
140
+ Scaffolded with [devkit](https://github.com/rellcodes16/devkit).
141
+
142
+ ## Stack
143
+
144
+ ${stackLines.join("\n")}
145
+
146
+ ## Getting started
147
+
148
+ \`\`\`bash
149
+ cp .env.example .env
150
+ npm run dev
151
+ \`\`\`
152
+
153
+ ## Project structure
154
+
155
+ \`\`\`
156
+ src/
157
+ components/ # Reusable UI components
158
+ pages/ # Page-level components
159
+ hooks/ # Custom React hooks
160
+ utils/ # Helper functions${options.axios ? "\n api.js # Pre-configured axios instance" : ""}
161
+ assets/ # Static assets
162
+ App.jsx # Root component
163
+ main.jsx # Entry point
164
+ \`\`\`
165
+
166
+ ## Environment variables
167
+
168
+ | Variable | Description |
169
+ |---|---|
170
+ | \`VITE_API_URL\` | Backend API base URL |
171
+ `;
172
+ }
package/src/utils.js ADDED
@@ -0,0 +1,40 @@
1
+ import { execa } from "execa";
2
+ import kleur from "kleur";
3
+
4
+ export function printStep(message) {
5
+ console.log(` ${kleur.gray(message)}`);
6
+ }
7
+
8
+ export function printSuccess(message) {
9
+ console.log(`\n ${kleur.green("✔")} ${kleur.green(message)}`);
10
+ }
11
+
12
+ export function printError(message) {
13
+ console.error(`\n ${kleur.red("✖")} ${kleur.red(message)}\n`);
14
+ }
15
+
16
+ export function printDivider() {
17
+ console.log(kleur.gray(" ─────────────────────────────────────────"));
18
+ }
19
+
20
+ export async function runCommand(cmd, args, cwd, label) {
21
+ printStep(label);
22
+ try {
23
+ await execa(cmd, args, { cwd, stdio: "pipe" });
24
+ } catch (err) {
25
+ printError(`Failed: ${label}`);
26
+ console.error(err.stderr || err.message);
27
+ process.exit(1);
28
+ }
29
+ }
30
+
31
+ export function printDoneMessage(appname, devCmd, extraLines = []) {
32
+ console.log(`
33
+ ${kleur.bold().green("Project ready!")}
34
+
35
+ ${kleur.gray("Next steps:")}
36
+ ${kleur.cyan(`cd ${appname}`)}
37
+ ${kleur.cyan(devCmd)}
38
+ ${extraLines.map((l) => ` ${kleur.gray(l)}`).join("\n")}
39
+ `);
40
+ }