@icarusmx/creta 0.0.2 → 0.1.1

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/CLAUDE.md ADDED
@@ -0,0 +1,25 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is "@icarusmx/creta" - a minimal CLI tool for the Icarus software school. The project is currently in early development (v0.0.2) with basic structure in place.
8
+
9
+ ## Architecture
10
+
11
+ - **Entry point**: `bin/creta.js` - Simple Node.js CLI executable that outputs a welcome message
12
+ - **Package**: Published as `@icarusmx/creta` on npm with public access
13
+ - **Language**: JavaScript (no TypeScript)
14
+
15
+ ## Development Commands
16
+
17
+ This is a minimal CLI project without build tools, testing frameworks, or linting configured yet. The main executable can be tested directly:
18
+
19
+ ```bash
20
+ node bin/creta.js
21
+ ```
22
+
23
+ ## Current State
24
+
25
+ The CLI currently only displays "Bienvenido a Crea" - this appears to be a foundational setup awaiting feature development.
package/bin/creta.js CHANGED
@@ -1,3 +1,217 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- console.log("Bienvenido a Crea")
3
+ import { createInterface } from 'readline'
4
+ import { execSync } from 'child_process'
5
+ import fs from 'fs'
6
+ import path from 'path'
7
+
8
+ const args = process.argv.slice(2)
9
+ const command = args[0]
10
+
11
+ console.log("¡Bienvenido a Creta! 🏛️")
12
+ console.log("Aprendamos construyendo productos reales.\n")
13
+
14
+ if (!command) {
15
+ console.log("Comandos disponibles:")
16
+ console.log(" creta website - Crea tu portfolio personal (reto completo)")
17
+ console.log(" creta website-1 - Portfolio con navbar hecho")
18
+ console.log(" creta website-2 - Portfolio con navbar + hero")
19
+ console.log(" creta website-3 - Portfolio completo (solución)")
20
+ process.exit(0)
21
+ }
22
+
23
+ if (command.startsWith('website')) {
24
+ const level = command === 'website' ? 0 : parseInt(command.split('-')[1]) || 0
25
+ await createWebsiteProject(level)
26
+ } else {
27
+ console.log(`Comando no reconocido: ${command}`)
28
+ process.exit(1)
29
+ }
30
+
31
+ async function createWebsiteProject(level) {
32
+ const rl = createInterface({
33
+ input: process.stdin,
34
+ output: process.stdout
35
+ })
36
+
37
+ const askQuestion = (question) => {
38
+ return new Promise((resolve) => {
39
+ rl.question(question, resolve)
40
+ })
41
+ }
42
+
43
+ try {
44
+ const name = await askQuestion("¿Cuál es tu nombre? ")
45
+ const projectName = `${name.toLowerCase().replace(/\s+/g, '-')}-portfolio`
46
+
47
+ console.log(`\n🚀 Creando proyecto: ${projectName}`)
48
+ console.log(`📚 Nivel: ${level === 0 ? 'Reto completo' : `Con ${getLevelDescription(level)} completado`}`)
49
+
50
+ await createProjectFiles(projectName, name, level)
51
+
52
+ console.log(`\n✨ ¡Proyecto creado exitosamente!`)
53
+ console.log(`\n📁 Ingresa a tu proyecto: cd ${projectName}`)
54
+ console.log(`📦 Instala dependencias: npm install`)
55
+ console.log(`🚀 Inicia el servidor: npm run dev`)
56
+ console.log(`\n💡 Lee los comentarios en los archivos para saber qué hacer`)
57
+
58
+ rl.close()
59
+ } catch (error) {
60
+ console.error('Error:', error.message)
61
+ rl.close()
62
+ process.exit(1)
63
+ }
64
+ }
65
+
66
+ async function createProjectFiles(projectName, studentName, level) {
67
+ const __dirname = path.dirname(new URL(import.meta.url).pathname)
68
+ const templatePath = path.join(__dirname, '../templates/sveltekit-portfolio')
69
+ const targetPath = path.join(process.cwd(), projectName)
70
+
71
+ // Check if template exists
72
+ if (!fs.existsSync(templatePath)) {
73
+ throw new Error('Template no encontrado. Asegúrate de ejecutar desde el directorio correcto.')
74
+ }
75
+
76
+ // Create target directory
77
+ if (fs.existsSync(targetPath)) {
78
+ throw new Error(`El directorio ${projectName} ya existe`)
79
+ }
80
+
81
+ fs.mkdirSync(targetPath, { recursive: true })
82
+
83
+ // Copy template files
84
+ await copyTemplate(templatePath, targetPath, projectName, studentName, level)
85
+ }
86
+
87
+ async function copyTemplate(src, dest, projectName, studentName, level) {
88
+ const items = fs.readdirSync(src)
89
+
90
+ for (const item of items) {
91
+ const srcPath = path.join(src, item)
92
+ const destPath = path.join(dest, item)
93
+
94
+ if (fs.statSync(srcPath).isDirectory()) {
95
+ fs.mkdirSync(destPath, { recursive: true })
96
+ await copyTemplate(srcPath, destPath, projectName, studentName, level)
97
+ } else {
98
+ let content = fs.readFileSync(srcPath, 'utf8')
99
+
100
+ // Apply level-specific modifications first
101
+ if (level > 0) {
102
+ content = applyLevelModifications(content, item, level)
103
+ }
104
+
105
+ // Then replace placeholders
106
+ content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName)
107
+ content = content.replace(/\{\{STUDENT_NAME\}\}/g, studentName)
108
+
109
+ fs.writeFileSync(destPath, content)
110
+ }
111
+ }
112
+ }
113
+
114
+ function applyLevelModifications(content, filename, level) {
115
+ if (filename === '+layout.svelte') {
116
+ return applyLayoutModifications(content, level)
117
+ }
118
+
119
+ if (filename === '+page.svelte') {
120
+ return applyPageModifications(content, level)
121
+ }
122
+
123
+ return content
124
+ }
125
+
126
+ function applyLayoutModifications(content, level) {
127
+ if (level >= 1) {
128
+ // Replace navbar placeholder with complete solution
129
+ content = content.replace(
130
+ '<nav class="bg-white shadow-sm">\n <!-- ⚠️ COMPLETA AQUÍ LA NAVEGACIÓN -->\n</nav>',
131
+ `<nav class="bg-white shadow-sm">
132
+ <div class="max-w-7xl mx-auto px-4">
133
+ <div class="flex justify-between items-center py-3">
134
+ <div class="text-xl font-bold text-gray-900">{{STUDENT_NAME}}</div>
135
+ <div class="hidden md:flex space-x-6">
136
+ <a href="#inicio" class="text-gray-600 hover:text-blue-600">Inicio</a>
137
+ <a href="#sobre-mi" class="text-gray-600 hover:text-blue-600">Sobre mí</a>
138
+ <a href="#proyectos" class="text-gray-600 hover:text-blue-600">Proyectos</a>
139
+ <a href="#contacto" class="text-gray-600 hover:text-blue-600">Contacto</a>
140
+ </div>
141
+ <button class="md:hidden">
142
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
143
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
144
+ </svg>
145
+ </button>
146
+ </div>
147
+ </div>
148
+ </nav>`
149
+ )
150
+ }
151
+
152
+ if (level >= 3) {
153
+ // Replace footer placeholder with complete solution
154
+ content = content.replace(
155
+ '<footer class="bg-gray-50 border-t">\n <!-- ⚠️ COMPLETA AQUÍ EL FOOTER -->\n</footer>',
156
+ `<footer class="bg-gray-50 border-t">
157
+ <div class="max-w-7xl mx-auto py-8 px-4">
158
+ <div class="text-center text-gray-600 text-sm space-y-2">
159
+ <p>© ${new Date().getFullYear()} {{STUDENT_NAME}}. Todos los derechos reservados.</p>
160
+ <p>Hecho con ❤️ en <a href="https://creta.school" class="text-blue-600 hover:underline">Creta</a></p>
161
+ </div>
162
+ </div>
163
+ </footer>`
164
+ )
165
+ }
166
+
167
+ return content
168
+ }
169
+
170
+ function applyPageModifications(content, level) {
171
+ if (level >= 2) {
172
+ // Replace hero placeholder with complete solution
173
+ content = content.replace(
174
+ `<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
175
+ <!-- ⚠️ COMPLETA AQUÍ LA SECCIÓN HERO -->
176
+ <div class="max-w-4xl mx-auto px-4 text-center">
177
+ <h1 class="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
178
+ ¡Construye tu hero aquí!
179
+ </h1>
180
+ <p class="text-lg text-gray-600 mb-8">
181
+ Lee los comentarios arriba para saber qué hacer ☝️
182
+ </p>
183
+ </div>
184
+ </section>`,
185
+ `<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
186
+ <div class="max-w-4xl mx-auto px-4 text-center">
187
+ <h1 class="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
188
+ Hola, soy {{STUDENT_NAME}}
189
+ </h1>
190
+ <p class="text-lg text-gray-600 mb-8 max-w-2xl mx-auto">
191
+ Soy un desarrollador apasionado por crear productos digitales que impacten positivamente.
192
+ Aprendo construyendo y siempre busco nuevos desafíos.
193
+ </p>
194
+ <div class="flex justify-center space-x-4">
195
+ <a href="#proyectos" class="bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg transition-colors">
196
+ Ver proyectos
197
+ </a>
198
+ <a href="#contacto" class="border border-blue-600 text-blue-600 hover:bg-blue-50 px-8 py-3 rounded-lg transition-colors">
199
+ Contáctame
200
+ </a>
201
+ </div>
202
+ </div>
203
+ </section>`
204
+ )
205
+ }
206
+
207
+ return content
208
+ }
209
+
210
+ function getLevelDescription(level) {
211
+ const descriptions = {
212
+ 1: 'navbar',
213
+ 2: 'navbar + hero',
214
+ 3: 'todo el portfolio'
215
+ }
216
+ return descriptions[level] || 'nivel desconocido'
217
+ }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@icarusmx/creta",
3
- "version": "0.0.2",
3
+ "version": "0.1.1",
4
4
  "description": "Salgamos de este laberinto.",
