@hotwyl/init-docker-minimal-dev 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.
- package/LICENSE +21 -0
- package/README.md +0 -0
- package/bin/cli.js +82 -0
- package/package.json +27 -0
- package/template/.env +22 -0
- package/template/Dockerfile +73 -0
- package/template/README.md +532 -0
- package/template/apache/.gitkeep +1 -0
- package/template/config/apache/000-default.conf +39 -0
- package/template/config/mysql/init/01-init.sql +42 -0
- package/template/config/mysql/my.cnf +33 -0
- package/template/config/php/php.ini +95 -0
- package/template/docker-compose.yml +89 -0
- package/template/www/.htaccess +181 -0
- package/template/www/errors/403.html +48 -0
- package/template/www/errors/404.html +48 -0
- package/template/www/errors/500.html +48 -0
- package/template/www/index.php +501 -0
- package/template/www/phpinfo.php +10 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* MinimalDev - Página Inicial
|
|
4
|
+
* Ambiente de Desenvolvimento Docker
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ============================================
|
|
8
|
+
// Headers de Segurança
|
|
9
|
+
// ============================================
|
|
10
|
+
header('X-Content-Type-Options: nosniff');
|
|
11
|
+
header('X-Frame-Options: SAMEORIGIN');
|
|
12
|
+
header('X-XSS-Protection: 1; mode=block');
|
|
13
|
+
header('Referrer-Policy: strict-origin-when-cross-origin');
|
|
14
|
+
header('Permissions-Policy: geolocation=(), microphone=(), camera=()');
|
|
15
|
+
|
|
16
|
+
// Prevenir cache de informações sensíveis
|
|
17
|
+
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
|
18
|
+
header('Pragma: no-cache');
|
|
19
|
+
|
|
20
|
+
// Iniciar sessão segura
|
|
21
|
+
if (session_status() === PHP_SESSION_NONE) {
|
|
22
|
+
ini_set('session.cookie_httponly', 1);
|
|
23
|
+
ini_set('session.use_only_cookies', 1);
|
|
24
|
+
ini_set('session.cookie_samesite', 'Strict');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ============================================
|
|
28
|
+
// Funções de Segurança
|
|
29
|
+
// ============================================
|
|
30
|
+
function sanitize($data)
|
|
31
|
+
{
|
|
32
|
+
return htmlspecialchars(strip_tags(trim($data)), ENT_QUOTES, 'UTF-8');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function generateCSRFToken()
|
|
36
|
+
{
|
|
37
|
+
if (empty($_SESSION['csrf_token'])) {
|
|
38
|
+
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
|
39
|
+
}
|
|
40
|
+
return $_SESSION['csrf_token'];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================
|
|
44
|
+
// Verificar conexão com MySQL
|
|
45
|
+
// ============================================
|
|
46
|
+
$dbStatus = false;
|
|
47
|
+
$dbError = '';
|
|
48
|
+
try {
|
|
49
|
+
$pdo = new PDO(
|
|
50
|
+
'mysql:host=mysql;dbname=minimaldev;charset=utf8mb4',
|
|
51
|
+
'developer',
|
|
52
|
+
'developer123',
|
|
53
|
+
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
|
|
54
|
+
);
|
|
55
|
+
$dbStatus = true;
|
|
56
|
+
} catch (PDOException $e) {
|
|
57
|
+
$dbError = $e->getMessage();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Informações do ambiente
|
|
61
|
+
$phpVersion = phpversion();
|
|
62
|
+
$apacheVersion = function_exists('apache_get_version') ? apache_get_version() : 'Apache (via Docker)';
|
|
63
|
+
$extensions = get_loaded_extensions();
|
|
64
|
+
sort($extensions);
|
|
65
|
+
?>
|
|
66
|
+
<!DOCTYPE html>
|
|
67
|
+
<html lang="pt-BR">
|
|
68
|
+
|
|
69
|
+
<head>
|
|
70
|
+
<meta charset="UTF-8">
|
|
71
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
72
|
+
<title>MinimalDev - Ambiente de Desenvolvimento</title>
|
|
73
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
74
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" rel="stylesheet">
|
|
75
|
+
<style>
|
|
76
|
+
:root {
|
|
77
|
+
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
78
|
+
--success-color: #28a745;
|
|
79
|
+
--danger-color: #dc3545;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
body {
|
|
83
|
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
84
|
+
min-height: 100vh;
|
|
85
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.hero {
|
|
89
|
+
background: var(--primary-gradient);
|
|
90
|
+
color: white;
|
|
91
|
+
padding: 3rem 0;
|
|
92
|
+
margin-bottom: 2rem;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.hero h1 {
|
|
96
|
+
font-size: 2.5rem;
|
|
97
|
+
font-weight: 700;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.card {
|
|
101
|
+
border: none;
|
|
102
|
+
border-radius: 15px;
|
|
103
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
|
104
|
+
transition: transform 0.3s ease;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.card:hover {
|
|
108
|
+
transform: translateY(-5px);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.card-header {
|
|
112
|
+
background: var(--primary-gradient);
|
|
113
|
+
color: white;
|
|
114
|
+
border-radius: 15px 15px 0 0 !important;
|
|
115
|
+
font-weight: 600;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.status-badge {
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
padding: 0.5rem 1rem;
|
|
122
|
+
border-radius: 50px;
|
|
123
|
+
font-weight: 500;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.status-online {
|
|
127
|
+
background: rgba(40, 167, 69, 0.15);
|
|
128
|
+
color: var(--success-color);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.status-offline {
|
|
132
|
+
background: rgba(220, 53, 69, 0.15);
|
|
133
|
+
color: var(--danger-color);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.service-card {
|
|
137
|
+
text-align: center;
|
|
138
|
+
padding: 1.5rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.service-icon {
|
|
142
|
+
font-size: 3rem;
|
|
143
|
+
margin-bottom: 1rem;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.extension-badge {
|
|
147
|
+
background: #e9ecef;
|
|
148
|
+
padding: 0.3rem 0.6rem;
|
|
149
|
+
border-radius: 5px;
|
|
150
|
+
margin: 0.2rem;
|
|
151
|
+
display: inline-block;
|
|
152
|
+
font-size: 0.85rem;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.quick-link {
|
|
156
|
+
display: block;
|
|
157
|
+
padding: 1rem;
|
|
158
|
+
background: #f8f9fa;
|
|
159
|
+
border-radius: 10px;
|
|
160
|
+
text-decoration: none;
|
|
161
|
+
color: #333;
|
|
162
|
+
margin-bottom: 0.5rem;
|
|
163
|
+
transition: all 0.3s ease;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.quick-link:hover {
|
|
167
|
+
background: var(--primary-gradient);
|
|
168
|
+
color: white;
|
|
169
|
+
transform: translateX(5px);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
footer {
|
|
173
|
+
background: #2d3748;
|
|
174
|
+
color: #a0aec0;
|
|
175
|
+
padding: 2rem 0;
|
|
176
|
+
margin-top: 3rem;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
footer a {
|
|
180
|
+
color: #667eea;
|
|
181
|
+
text-decoration: none;
|
|
182
|
+
transition: color 0.3s ease;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
footer a:hover {
|
|
186
|
+
color: #764ba2;
|
|
187
|
+
text-decoration: underline;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.developer-credit {
|
|
191
|
+
border-top: 1px solid #4a5568;
|
|
192
|
+
padding-top: 1rem;
|
|
193
|
+
margin-top: 1rem;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.cta-section {
|
|
197
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
198
|
+
border-radius: 15px;
|
|
199
|
+
padding: 2.5rem;
|
|
200
|
+
margin-top: 2rem;
|
|
201
|
+
text-align: center;
|
|
202
|
+
color: white;
|
|
203
|
+
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.cta-section h4 {
|
|
207
|
+
font-weight: 700;
|
|
208
|
+
margin-bottom: 1rem;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.cta-section p {
|
|
212
|
+
opacity: 0.9;
|
|
213
|
+
margin-bottom: 1.5rem;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.cta-button {
|
|
217
|
+
display: inline-block;
|
|
218
|
+
padding: 1rem 2.5rem;
|
|
219
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
220
|
+
color: white;
|
|
221
|
+
text-decoration: none;
|
|
222
|
+
border-radius: 50px;
|
|
223
|
+
font-weight: 600;
|
|
224
|
+
font-size: 1.1rem;
|
|
225
|
+
transition: all 0.3s ease;
|
|
226
|
+
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.cta-button:hover {
|
|
230
|
+
transform: translateY(-3px);
|
|
231
|
+
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.6);
|
|
232
|
+
color: white;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.cta-button i {
|
|
236
|
+
margin-right: 0.5rem;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.code-block {
|
|
240
|
+
background: #2d3748;
|
|
241
|
+
color: #e2e8f0;
|
|
242
|
+
padding: 0.5rem 1rem;
|
|
243
|
+
border-radius: 5px;
|
|
244
|
+
font-family: 'Consolas', monospace;
|
|
245
|
+
font-size: 0.9rem;
|
|
246
|
+
}
|
|
247
|
+
</style>
|
|
248
|
+
</head>
|
|
249
|
+
|
|
250
|
+
<body>
|
|
251
|
+
<!-- Hero Section -->
|
|
252
|
+
<section class="hero text-center">
|
|
253
|
+
<div class="container">
|
|
254
|
+
<h1><i class="bi bi-box-seam me-2"></i>MinimalDev</h1>
|
|
255
|
+
<p class="lead mb-0">Ambiente de Desenvolvimento Docker - PHP, MySQL, Node.js & Apache</p>
|
|
256
|
+
</div>
|
|
257
|
+
</section>
|
|
258
|
+
|
|
259
|
+
<div class="container">
|
|
260
|
+
<!-- Status dos Serviços -->
|
|
261
|
+
<div class="row mb-4">
|
|
262
|
+
<div class="col-12">
|
|
263
|
+
<h3 class="mb-3"><i class="bi bi-activity me-2"></i>Status dos Serviços</h3>
|
|
264
|
+
</div>
|
|
265
|
+
|
|
266
|
+
<!-- PHP -->
|
|
267
|
+
<div class="col-md-3 col-sm-6 mb-3">
|
|
268
|
+
<div class="card service-card h-100">
|
|
269
|
+
<div class="service-icon text-primary"><i class="bi bi-filetype-php"></i></div>
|
|
270
|
+
<h5>PHP</h5>
|
|
271
|
+
<p class="text-muted mb-2">v<?php echo $phpVersion ?></p>
|
|
272
|
+
<span class="status-badge status-online">
|
|
273
|
+
<i class="bi bi-check-circle me-1"></i> Online
|
|
274
|
+
</span>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
<!-- MySQL -->
|
|
279
|
+
<div class="col-md-3 col-sm-6 mb-3">
|
|
280
|
+
<div class="card service-card h-100">
|
|
281
|
+
<div class="service-icon text-warning"><i class="bi bi-database"></i></div>
|
|
282
|
+
<h5>MySQL</h5>
|
|
283
|
+
<p class="text-muted mb-2">Porta: 3306</p>
|
|
284
|
+
<?php if ($dbStatus): ?>
|
|
285
|
+
<span class="status-badge status-online">
|
|
286
|
+
<i class="bi bi-check-circle me-1"></i> Conectado
|
|
287
|
+
</span>
|
|
288
|
+
<?php else: ?>
|
|
289
|
+
<span class="status-badge status-offline">
|
|
290
|
+
<i class="bi bi-x-circle me-1"></i> Offline
|
|
291
|
+
</span>
|
|
292
|
+
<?php endif; ?>
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
|
|
296
|
+
<!-- Apache -->
|
|
297
|
+
<div class="col-md-3 col-sm-6 mb-3">
|
|
298
|
+
<div class="card service-card h-100">
|
|
299
|
+
<div class="service-icon text-danger"><i class="bi bi-server"></i></div>
|
|
300
|
+
<h5>Apache</h5>
|
|
301
|
+
<p class="text-muted mb-2">Porta: 80</p>
|
|
302
|
+
<span class="status-badge status-online">
|
|
303
|
+
<i class="bi bi-check-circle me-1"></i> Online
|
|
304
|
+
</span>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
<!-- Node.js -->
|
|
309
|
+
<div class="col-md-3 col-sm-6 mb-3">
|
|
310
|
+
<div class="card service-card h-100">
|
|
311
|
+
<div class="service-icon text-success"><i class="bi bi-node-plus"></i></div>
|
|
312
|
+
<h5>Node.js</h5>
|
|
313
|
+
<p class="text-muted mb-2">Container disponível</p>
|
|
314
|
+
<span class="status-badge status-online">
|
|
315
|
+
<i class="bi bi-check-circle me-1"></i> Pronto
|
|
316
|
+
</span>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<div class="row">
|
|
322
|
+
<!-- Links Rápidos -->
|
|
323
|
+
<div class="col-lg-4 mb-4">
|
|
324
|
+
<div class="card h-100">
|
|
325
|
+
<div class="card-header">
|
|
326
|
+
<i class="bi bi-lightning me-2"></i>Links Rápidos
|
|
327
|
+
</div>
|
|
328
|
+
<div class="card-body">
|
|
329
|
+
<a href="http://localhost:8080" target="_blank" class="quick-link">
|
|
330
|
+
<i class="bi bi-table me-2"></i>phpMyAdmin
|
|
331
|
+
</a>
|
|
332
|
+
<a href="/phpinfo.php" target="_blank" class="quick-link">
|
|
333
|
+
<i class="bi bi-info-circle me-2"></i>PHP Info
|
|
334
|
+
</a>
|
|
335
|
+
<a href="https://www.php.net/docs.php" target="_blank" class="quick-link">
|
|
336
|
+
<i class="bi bi-book me-2"></i>Documentação PHP
|
|
337
|
+
</a>
|
|
338
|
+
<a href="https://dev.mysql.com/doc/" target="_blank" class="quick-link">
|
|
339
|
+
<i class="bi bi-book me-2"></i>Documentação MySQL
|
|
340
|
+
</a>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
|
|
345
|
+
<!-- Extensões PHP -->
|
|
346
|
+
<div class="col-lg-8 mb-4">
|
|
347
|
+
<div class="card h-100">
|
|
348
|
+
<div class="card-header">
|
|
349
|
+
<i class="bi bi-puzzle me-2"></i>Extensões PHP Instaladas (<?php echo count($extensions) ?>)
|
|
350
|
+
</div>
|
|
351
|
+
<div class="card-body">
|
|
352
|
+
<?php foreach ($extensions as $ext): ?>
|
|
353
|
+
<span class="extension-badge"><?php echo htmlspecialchars($ext) ?></span>
|
|
354
|
+
<?php endforeach; ?>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
</div>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<!-- Informações de Conexão -->
|
|
361
|
+
<div class="row">
|
|
362
|
+
<div class="col-12 mb-4">
|
|
363
|
+
<div class="card">
|
|
364
|
+
<div class="card-header">
|
|
365
|
+
<i class="bi bi-gear me-2"></i>Configurações de Conexão
|
|
366
|
+
</div>
|
|
367
|
+
<div class="card-body">
|
|
368
|
+
<div class="row">
|
|
369
|
+
<div class="col-md-6">
|
|
370
|
+
<h6><i class="bi bi-database me-2"></i>MySQL</h6>
|
|
371
|
+
<table class="table table-sm">
|
|
372
|
+
<tr>
|
|
373
|
+
<td><strong>Host:</strong></td>
|
|
374
|
+
<td><code>mysql</code> (interno) / <code>localhost</code> (externo)</td>
|
|
375
|
+
</tr>
|
|
376
|
+
<tr>
|
|
377
|
+
<td><strong>Porta:</strong></td>
|
|
378
|
+
<td><code>3306</code></td>
|
|
379
|
+
</tr>
|
|
380
|
+
<tr>
|
|
381
|
+
<td><strong>Usuário:</strong></td>
|
|
382
|
+
<td><code>developer</code></td>
|
|
383
|
+
</tr>
|
|
384
|
+
<tr>
|
|
385
|
+
<td><strong>Senha:</strong></td>
|
|
386
|
+
<td><code>developer123</code></td>
|
|
387
|
+
</tr>
|
|
388
|
+
<tr>
|
|
389
|
+
<td><strong>Database:</strong></td>
|
|
390
|
+
<td><code>minimaldev</code></td>
|
|
391
|
+
</tr>
|
|
392
|
+
</table>
|
|
393
|
+
</div>
|
|
394
|
+
<div class="col-md-6">
|
|
395
|
+
<h6><i class="bi bi-globe me-2"></i>URLs de Acesso</h6>
|
|
396
|
+
<table class="table table-sm">
|
|
397
|
+
<tr>
|
|
398
|
+
<td><strong>Website:</strong></td>
|
|
399
|
+
<td><a href="http://localhost">http://localhost</a></td>
|
|
400
|
+
</tr>
|
|
401
|
+
<tr>
|
|
402
|
+
<td><strong>phpMyAdmin:</strong></td>
|
|
403
|
+
<td><a href="http://localhost:8080">http://localhost:8080</a></td>
|
|
404
|
+
</tr>
|
|
405
|
+
</table>
|
|
406
|
+
|
|
407
|
+
<h6 class="mt-3"><i class="bi bi-terminal me-2"></i>Comandos Úteis</h6>
|
|
408
|
+
<p class="code-block mb-1">docker exec -it minimaldev-node npm -v</p>
|
|
409
|
+
<p class="code-block">docker exec -it minimaldev-web composer -V</p>
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
|
|
417
|
+
<!-- Projetos -->
|
|
418
|
+
<div class="row">
|
|
419
|
+
<div class="col-12">
|
|
420
|
+
<div class="card">
|
|
421
|
+
<div class="card-header">
|
|
422
|
+
<i class="bi bi-folder me-2"></i>Seus Projetos
|
|
423
|
+
</div>
|
|
424
|
+
<div class="card-body">
|
|
425
|
+
<p class="text-muted">
|
|
426
|
+
Coloque seus projetos na pasta <code>www/</code> para acessá-los automaticamente.<br>
|
|
427
|
+
Exemplo: <code>www/meu-projeto/</code> → <a
|
|
428
|
+
href="http://localhost/meu-projeto/">http://localhost/meu-projeto/</a>
|
|
429
|
+
</p>
|
|
430
|
+
|
|
431
|
+
<h6>Projetos encontrados:</h6>
|
|
432
|
+
<div class="row">
|
|
433
|
+
<?php
|
|
434
|
+
$directories = array_filter(glob('*'), 'is_dir');
|
|
435
|
+
if (empty($directories)):
|
|
436
|
+
?>
|
|
437
|
+
<div class="col-12">
|
|
438
|
+
<div class="alert alert-info">
|
|
439
|
+
<i class="bi bi-info-circle me-2"></i>
|
|
440
|
+
Nenhum projeto encontrado. Crie uma pasta dentro de <code>www/</code> para começar!
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
<?php else: ?>
|
|
444
|
+
<?php foreach ($directories as $dir): ?>
|
|
445
|
+
<div class="col-md-3 col-sm-6 mb-2">
|
|
446
|
+
<a href="/<?php echo htmlspecialchars($dir) ?>/" class="quick-link">
|
|
447
|
+
<i class="bi bi-folder2-open me-2"></i><?php echo htmlspecialchars($dir) ?>
|
|
448
|
+
</a>
|
|
449
|
+
</div>
|
|
450
|
+
<?php endforeach; ?>
|
|
451
|
+
<?php endif; ?>
|
|
452
|
+
</div>
|
|
453
|
+
</div>
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
457
|
+
|
|
458
|
+
<!-- CTA Section - Grupo 3W Online -->
|
|
459
|
+
<div class="row">
|
|
460
|
+
<div class="col-12">
|
|
461
|
+
<div class="cta-section">
|
|
462
|
+
<h4><i class="bi bi-rocket-takeoff me-2"></i>Precisa de um Site ou Sistema Personalizado?</h4>
|
|
463
|
+
<p>
|
|
464
|
+
O <strong>Grupo 3W Online</strong> desenvolve sites e sistemas sob demanda,
|
|
465
|
+
com soluções personalizadas para o seu negócio.
|
|
466
|
+
Transforme suas ideias em realidade digital!
|
|
467
|
+
</p>
|
|
468
|
+
<a href="https://www.3wonline.com.br" target="_blank" rel="noopener noreferrer" class="cta-button">
|
|
469
|
+
<i class="bi bi-globe"></i>Conheça a 3W Online
|
|
470
|
+
</a>
|
|
471
|
+
</div>
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
</div>
|
|
475
|
+
|
|
476
|
+
<!-- Footer -->
|
|
477
|
+
<footer class="text-center">
|
|
478
|
+
<div class="container">
|
|
479
|
+
<p class="mb-1">
|
|
480
|
+
<strong>MinimalDev</strong> - Ambiente de Desenvolvimento Docker
|
|
481
|
+
</p>
|
|
482
|
+
<p class="mb-2">
|
|
483
|
+
PHP <?php echo sanitize($phpVersion) ?> | MySQL | Node.js | Apache |
|
|
484
|
+
<i class="bi bi-heart-fill text-danger"></i> Desenvolvido para facilitar sua vida
|
|
485
|
+
</p>
|
|
486
|
+
<div class="developer-credit">
|
|
487
|
+
<p class="mb-1">
|
|
488
|
+
<i class="bi bi-code-slash me-1"></i>
|
|
489
|
+
Sistema desenvolvido por <strong>Hotwyl - WillFromBrasil</strong>
|
|
490
|
+
</p>
|
|
491
|
+
<a href="https://www.linkedin.com/in/william-camargo-dev/" target="_blank" rel="noopener noreferrer">
|
|
492
|
+
<i class="bi bi-linkedin me-1"></i>LinkedIn - William Camargo
|
|
493
|
+
</a>
|
|
494
|
+
</div>
|
|
495
|
+
</div>
|
|
496
|
+
</footer>
|
|
497
|
+
|
|
498
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
499
|
+
</body>
|
|
500
|
+
|
|
501
|
+
</html>
|