create-atsdc-stack 1.0.1 → 1.2.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.
Files changed (48) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/CLAUDE.md +236 -0
  3. package/CONTRIBUTING.md +342 -342
  4. package/INSTALLATION.md +359 -359
  5. package/LICENSE +201 -201
  6. package/README.md +405 -405
  7. package/app/.env.example +17 -17
  8. package/app/.github/labeler.yml +61 -0
  9. package/app/.github/workflows/browser-tests.yml +101 -0
  10. package/app/.github/workflows/check.yml +24 -0
  11. package/app/.github/workflows/greetings.yml +16 -0
  12. package/app/.github/workflows/label.yml +22 -0
  13. package/app/.github/workflows/stale.yml +27 -0
  14. package/app/.github/workflows/summary.yml +34 -0
  15. package/app/.stylelintrc.json +8 -0
  16. package/app/README.md +251 -251
  17. package/app/astro.config.mjs +83 -83
  18. package/app/drizzle.config.ts +16 -16
  19. package/app/package.json +66 -52
  20. package/app/playwright.config.ts +27 -0
  21. package/app/public/manifest.webmanifest +36 -36
  22. package/app/pwa-assets.config.ts +8 -0
  23. package/app/src/components/Card.astro +36 -36
  24. package/app/src/db/initialize.ts +107 -107
  25. package/app/src/db/schema.ts +72 -72
  26. package/app/src/db/validations.ts +158 -158
  27. package/app/src/layouts/Layout.astro +63 -63
  28. package/app/src/lib/config.ts +36 -36
  29. package/app/src/lib/content-converter.ts +141 -141
  30. package/app/src/lib/dom-utils.ts +230 -230
  31. package/app/src/lib/exa-search.ts +269 -269
  32. package/app/src/pages/api/chat.ts +91 -91
  33. package/app/src/pages/api/posts.ts +350 -350
  34. package/app/src/pages/index.astro +87 -87
  35. package/app/src/styles/components/button.scss +152 -152
  36. package/app/src/styles/components/card.scss +180 -180
  37. package/app/src/styles/components/form.scss +240 -240
  38. package/app/src/styles/global.scss +141 -141
  39. package/app/src/styles/pages/index.scss +80 -80
  40. package/app/src/styles/reset.scss +83 -83
  41. package/app/src/styles/variables/globals.scss +96 -96
  42. package/app/src/styles/variables/mixins.scss +238 -238
  43. package/app/tests/browser.test.nopause.ts +10 -0
  44. package/app/tests/browser.test.ts +13 -0
  45. package/bin/cli.js +1151 -1138
  46. package/package.json +8 -6
  47. package/app/.astro/settings.json +0 -5
  48. package/app/.astro/types.d.ts +0 -1