5
+ "type": "module",
5
6
  "bin": {
6
7
  "creta": "./bin/creta.js"
7
8
  },
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "scripts": {
6
+ "build": "vite build",
7
+ "dev": "vite dev",
8
+ "preview": "vite preview"
9
+ },
10
+ "devDependencies": {
11
+ "@sveltejs/adapter-auto": "^3.0.0",
12
+ "@sveltejs/kit": "^2.0.0",
13
+ "@sveltejs/vite-plugin-svelte": "^4.0.0",
14
+ "autoprefixer": "^10.4.16",
15
+ "postcss": "^8.4.32",
16
+ "svelte": "^5.0.0",
17
+ "tailwindcss": "^3.3.6",
18
+ "vite": "^5.0.3"
19
+ },
20
+ "type": "module"
21
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%sveltekit.assets%/favicon.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ %sveltekit.head%
8
+ </head>
9
+ <body data-sveltekit-preload-data="hover" class="antialiased">
10
+ <div style="display: contents">%sveltekit.body%</div>
11
+ </body>
12
+ </html>
@@ -0,0 +1,94 @@
1
+ <!--
2
+ RETO CRETA: PORTFOLIO PERSONAL
3
+ ===============================
4
+
5
+ ¡Hola {{STUDENT_NAME}}! 👋
6
+
7
+ Este es tu proyecto base para crear un portfolio personal.
8
+ Necesitas completar 3 secciones principales:
9
+
10
+ 1. 🧭 NAVBAR (Barra de navegación)
11
+ 2. 🌟 HERO (Sección principal)
12
+ 3. 🦶 FOOTER (Pie de página)
13
+
14
+ Cada sección tiene comentarios que te guían sobre qué hacer.
15
+
16
+ COMANDOS ÚTILES:
17
+ - npm run dev (inicia el servidor de desarrollo)
18
+ - Ctrl+C (para parar el servidor)
19
+
20
+ ¡Manos a la obra! 🚀
21
+ -->
22
+
23
+ <script>
24
+ import '../app.css'
25
+ </script>
26
+
27
+ <!--
28
+ 🧭 RETO 1: NAVBAR
29
+ ==================
30
+
31
+ Crea una barra de navegación que incluya:
32
+ - Logo o nombre (lado izquierdo)
33
+ - Menú de navegación (lado derecho)
34
+ * Inicio
35
+ * Sobre mí
36
+ * Proyectos
37
+ * Contacto
38
+
39
+ TIPS DE TAILWIND:
40
+ - Usa 'flex justify-between items-center' para distribuir elementos
41
+ - Usa 'bg-white shadow-sm' para fondo y sombra sutil
42
+ - Usa 'px-4 py-3' para espaciado interno
43
+ - Usa 'hover:text-blue-600' para efectos hover
44
+
45
+ ESTRUCTURA SUGERIDA:
46
+ ```html
47
+ <nav class="bg-white shadow-sm">
48
+ <div class="max-w-7xl mx-auto px-4">
49
+ <div class="flex justify-between items-center py-3">
50
+ <!-- Logo/Nombre aquí -->
51
+ <!-- Menú aquí -->
52
+ </div>
53
+ </div>
54
+ </nav>
55
+ ```
56
+ -->
57
+
58
+ <nav class="bg-white shadow-sm">
59
+ <!-- ⚠️ COMPLETA AQUÍ LA NAVEGACIÓN -->
60
+ </nav>
61
+
62
+ <main>
63
+ <slot />
64
+ </main>
65
+
66
+ <!--
67
+ 🦶 RETO 3: FOOTER
68
+ ==================
69
+
70
+ Crea un pie de página simple que incluya:
71
+ - Tu nombre y año actual
72
+ - Links a redes sociales (opcional)
73
+ - Mensaje "Hecho con ❤️ en Creta"
74
+
75
+ TIPS DE TAILWIND:
76
+ - Usa 'bg-gray-50 border-t' para fondo y borde superior
77
+ - Usa 'py-8 px-4' para espaciado
78
+ - Usa 'text-center text-gray-600 text-sm' para texto centrado y gris
79
+
80
+ ESTRUCTURA SUGERIDA:
81
+ ```html
82
+ <footer class="bg-gray-50 border-t">
83
+ <div class="max-w-7xl mx-auto py-8 px-4">
84
+ <div class="text-center text-gray-600 text-sm">
85
+ <!-- Tu contenido aquí -->
86
+ </div>
87
+ </div>
88
+ </footer>
89
+ ```
90
+ -->
91
+
92
+ <footer class="bg-gray-50 border-t">
93
+ <!-- ⚠️ COMPLETA AQUÍ EL FOOTER -->
94
+ </footer>
@@ -0,0 +1,50 @@
1
+ <!--
2
+ 🌟 RETO 2: HERO SECTION
3
+ ========================
4
+
5
+ Crea la sección principal de tu portfolio que incluya:
6
+ - Tu nombre como título principal
7
+ - Una descripción breve de quién eres
8
+ - Un botón de llamada a la acción
9
+ - Opcionalmente: tu foto o avatar
10
+
11
+ TIPS DE TAILWIND:
12
+ - Usa 'min-h-screen flex items-center justify-center' para centrar verticalmente
13
+ - Usa 'text-4xl md:text-6xl font-bold' para títulos grandes y responsivos
14
+ - Usa 'text-lg text-gray-600 mb-8' para descripciones
15
+ - Usa 'bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg' para botones
16
+
17
+ ESTRUCTURA SUGERIDA:
18
+ ```html
19
+ <section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
20
+ <div class="max-w-4xl mx-auto px-4 text-center">
21
+ <h1 class="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
22
+ Hola, soy [Tu Nombre]
23
+ </h1>
24
+ <p class="text-lg text-gray-600 mb-8">
25
+ [Tu descripción aquí]
26
+ </p>
27
+ <a href="#contacto" class="bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg">
28
+ Contáctame
29
+ </a>
30
+ </div>
31
+ </section>
32
+ ```
33
+ -->
34
+
35
+ <svelte:head>
36
+ <title>{{STUDENT_NAME}} - Portfolio</title>
37
+ <meta name="description" content="Portfolio personal de {{STUDENT_NAME}}" />
38
+ </svelte:head>
39
+
40
+ <section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
41
+ <!-- ⚠️ COMPLETA AQUÍ LA SECCIÓN HERO -->
42
+ <div class="max-w-4xl mx-auto px-4 text-center">
43
+ <h1 class="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
44
+ ¡Construye tu hero aquí!
45
+ </h1>
46
+ <p class="text-lg text-gray-600 mb-8">
47
+ Lee los comentarios arriba para saber qué hacer ☝️
48
+ </p>
49
+ </div>
50
+ </section>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="#3b82f6"/><text x="16" y="20" font-family="Arial" font-size="18" fill="white" text-anchor="middle">C</text></svg>
@@ -0,0 +1,10 @@
1
+ import adapter from '@sveltejs/adapter-auto';
2
+
3
+ /** @type {import('@sveltejs/kit').Config} */
4
+ const config = {
5
+ kit: {
6
+ adapter: adapter()
7
+ }
8
+ };
9
+
10
+ export default config;
@@ -0,0 +1,8 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: ['./src/**/*.{html,js,svelte,ts}'],
4
+ theme: {
5
+ extend: {},
6
+ },
7
+ plugins: [],
8
+ }
@@ -0,0 +1,6 @@
1
+ import { sveltekit } from '@sveltejs/kit/vite';
2
+ import { defineConfig } from 'vite';
3
+
4
+ export default defineConfig({
5
+ plugins: [sveltekit()]
6
+ });