diff --git a/.github/workflows/hello-world.yml b/.github/workflows/hello-world.yml
new file mode 100644
index 0000000..4a09b2c
--- /dev/null
+++ b/.github/workflows/hello-world.yml
@@ -0,0 +1,21 @@
+name: Hello World Workflow
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - '**'
+ pull_request:
+ types: [opened, synchronize, reopened]
+
+jobs:
+ say-hello:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ - name: Say Hello
+ run: |
+ echo "Hello, World!"
+ echo "Running on branch: ${{ github.ref_name }}"
+ echo "Triggered by: ${{ github.event_name }}"
\ No newline at end of file
diff --git a/_quarto.yml b/_quarto.yml
index 541a540..fa0601c 100644
--- a/_quarto.yml
+++ b/_quarto.yml
@@ -38,6 +38,13 @@ website:
- icon: github
text: Github
href: "https://github.com/isamplesorg/"
+ - section: "Tutorials"
+ contents:
+ - text: "iSamples Tutorials Overview"
+ href: tutorials/index.qmd
+ - text: "iSamples Parquet Tutorial"
+ href: tutorials/parquet.qmd
+
# configure for correct source repository
diff --git a/tutorials/index.qmd b/tutorials/index.qmd
new file mode 100644
index 0000000..241abf2
--- /dev/null
+++ b/tutorials/index.qmd
@@ -0,0 +1,67 @@
+---
+title: "Tutorials: Overview"
+---
+
+Here's where we park our various tutorials!
+
+Get the OpenAPI spec.
+
+```{ojs}
+//| echo: true
+
+// Get the OpenAPI specification and display detailed endpoint information
+viewof apiEndpointDetails = {
+ // Show loading indicator
+ const loadingElement = html`
Loading API endpoints...
`;
+ document.body.appendChild(loadingElement);
+
+ try {
+ const OPENAPI_URL = 'https://central.isample.xyz/isamples_central/openapi.json';
+
+ // Fetch the OpenAPI spec
+ const response = await fetch(OPENAPI_URL);
+ if (!response.ok) throw new Error(`Failed to fetch API spec: ${response.status}`);
+
+ const apiSpec = await response.json();
+
+ // Extract detailed information about each endpoint
+ const endpointDetails = [];
+
+ for (const [path, pathMethods] of Object.entries(apiSpec.paths)) {
+ for (const [method, details] of Object.entries(pathMethods)) {
+ endpointDetails.push({
+ endpoint: path,
+ method: method.toUpperCase(),
+ summary: details.summary || '',
+ operationId: details.operationId || '',
+ tags: (details.tags || []).join(', '),
+ parameters: (details.parameters || [])
+ .map(p => `${p.name} (${p.required ? 'required' : 'optional'})`)
+ .join(', ')
+ });
+ }
+ }
+
+ // Create a table with the detailed endpoint information
+ return Inputs.table(
+ endpointDetails,
+ {
+ label: "iSamples API Endpoints Details",
+ width: {
+ endpoint: 150,
+ method: 80,
+ summary: 200,
+ operationId: 200,
+ tags: 100,
+ parameters: 300
+ }
+ }
+ );
+ } catch (error) {
+ return html`Error fetching API endpoints: ${error.message}
`;
+ } finally {
+ // Remove loading indicator
+ loadingElement.remove();
+ }
+}
+```
\ No newline at end of file
diff --git a/tutorials/parquet.qmd b/tutorials/parquet.qmd
new file mode 100644
index 0000000..c16b20c
--- /dev/null
+++ b/tutorials/parquet.qmd
@@ -0,0 +1,64 @@
+---
+title: "Parquet"
+---
+
+Let's query Eric's parquet file using duckdb+parquet
+
+
+simpler query:
+
+```{ojs}
+//| echo: true
+
+// Import Observable's libraries
+import {DuckDBClient} from "@observablehq/duckdb"
+
+// Create a DuckDB instance
+db = DuckDBClient.of()
+
+// Set the Parquet file path
+parquet_path = 'https://storage.googleapis.com/opencontext-parquet/oc_isamples_pqg.parquet'
+
+// For testing, use a smaller dataset or limit rows
+// Option 1: Use LIMIT to reduce data transferred
+viewof testResults = {
+ // Show loading indicator
+ const loadingElement = html`Running query...
`;
+ document.body.appendChild(loadingElement);
+
+ try {
+ // Test with a small LIMIT to verify connection works
+ const data = await db.query(`
+ SELECT otype, pid
+ FROM read_parquet('${parquet_path}')
+ LIMIT 10
+ `);
+ return Inputs.table(data);
+ } finally {
+ // Remove loading indicator when done (whether success or error)
+ loadingElement.remove();
+ }
+}
+
+```
+
+now the full query
+
+
+```{ojs}
+//| echo: true
+
+
+// Query the Parquet file
+viewof results = Inputs.table(
+ await db.query(`
+ SELECT COUNT(pid) as count, otype
+ FROM read_parquet('${parquet_path}')
+ GROUP BY otype
+ ORDER BY count DESC
+ `)
+)
+```
+
+
+