@@ -1,16 +1,16 @@
1
- import type { Config } from 'drizzle-kit';
2
-
3
- if (!process.env.DATABASE_URL) {
4
- throw new Error('DATABASE_URL environment variable is required');
5
- }
6
-
7
- export default {
8
- schema: './src/db/schema.ts',
9
- out: './drizzle',
10
- dialect: 'postgresql',
11
- dbCredentials: {
12
- url: process.env.DATABASE_URL,
13
- },
14
- verbose: true,
15
- strict: true,
16
- } satisfies Config;
1
+ import type { Config } from 'drizzle-kit';
2
+
3
+ if (!process.env.DATABASE_URL) {
4
+ throw new Error('DATABASE_URL environment variable is required');
5
+ }
6
+
7
+ export default {
8
+ schema: './src/db/schema.ts',
9
+ out: './drizzle',
10
+ dialect: 'postgresql',
11
+ dbCredentials: {
12
+ url: process.env.DATABASE_URL,
13
+ },
14
+ verbose: true,
15
+ strict: true,
16
+ } satisfies Config;
package/app/package.json CHANGED
@@ -1,52 +1,66 @@
1
- {
2
- "name": "atsdc-app",
3
- "version": "1.0.0",
4
- "description": "ATSDC Stack - Astro application",
5
- "type": "module",
6
- "scripts": {
7
- "dev": "astro dev",
8
- "build": "astro check && astro build",
9
- "preview": "astro preview",
10
- "astro": "astro",
11
- "db:generate": "drizzle-kit generate",
12
- "db:migrate": "drizzle-kit migrate",
13
- "db:push": "drizzle-kit push",
14
- "db:studio": "drizzle-kit studio"
15
- },
16
- "dependencies": {
17
- "@astrojs/check": "^0.9.6",
18
- "@astrojs/react": "^4.4.2",
19
- "@astrojs/vercel": "^9.0.2",
20
- "@clerk/astro": "^1.4.3",
21
- "@clerk/clerk-react": "^5.17.3",
22
- "@rocicorp/zero": "^0.2.0",
23
- "@vercel/postgres": "^0.10.0",
24
- "ai": "^5.0.0",
25
- "astro": "^5.16.6",
26
- "cheerio": "^1.0.0",
27
- "drizzle-orm": "^0.36.4",
28
- "exa-js": "^1.1.1",
29
- "marked": "^14.1.3",
30
- "nanoid": "^5.0.9",
31
- "open-props": "^1.7.17",
32
- "react": "^18.3.1",
33
- "react-dom": "^18.3.1",
34
- "sass": "^1.82.0",
35
- "turndown": "^7.2.0",
36
- "typescript": "^5.7.2",
37
- "zod": "^3.24.1"
38
- },
39
- "devDependencies": {
40
- "@types/node": "^22.10.5",
41
- "@types/react": "^18.3.18",
42
- "@types/react-dom": "^18.3.5",
43
- "@types/turndown": "^5.0.5",
44
- "@vite-pwa/assets-generator": "^0.2.6",
45
- "drizzle-kit": "^0.29.1",
46
- "vercel": "^39.2.0",
47
- "vite-plugin-pwa": "^0.21.2"
48
- },
49
- "engines": {
50
- "node": ">=18.0.0"
51
- }
52
- }
1
+ {
2
+ "name": "atsdc-app",
3
+ "version": "1.0.0",
4
+ "description": "ATSDC Stack - Astro application",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "astro dev",
8
+ "build": "astro check && astro build",
9
+ "preview": "astro preview",
10
+ "astro": "astro",
11
+ "ts": "node --experimental-strip-types",
12
+ "test:chrome": "npx playwright test --headed --browser=chromium",
13
+ "test:firefox": "npx playwright test --headed --browser=firefox",
14
+ "test:safari": "npx playwright test --headed --browser=webkit",
15
+ "test": "npm run test:chrome && npm run test:firefox && npm run test:safari",
16
+ "test:nopause:chrome": "npx playwright test tests/browser.test.nopause.ts --browser=chromium",
17
+ "test:nopause:firefox": "npx playwright test tests/browser.test.nopause.ts --browser=firefox",
18
+ "test:nopause:safari": "npx playwright test tests/browser.test.nopause.ts --browser=webkit",
19
+ "test:nopause": "npm run test:nopause:chrome && npm run test:nopause:firefox && npm run test:nopause:safari",
20
+ "test:nopause:chrome:headed": "npx playwright test tests/browser.test.nopause.ts --headed --browser=chromium",
21
+ "test:nopause:firefox:headed": "npx playwright test tests/browser.test.nopause.ts --headed --browser=firefox",
22
+ "test:nopause:safari:headed": "npx playwright test tests/browser.test.nopause.ts --headed --browser=webkit",
23
+ "check": "astro check && stylelint \"src/**/*.scss\" && astro build",
24
+ "stylelint:fix": "stylelint \"src/**/*.scss\" --fix"
25
+ },
26
+ "dependencies": {
27
+ "@astrojs/check": "^0.9.6",
28
+ "@astrojs/react": "^4.4.2",
29
+ "@astrojs/vercel": "^9.0.2",
30
+ "@clerk/astro": "^1.4.3",
31
+ "@clerk/clerk-react": "^5.17.3",
32
+ "@rocicorp/zero": "^0.2.0",
33
+ "@vercel/postgres": "^0.10.0",
34
+ "ai": "^5.0.0",
35
+ "astro": "^5.16.6",
36
+ "cheerio": "^1.0.0",
37
+ "drizzle-orm": "^0.36.4",
38
+ "exa-js": "^1.1.1",
39
+ "marked": "^14.1.3",
40
+ "nanoid": "^5.0.9",
41
+ "open-props": "^1.7.17",
42
+ "react": "^18.3.1",
43
+ "react-dom": "^18.3.1",
44
+ "sass": "^1.82.0",
45
+ "turndown": "^7.2.0",
46
+ "typescript": "^5.7.2",
47
+ "zod": "^3.24.1"
48
+ },
49
+ "devDependencies": {
50
+ "@playwright/test": "^1.58.2",
51
+ "@types/node": "^22.10.5",
52
+ "@types/react": "^18.3.18",
53
+ "@types/react-dom": "^18.3.5",
54
+ "@types/turndown": "^5.0.5",
55
+ "@vite-pwa/assets-generator": "^0.2.6",
56
+ "dotenv": "^16.6.1",
57
+ "drizzle-kit": "^0.29.1",
58
+ "stylelint": "^16.26.1",
59
+ "stylelint-config-standard-scss": "^14.0.0",
60
+ "vercel": "^39.2.0",
61
+ "vite-plugin-pwa": "^0.21.2"
62
+ },
63
+ "engines": {
64
+ "node": ">=18.0.0"
65
+ }
66
+ }
@@ -0,0 +1,27 @@
1
+ import { defineConfig, devices } from '@playwright/test'
2
+
3
+ export default defineConfig({
4
+ testDir: './tests',
5
+ fullyParallel: false,
6
+ forbidOnly: !!process.env.CI,
7
+ retries: process.env.CI ? 1 : 0,
8
+ reporter: 'html',
9
+ use: {
10
+ baseURL: 'http://localhost:4321',
11
+ trace: 'on-first-retry',
12
+ },
13
+ projects: [
14
+ {
15
+ name: 'chromium',
16
+ use: { ...devices['Desktop Chrome'] },
17
+ },
18
+ {
19
+ name: 'firefox',
20
+ use: { ...devices['Desktop Firefox'] },
21
+ },
22
+ {
23
+ name: 'webkit',
24
+ use: { ...devices['Desktop Safari'] },
25
+ },
26
+ ],
27
+ })
@@ -1,36 +1,36 @@
1
- {
2
- "name": "ATSDC Stack App",
3
- "short_name": "ATSDC",
4
- "description": "Progressive Web App built with the ATSDC Stack",
5
- "start_url": "/",
6
- "display": "standalone",
7
- "background_color": "#ffffff",
8
- "theme_color": "#4f46e5",
9
- "orientation": "portrait-primary",
10
- "icons": [
11
- {
12
- "src": "/pwa-192x192.png",
13
- "sizes": "192x192",
14
- "type": "image/png",
15
- "purpose": "any"
16
- },
17
- {
18
- "src": "/pwa-512x512.png",
19
- "sizes": "512x512",
20
- "type": "image/png",
21
- "purpose": "any"
22
- },
23
- {
24
- "src": "/pwa-512x512.png",
25
- "sizes": "512x512",
26
- "type": "image/png",
27
- "purpose": "maskable"
28
- }
29
- ],
30
- "categories": [
31
- "productivity",
32
- "utilities"
33
- ],
34
- "screenshots": [],
35
- "shortcuts": []
36
- }
1
+ {
2
+ "name": "ATSDC Stack App",
3
+ "short_name": "ATSDC",
4
+ "description": "Progressive Web App built with the ATSDC Stack",
5
+ "start_url": "/",
6
+ "display": "standalone",
7
+ "background_color": "#ffffff",
8
+ "theme_color": "#4f46e5",
9
+ "orientation": "portrait-primary",
10
+ "icons": [
11
+ {
12
+ "src": "/pwa-192x192.png",
13
+ "sizes": "192x192",
14
+ "type": "image/png",
15
+ "purpose": "any"
16
+ },
17
+ {
18
+ "src": "/pwa-512x512.png",
19
+ "sizes": "512x512",
20
+ "type": "image/png",
21
+ "purpose": "any"
22
+ },
23
+ {
24
+ "src": "/pwa-512x512.png",
25
+ "sizes": "512x512",
26
+ "type": "image/png",
27
+ "purpose": "maskable"
28
+ }
29
+ ],
30
+ "categories": [
31
+ "productivity",
32
+ "utilities"
33
+ ],
34
+ "screenshots": [],
35
+ "shortcuts": []
36
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig, minimal2023Preset as preset } from '@vite-pwa/assets-generator/config'
2
+
3
+ export default defineConfig({
4
+ preset,
5
+ images: [
6
+ 'favicon.png'
7
+ ]
8
+ })
@@ -1,36 +1,36 @@
1
- ---
2
- /**
3
- * Card Component
4
- * Demonstrates proper SCSS architecture:
5
- * - No <style> tag in this file
6
- * - Styles imported from external SCSS file
7
- * - Reusable component with props
8
- */
9
-
10
- interface Props {
11
- title?: string;
12
- href?: string;
13
- class?: string;
14
- }
15
-
16
- const { title, href, class: className = '' } = Astro.props;
17
-
18
- // Import component-specific styles
19
- import '@/styles/components/card.scss';
20
- ---
21
-
22
- {href ? (
23
- <a href={href} class={`card-component ${className}`}>
24
- {title && <h3 class="card-component__title">{title}</h3>}
25
- <div class="card-component__content">
26
- <slot />
27
- </div>
28
- </a>
29
- ) : (
30
- <div class={`card-component ${className}`}>
31
- {title && <h3 class="card-component__title">{title}</h3>}
32
- <div class="card-component__content">
33
- <slot />
34
- </div>
35
- </div>
36
- )}
1
+ ---
2
+ /**
3
+ * Card Component
4
+ * Demonstrates proper SCSS architecture:
5
+ * - No <style> tag in this file
6
+ * - Styles imported from external SCSS file
7
+ * - Reusable component with props
8
+ */
9
+
10
+ interface Props {
11
+ title?: string;
12
+ href?: string;
13
+ class?: string;
14
+ }
15
+
16
+ const { title, href, class: className = '' } = Astro.props;
17
+
18
+ // Import component-specific styles
19
+ import '@/styles/components/card.scss';
20
+ ---
21
+
22
+ {href ? (
23
+ <a href={href} class={`card-component ${className}`}>
24
+ {title && <h3 class="card-component__title">{title}</h3>}
25
+ <div class="card-component__content">
26
+ <slot />
27
+ </div>
28
+ </a>
29
+ ) : (
30
+ <div class={`card-component ${className}`}>
31
+ {title && <h3 class="card-component__title">{title}</h3>}
32
+ <div class="card-component__content">
33
+ <slot />
34
+ </div>
35
+ </div>
36
+ )}
@@ -1,107 +1,107 @@
1
- import { sql } from '@vercel/postgres';
2
- import { drizzle } from 'drizzle-orm/vercel-postgres';
3
- import * as schema from './schema';
4
- import { posts, comments } from './schema';
5
-
6
- /**
7
- * Database client configuration
8
- * Uses Vercel Postgres for production-ready connection pooling
9
- */
10
-
11
- // Create Drizzle instance with schema
12
- export const db = drizzle(sql, { schema });
13
-
14
- // Export schema for convenience
15
- export { schema };
16
-
17
- /**
18
- * Database initialization utilities
19
- * Handles table creation, migrations, and initial setup
20
- */
21
-
22
- /**
23
- * Check if the database tables exist by attempting a simple query
24
- */
25
- export async function checkTablesExist(): Promise<boolean> {
26
- try {
27
- await db.select().from(posts).limit(1);
28
- return true;
29
- } catch (error) {
30
- console.error('Error checking if tables exist:', error);
31
- return false;
32
- }
33
- }
34
-
35
- /**
36
- * Initialize the database by creating tables if they don't exist
37
- * Note: In production, use Drizzle migrations instead
38
- */
39
- export async function initializeDatabase(): Promise<void> {
40
- try {
41
- const tablesExist = await checkTablesExist();
42
-
43
- if (!tablesExist) {
44
- console.log('Database tables do not exist. Please run migrations using:');
45
- console.log(' npm run db:push');
46
- console.log(' or');
47
- console.log(' npm run db:migrate');
48
- throw new Error('Database tables not initialized');
49
- }
50
-
51
- console.log('Database tables verified successfully');
52
- } catch (error) {
53
- console.error('Database initialization failed:', error);
54
- throw error;
55
- }
56
- }
57
-
58
- /**
59
- * Verify database connection
60
- */
61
- export async function verifyConnection(): Promise<boolean> {
62
- try {
63
- await db.select().from(posts).limit(1);
64
- return true;
65
- } catch (error) {
66
- console.error('Database connection failed:', error);
67
- return false;
68
- }
69
- }
70
-
71
- /**
72
- * Get database health status
73
- */
74
- export async function getDatabaseHealth(): Promise<{
75
- connected: boolean;
76
- tablesExist: boolean;
77
- timestamp: Date;
78
- }> {
79
- const connected = await verifyConnection();
80
- const tablesExist = connected ? await checkTablesExist() : false;
81
-
82
- return {
83
- connected,
84
- tablesExist,
85
- timestamp: new Date(),
86
- };
87
- }
88
-
89
- /**
90
- * Seed initial data (optional - for development)
91
- */
92
- export async function seedDatabase(): Promise<void> {
93
- try {
94
- // Check if data already exists
95
- const existingPosts = await db.select().from(posts).limit(1);
96
-
97
- if (existingPosts.length > 0) {
98
- console.log('Database already contains data, skipping seed');
99
- return;
100
- }
101
-
102
- console.log('Database seeding completed');
103
- } catch (error) {
104
- console.error('Database seeding failed:', error);
105
- throw error;
106
- }
107
- }
1
+ import { sql } from '@vercel/postgres';
2
+ import { drizzle } from 'drizzle-orm/vercel-postgres';
3
+ import * as schema from './schema';
4
+ import { posts, comments } from './schema';
5
+
6
+ /**
7
+ * Database client configuration
8
+ * Uses Vercel Postgres for production-ready connection pooling
9
+ */
10
+
11
+ // Create Drizzle instance with schema
12
+ export const db = drizzle(sql, { schema });
13
+
14
+ // Export schema for convenience
15
+ export { schema };
16
+
17
+ /**
18
+ * Database initialization utilities
19
+ * Handles table creation, migrations, and initial setup
20
+ */
21
+
22
+ /**
23
+ * Check if the database tables exist by attempting a simple query
24
+ */
25
+ export async function checkTablesExist(): Promise<boolean> {
26
+ try {
27
+ await db.select().from(posts).limit(1);
28
+ return true;
29
+ } catch (error) {
30
+ console.error('Error checking if tables exist:', error);
31
+ return false;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Initialize the database by creating tables if they don't exist
37
+ * Note: In production, use Drizzle migrations instead
38
+ */
39
+ export async function initializeDatabase(): Promise<void> {
40
+ try {
41
+ const tablesExist = await checkTablesExist();
42
+
43
+ if (!tablesExist) {
44
+ console.log('Database tables do not exist. Please run migrations using:');
45
+ console.log(' npm run db:push');
46
+ console.log(' or');
47
+ console.log(' npm run db:migrate');
48
+ throw new Error('Database tables not initialized');
49
+ }
50
+
51
+ console.log('Database tables verified successfully');
52
+ } catch (error) {
53
+ console.error('Database initialization failed:', error);
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Verify database connection
60
+ */
61
+ export async function verifyConnection(): Promise<boolean> {
62
+ try {
63
+ await db.select().from(posts).limit(1);
64
+ return true;
65
+ } catch (error) {
66
+ console.error('Database connection failed:', error);
67
+ return false;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Get database health status
73
+ */
74
+ export async function getDatabaseHealth(): Promise<{
75
+ connected: boolean;
76
+ tablesExist: boolean;
77
+ timestamp: Date;
78
+ }> {
79
+ const connected = await verifyConnection();
80
+ const tablesExist = connected ? await checkTablesExist() : false;
81
+
82
+ return {
83
+ connected,
84
+ tablesExist,
85
+ timestamp: new Date(),
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Seed initial data (optional - for development)
91
+ */
92
+ export async function seedDatabase(): Promise<void> {
93
+ try {
94
+ // Check if data already exists
95
+ const existingPosts = await db.select().from(posts).limit(1);
96
+
97
+ if (existingPosts.length > 0) {
98
+ console.log('Database already contains data, skipping seed');
99
+ return;
100
+ }
101
+
102
+ console.log('Database seeding completed');
103
+ } catch (error) {
104
+ console.error('Database seeding failed:', error);
105
+ throw error;
106
+ }
107
+ }