diff --git a/ai-code-completion/.eslintrc.json b/ai-code-completion/.eslintrc.json
new file mode 100644
index 0000000..0e81f9b
--- /dev/null
+++ b/ai-code-completion/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
\ No newline at end of file
diff --git a/ai-code-completion/README.md b/ai-code-completion/README.md
new file mode 100644
index 0000000..f6e9216
--- /dev/null
+++ b/ai-code-completion/README.md
@@ -0,0 +1,69 @@
+# AI Code Completion Tool
+
+A self-hosted AI code completion tool that runs entirely in your Codesphere workspace. No external API required — your code never leaves your server.
+
+## Features
+
+- **Local Processing**: All code stays on your machine. No cloud API calls.
+- **Multi-Language Support**: JavaScript, Python, HTML, CSS, JSON
+- **Smart Completions**: Context-aware code suggestions
+- **CodeMirror Editor**: Professional code editing experience with syntax highlighting, line numbers, and code folding
+
+## Supported Languages
+
+| Language | Completions |
+|----------|-------------|
+| JavaScript | functions, classes, async/await, imports, loops, conditionals |
+| Python | functions, classes, decorators, list comprehensions, context managers |
+| HTML | semantic elements, forms, tables, media |
+| CSS | flexbox, grid, colors, typography, layouts |
+| JSON | key-value pairs, nested objects, arrays |
+
+## Deployment on Codesphere
+
+1. Fork this template
+2. Create a new Codesphere workspace from your fork
+3. Set up the CI pipeline (auto-installed on Codesphere)
+4. Run the `prepare` stage to install dependencies
+5. Run the `run` stage to start the dev server
+6. Click "Open deployment" to access the tool
+
+## Local Development
+
+```bash
+npm install
+npm run dev
+```
+
+Open http://localhost:3000 to use the tool.
+
+## Usage
+
+1. Select your programming language from the dropdown
+2. Start typing code in the editor
+3. When you type a keyword (like "func", "const", "def"), completion suggestions appear
+4. Click a suggestion or use it as inspiration to complete your code
+
+## How It Works
+
+This tool uses local snippet matching rather than a real AI model to provide code completions. In a production environment, you could replace the completion logic with:
+
+- A self-hosted LLM (like CodeLlama or StarCoder)
+- The Continue.dev or other open-source completion engines
+- A local instance of the AI Code Completion model
+
+The architecture is designed so that the completion backend can be swapped out without changing the frontend.
+
+## Tech Stack
+
+- Next.js 14 (App Router)
+- CodeMirror 6 (editor)
+- React 18
+
+## Blog Post
+
+[Write a blog article about this project on Dev.To, Medium, or personal blog and link it here]
+
+---
+
+Built for Codesphere Templates — deploy complex apps in minutes.
\ No newline at end of file
diff --git a/ai-code-completion/ai-code-completion.webp b/ai-code-completion/ai-code-completion.webp
new file mode 100644
index 0000000..e69de29
diff --git a/ai-code-completion/ci.yml b/ai-code-completion/ci.yml
new file mode 100644
index 0000000..617d99a
--- /dev/null
+++ b/ai-code-completion/ci.yml
@@ -0,0 +1,14 @@
+prepare:
+ steps:
+ - name: "Install dependencies"
+ command: "npm install"
+
+test:
+ steps:
+ - name: "Lint"
+ command: "npm run lint || true"
+
+run:
+ steps:
+ - name: "Start dev server"
+ command: "PORT=3000 npm run dev"
\ No newline at end of file
diff --git a/ai-code-completion/jsconfig.json b/ai-code-completion/jsconfig.json
new file mode 100644
index 0000000..e8b3494
--- /dev/null
+++ b/ai-code-completion/jsconfig.json
@@ -0,0 +1,7 @@
+{
+ "compilerOptions": {
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
\ No newline at end of file
diff --git a/ai-code-completion/metadata.json b/ai-code-completion/metadata.json
new file mode 100644
index 0000000..17e95bc
--- /dev/null
+++ b/ai-code-completion/metadata.json
@@ -0,0 +1,10 @@
+{
+ "Workspace": "paid",
+ "Links": {
+ "Next.js": "https://nextjs.org/",
+ "CodeMirror": "https://codemirror.net/"
+ },
+ "Categories": ["AI", "Developer Tools"],
+ "Contributors": ["opencode-MiniMaxM27"],
+ "Title": "AI Code Completion Tool"
+}
\ No newline at end of file
diff --git a/ai-code-completion/next.config.js b/ai-code-completion/next.config.js
new file mode 100644
index 0000000..cc59526
--- /dev/null
+++ b/ai-code-completion/next.config.js
@@ -0,0 +1,6 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ output: 'standalone',
+}
+
+module.exports = nextConfig
\ No newline at end of file
diff --git a/ai-code-completion/package.json b/ai-code-completion/package.json
new file mode 100644
index 0000000..c277125
--- /dev/null
+++ b/ai-code-completion/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "ai-code-completion",
+ "version": "1.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "next": "^14.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "@codemirror/lang-javascript": "^6.2.0",
+ "@codemirror/lang-python": "^6.1.0",
+ "@codemirror/lang-html": "^6.4.0",
+ "@codemirror/lang-css": "^6.2.0",
+ "@codemirror/lang-json": "^6.0.0",
+ "@codemirror/lang-markdown": "^6.2.0",
+ "@codemirror/view": "^6.22.0",
+ "@codemirror/state": "^6.3.0",
+ "@codemirror/commands": "^6.3.0",
+ "@codemirror/autocomplete": "^6.12.0",
+ "codemirror": "^6.0.1",
+ "@uiw/react-codemirror": "^4.21.0",
+ "axios": "^1.6.0"
+ }
+}
\ No newline at end of file
diff --git a/ai-code-completion/src/app/globals.css b/ai-code-completion/src/app/globals.css
new file mode 100644
index 0000000..c9b4f90
--- /dev/null
+++ b/ai-code-completion/src/app/globals.css
@@ -0,0 +1,9 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+}
\ No newline at end of file
diff --git a/ai-code-completion/src/app/layout.js b/ai-code-completion/src/app/layout.js
new file mode 100644
index 0000000..69eea4f
--- /dev/null
+++ b/ai-code-completion/src/app/layout.js
@@ -0,0 +1,14 @@
+import './globals.css'
+
+export const metadata = {
+ title: 'AI Code Completion',
+ description: 'Self-hosted AI code completion tool',
+}
+
+export default function RootLayout({ children }) {
+ return (
+
+
{children}
+
+ )
+}
\ No newline at end of file
diff --git a/ai-code-completion/src/app/page.js b/ai-code-completion/src/app/page.js
new file mode 100644
index 0000000..4b7fa25
--- /dev/null
+++ b/ai-code-completion/src/app/page.js
@@ -0,0 +1,217 @@
+'use client'
+
+import { useState } from 'react'
+import CodeMirror from '@uiw/react-codemirror'
+import { javascript } from '@codemirror/lang-javascript'
+import { python } from '@codemirror/lang-python'
+import { html } from '@codemirror/lang-html'
+import { css } from '@codemirror/lang-css'
+import { json } from '@codemirror/lang-json'
+
+const LANGUAGES = {
+ javascript: javascript({ jsx: true }),
+ python: python(),
+ html: html(),
+ css: css(),
+ json: json(),
+}
+
+const SAMPLE_COMPLETIONS = {
+ javascript: [
+ { label: 'console.log', detail: 'Log to console', insertText: 'console.log(${1:value})' },
+ { label: 'function', detail: 'Function declaration', insertText: 'function ${1:name}(${2:params}) {\n ${3:// body}\n}' },
+ { label: 'async function', detail: 'Async function', insertText: 'async function ${1:name}(${2:params}) {\n ${3:// body}\n}' },
+ { label: 'const', detail: 'Constant declaration', insertText: 'const ${1:name} = ${2:value}' },
+ { label: 'let', detail: 'Variable declaration', insertText: 'let ${1:name} = ${2:value}' },
+ { label: 'if', detail: 'If statement', insertText: 'if (${1:condition}) {\n ${2:// body}\n}' },
+ { label: 'for', detail: 'For loop', insertText: 'for (let ${1:i} = 0; ${1:i} < ${2:length}; ${1:i}++) {\n ${3:// body}\n}' },
+ { label: 'return', detail: 'Return statement', insertText: 'return ${1:value}' },
+ { label: 'class', detail: 'Class declaration', insertText: 'class ${1:name} {\n constructor(${2:params}) {\n ${3:// init}\n }\n}' },
+ { label: 'import', detail: 'Import statement', insertText: "import { ${1:module} } from '${2:path}'" },
+ ],
+ python: [
+ { label: 'def', detail: 'Function definition', insertText: 'def ${1:name}(${2:params}):\n ${3:pass}' },
+ { label: 'class', detail: 'Class definition', insertText: 'class ${1:name}:\n def __init__(self${2:params}):\n ${3:pass}' },
+ { label: 'print', detail: 'Print to stdout', insertText: 'print(${1:value})' },
+ { label: 'if', detail: 'If statement', insertText: 'if ${1:condition}:\n ${2:pass}' },
+ { label: 'for', detail: 'For loop', insertText: 'for ${1:item} in ${2:iterable}:\n ${3:pass}' },
+ { label: 'while', detail: 'While loop', insertText: 'while ${1:condition}:\n ${2:pass}' },
+ { label: 'try', detail: 'Try-except block', insertText: 'try:\n ${1:pass}\nexcept ${2:Exception} as ${3:e}:\n ${4:pass}' },
+ { label: 'with', detail: 'Context manager', insertText: 'with ${1:context} as ${2:target}:\n ${3:pass}' },
+ { label: 'async def', detail: 'Async function', insertText: 'async def ${1:name}(${2:params}):\n ${3:pass}' },
+ { label: 'return', detail: 'Return statement', insertText: 'return ${1:value}' },
+ ],
+ html: [
+ { label: '', detail: 'Div element', insertText: '
\n ${2:content}\n
' },
+ { label: '
', detail: 'Span element', insertText: '${2:content} ' },
+ { label: '', detail: 'Paragraph', insertText: '
${1:content}
' },
+ { label: '', detail: 'Link', insertText: ' ${3:text} ' },
+ { label: ' ', detail: 'Image', insertText: ' ' },
+ { label: '', detail: 'Unordered list', insertText: '' },
+ { label: '', detail: 'Button', insertText: '${2:text} ' },
+ { label: ' ', detail: 'Input field', insertText: ' ' },
+ ],
+ css: [
+ { label: 'display', detail: 'Display property', insertText: 'display: ${1:block}' },
+ { label: 'margin', detail: 'Margin shorthand', insertText: 'margin: ${1:0}' },
+ { label: 'padding', detail: 'Padding shorthand', insertText: 'padding: ${1:0}' },
+ { label: 'color', detail: 'Text color', insertText: 'color: ${1:#000}' },
+ { label: 'font-size', detail: 'Font size', insertText: 'font-size: ${1:16px}' },
+ { label: 'background', detail: 'Background', insertText: 'background: ${1:#fff}' },
+ { label: 'flex', detail: 'Flexbox', insertText: 'display: flex;\n justify-content: ${1:center};\n align-items: ${2:center};' },
+ { label: 'grid', detail: 'CSS Grid', insertText: 'display: grid;\n grid-template-columns: ${1:1fr};\n gap: ${2:1rem};' },
+ ],
+ json: [
+ { label: '"key": "value"', detail: 'Key-value pair', insertText: '"${1:key}": "${2:value}"' },
+ { label: '"name": "', detail: 'Name property', insertText: '"name": "${1:value}"' },
+ { label: '"version": "', detail: 'Version property', insertText: '"version": "${1:1.0.0}"' },
+ { label: '"dependencies": {}', detail: 'Dependencies object', insertText: '"dependencies": {\n "${1:name}": "${2:version}"\n}' },
+ ],
+}
+
+function getCompletions(lang, query) {
+ const langCompletions = SAMPLE_COMPLETIONS[lang] || SAMPLE_COMPLETIONS.javascript
+ if (!query) return langCompletions.slice(0, 8)
+ const q = query.toLowerCase()
+ return langCompletions.filter(c => c.label.toLowerCase().includes(q)).slice(0, 6)
+}
+
+export default function Home() {
+ const [code, setCode] = useState('// Start typing code here\nfunction hello() {\n \n}\n')
+ const [language, setLanguage] = useState('javascript')
+ const [completions, setCompletions] = useState([])
+ const [activeCompletion, setActiveCompletion] = useState(null)
+ const [showCompletions, setShowCompletions] = useState(false)
+
+ const handleChange = (value) => {
+ setCode(value)
+ const lines = value.split('\n')
+ const lastLine = lines[lines.length - 1]
+ const words = lastLine.split(/\s/)
+ const lastWord = words[words.length - 1]
+
+ if (lastWord.length >= 2) {
+ const found = getCompletions(language, lastWord)
+ setCompletions(found)
+ setShowCompletions(found.length > 0)
+ setActiveCompletion(found[0] || null)
+ } else {
+ setShowCompletions(false)
+ setCompletions([])
+ setActiveCompletion(null)
+ }
+ }
+
+ const insertCompletion = (completion) => {
+ const lines = code.split('\n')
+ const lastLineIdx = lines.length - 1
+ const lastLine = lines[lastLineIdx]
+ const words = lastLine.split(/\s/)
+ const wordStart = code.lastIndexOf(' ' + lastWord(lastLine)) + 1
+ const lastWord = lastWord(lastLine)
+
+ let newCode = code.substring(0, wordStart) + completion.label + code.substring(wordStart + lastWord.length)
+ setCode(newCode)
+ setShowCompletions(false)
+ }
+
+ const lastWord = (line) => {
+ const words = line.split(/\s/)
+ return words[words.length - 1] || ''
+ }
+
+ const langExtensions = {
+ javascript: javascript({ jsx: true }),
+ python: python(),
+ html: html(),
+ css: css(),
+ json: json(),
+ }
+
+ return (
+
+
+
+
AI Code Completion
+
Self-hosted • No API required • Your code stays local
+
+
+ Language:
+ setLanguage(e.target.value)}
+ style={{ background: '#161b22', border: '1px solid #30363d', color: '#c9d1d9', padding: '6px 12px', borderRadius: '6px', fontSize: '14px' }}
+ >
+ JavaScript
+ Python
+ HTML
+ CSS
+ JSON
+
+
+
+
+
+
+
+
+ {showCompletions && completions.length > 0 && (
+
+
+ AI Completions (local model)
+
+ {completions.map((comp, i) => (
+
insertCompletion(comp)}
+ style={{
+ padding: '8px 12px',
+ cursor: 'pointer',
+ borderRadius: '4px',
+ background: activeCompletion === comp ? '#21262d' : 'transparent',
+ }}
+ onMouseEnter={() => setActiveCompletion(comp)}
+ >
+ {comp.label}
+ {comp.detail}
+
+ ))}
+
+ )}
+
+
+
+
+ How it works: Type any keyword (e.g., "func", "const", "def") and AI Code Completion will suggest relevant snippets from your local model.
+ All processing happens locally — no data leaves your workspace.
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/ai-code-completion/start.sh b/ai-code-completion/start.sh
new file mode 100644
index 0000000..0aaebe7
--- /dev/null
+++ b/ai-code-completion/start.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+
+echo "Installing dependencies..."
+npm install
+
+echo "Starting AI Code Completion dev server..."
+npm run dev
\ No newline at end of file
diff --git a/laravel/.env b/laravel/.env
new file mode 100644
index 0000000..5266c50
--- /dev/null
+++ b/laravel/.env
@@ -0,0 +1,8 @@
+APP_NAME="Laravel Quiz App"
+APP_ENV=local
+APP_KEY=base64:MHMyGZ7hZG8z4V5j6F3qW1pL8n2R4s9X0yB7cE6dA=
+APP_DEBUG=true
+APP_URL=http://localhost:3000
+
+DB_CONNECTION=sqlite
+DB_DATABASE=/tmp/templates-fork/laravel/database.sqlite
\ No newline at end of file
diff --git a/laravel/README.md b/laravel/README.md
new file mode 100644
index 0000000..4ce2f99
--- /dev/null
+++ b/laravel/README.md
@@ -0,0 +1,33 @@
+# Laravel Quiz App Template
+
+A basic quiz application built with Laravel for Codesphere workspaces.
+
+## Features
+
+- Create and manage quizzes
+- Add multiple-choice questions to each quiz
+- Take quizzes and see your score
+- SQLite database (no external DB required)
+
+## Deployment on Codesphere
+
+1. Fork this template
+2. In Codesphere, create a new workspace from your fork
+3. Set up the CI pipeline (it will auto-run on Codesphere)
+4. Click "Run" stage to start the dev server
+5. Click "Open deployment" to access the app
+
+## Local Development
+
+```bash
+composer install
+touch database/database.sqlite
+php artisan migrate
+php artisan serve --host=0.0.0.0 --port=3000
+```
+
+## Tech Stack
+
+- PHP 8.1+
+- Laravel 10
+- SQLite (file-based, no setup required)
\ No newline at end of file
diff --git a/laravel/app/Http/Controllers/Controller.php b/laravel/app/Http/Controllers/Controller.php
new file mode 100644
index 0000000..376e5b7
--- /dev/null
+++ b/laravel/app/Http/Controllers/Controller.php
@@ -0,0 +1,8 @@
+validate([
+ 'quiz_id' => 'required|exists:quizzes,id',
+ 'question_text' => 'required|string',
+ 'options' => 'required|array|min:2',
+ 'correct_answer' => 'required|string',
+ ]);
+
+ Question::create($validated);
+ return redirect()->route('quizzes.show', $validated['quiz_id'])->with('success', 'Question added!');
+ }
+
+ public function destroy(Question $question)
+ {
+ $quiz_id = $question->quiz_id;
+ $question->delete();
+ return redirect()->route('quizzes.show', $quiz_id)->with('success', 'Question deleted!');
+ }
+}
\ No newline at end of file
diff --git a/laravel/app/Http/Controllers/QuizController.php b/laravel/app/Http/Controllers/QuizController.php
new file mode 100644
index 0000000..3828f8d
--- /dev/null
+++ b/laravel/app/Http/Controllers/QuizController.php
@@ -0,0 +1,55 @@
+latest()->paginate(10);
+ return view('quizzes.index', compact('quizzes'));
+ }
+
+ public function create()
+ {
+ return view('quizzes.create');
+ }
+
+ public function store(Request $request)
+ {
+ $validated = $request->validate([
+ 'title' => 'required|string|max:255',
+ 'description' => 'nullable|string',
+ ]);
+
+ Quiz::create($validated);
+ return redirect()->route('quizzes.index')->with('success', 'Quiz created!');
+ }
+
+ public function show(Quiz $quiz)
+ {
+ $quiz->load('questions');
+ return view('quizzes.show', compact('quiz'));
+ }
+
+ public function take(Request $request, Quiz $quiz)
+ {
+ $answers = $request->except(['_token']);
+ $quiz->load('questions');
+
+ $score = 0;
+ $total = $quiz->questions->count();
+
+ foreach ($quiz->questions as $question) {
+ if (isset($answers['question_' . $question->id]) &&
+ $answers['question_' . $question->id] === $question->correct_answer) {
+ $score++;
+ }
+ }
+
+ return view('quizzes.result', compact('quiz', 'score', 'total'));
+ }
+}
\ No newline at end of file
diff --git a/laravel/app/Models/Question.php b/laravel/app/Models/Question.php
new file mode 100644
index 0000000..c70384c
--- /dev/null
+++ b/laravel/app/Models/Question.php
@@ -0,0 +1,19 @@
+ 'array',
+ ];
+
+ public function quiz()
+ {
+ return $this->belongsTo(Quiz::class);
+ }
+}
\ No newline at end of file
diff --git a/laravel/app/Models/Quiz.php b/laravel/app/Models/Quiz.php
new file mode 100644
index 0000000..f601273
--- /dev/null
+++ b/laravel/app/Models/Quiz.php
@@ -0,0 +1,15 @@
+hasMany(Question::class);
+ }
+}
\ No newline at end of file
diff --git a/laravel/app/Providers/AppServiceProvider.php b/laravel/app/Providers/AppServiceProvider.php
new file mode 100644
index 0000000..a4254c4
--- /dev/null
+++ b/laravel/app/Providers/AppServiceProvider.php
@@ -0,0 +1,18 @@
+make(Illuminate\Contracts\Console\Kernel::class);
+
+$status = $kernel->handle(
+ $input = new Symfony\Component\Console\Input\ArgvInput,
+ new Symfony\Component\Console\Output\ConsoleOutput
+);
+
+$kernel->terminate($input, $status);
+
+exit($status);
\ No newline at end of file
diff --git a/laravel/bootstrap/app.php b/laravel/bootstrap/app.php
new file mode 100644
index 0000000..3d8b5f7
--- /dev/null
+++ b/laravel/bootstrap/app.php
@@ -0,0 +1,18 @@
+withRouting(
+ web: __DIR__.'/../routes/web.php',
+ commands: __DIR__.'/../routes/console.php',
+ health: '/up',
+ )
+ ->withMiddleware(function (Middleware $middleware) {
+ //
+ })
+ ->withExceptions(function (Exceptions $exceptions) {
+ //
+ })->create();
\ No newline at end of file
diff --git a/laravel/ci.yml b/laravel/ci.yml
new file mode 100644
index 0000000..304ec06
--- /dev/null
+++ b/laravel/ci.yml
@@ -0,0 +1,14 @@
+prepare:
+ steps:
+ - name: "Install dependencies"
+ command: "composer install --no-interaction"
+
+test:
+ steps:
+ - name: "Run migrations"
+ command: "php artisan migrate --force 2>&1 || true"
+
+run:
+ steps:
+ - name: "Start Laravel dev server"
+ command: "php artisan serve --host=0.0.0.0 --port=3000"
\ No newline at end of file
diff --git a/laravel/composer.json b/laravel/composer.json
new file mode 100644
index 0000000..7d520fa
--- /dev/null
+++ b/laravel/composer.json
@@ -0,0 +1,51 @@
+{
+ "name": "codesphere/laravel-quiz-app",
+ "description": "Laravel Quiz App Template for Codesphere",
+ "type": "project",
+ "require": {
+ "php": "^8.1",
+ "laravel/framework": "^10.0",
+ "guzzlehttp/guzzle": "^7.2"
+ },
+ "require-dev": {
+ "fakerphp/faker": "^1.9.1",
+ "laravel/sail": "^1.18",
+ "mockery/mockery": "^1.4.4",
+ "nunomaduro/collision": "^7.0",
+ "phpunit/phpunit": "^10.1"
+ },
+ "autoload": {
+ "psr-4": {
+ "App\\": "app/",
+ "Database\\Factories\\": "database/factories/",
+ "Database\\Seeders\\": "database/seeders/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Tests\\": "tests/"
+ }
+ },
+ "scripts": {
+ "post-autoload-dump": [
+ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
+ "@php artisan package:discover --ansi"
+ ]
+ },
+ "extra": {
+ "laravel": {
+ "dont-discover": []
+ }
+ },
+ "config": {
+ "optimize-autoloader": true,
+ "preferred-install": "dist",
+ "sort-packages": true,
+ "allow-plugins": {
+ "pestphp/pest-plugin": true,
+ "php-http/discovery": true
+ }
+ },
+ "minimum-stability": "stable",
+ "prefer-stable": true
+}
\ No newline at end of file
diff --git a/laravel/config/app.php b/laravel/config/app.php
new file mode 100644
index 0000000..193f218
--- /dev/null
+++ b/laravel/config/app.php
@@ -0,0 +1,41 @@
+ env('APP_NAME', 'Laravel Quiz App'),
+ 'env' => env('APP_ENV', 'production'),
+ 'debug' => (bool) env('APP_DEBUG', false),
+ 'url' => env('APP_URL', 'http://localhost'),
+ 'timezone' => 'UTC',
+ 'locale' => 'en',
+ 'fallback_locale' => 'en',
+ 'faker_locale' => 'en_US',
+ 'key' => env('APP_KEY'),
+ 'cipher' => 'AES-256-CBC',
+ 'maintenance' => ['driver' => 'file'],
+ 'providers' => [
+ Illuminate\Auth\AuthServiceProvider::class,
+ Illuminate\Broadcasting\BroadcastServiceProvider::class,
+ Illuminate\Bus\BusServiceProvider::class,
+ Illuminate\Cache\CacheServiceProvider::class,
+ Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
+ Illuminate\Cookie\CookieServiceProvider::class,
+ Illuminate\Database\DatabaseServiceProvider::class,
+ Illuminate\Encryption\EncryptionServiceProvider::class,
+ Illuminate\Filesystem\FilesystemServiceProvider::class,
+ Illuminate\Foundation\Providers\FoundationServiceProvider::class,
+ Illuminate\Hashing\HashServiceProvider::class,
+ Illuminate\Mail\MailServiceProvider::class,
+ Illuminate\Notifications\NotificationServiceProvider::class,
+ Illuminate\Pagination\PaginationServiceProvider::class,
+ Illuminate\Pipeline\PipelineServiceProvider::class,
+ Illuminate\Queue\QueueServiceProvider::class,
+ Illuminate\Redis\RedisServiceProvider::class,
+ Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
+ Illuminate\Session\SessionServiceProvider::class,
+ Illuminate\Translation\TranslationServiceProvider::class,
+ Illuminate\Validation\ValidationServiceProvider::class,
+ Illuminate\View\ViewServiceProvider::class,
+ App\Providers\AppServiceProvider::class,
+ ],
+ 'aliases' => Illuminate\Support\Facades\Facade::defaultAliases()->toArray(),
+];
\ No newline at end of file
diff --git a/laravel/config/database.php b/laravel/config/database.php
new file mode 100644
index 0000000..7305081
--- /dev/null
+++ b/laravel/config/database.php
@@ -0,0 +1,18 @@
+ 'sqlite',
+ 'connections' => [
+ 'sqlite' => [
+ 'driver' => 'sqlite',
+ 'url' => env('DATABASE_URL'),
+ 'database' => database_path('database.sqlite'),
+ 'prefix' => '',
+ 'foreign_key_constraints' => true,
+ ],
+ ],
+ 'migrations' => [
+ 'table' => 'migrations',
+ 'update_date_on_publish' => true,
+ ],
+];
\ No newline at end of file
diff --git a/laravel/database/migrations/2024_01_01_000000_create_quizzes_questions_tables.php b/laravel/database/migrations/2024_01_01_000000_create_quizzes_questions_tables.php
new file mode 100644
index 0000000..73b9156
--- /dev/null
+++ b/laravel/database/migrations/2024_01_01_000000_create_quizzes_questions_tables.php
@@ -0,0 +1,33 @@
+id();
+ $table->string('title');
+ $table->text('description')->nullable();
+ $table->timestamps();
+ });
+
+ Schema::create('questions', function (Blueprint $table) {
+ $table->id();
+ $table->foreignId('quiz_id')->constrained()->onDelete('cascade');
+ $table->text('question_text');
+ $table->json('options');
+ $table->string('correct_answer');
+ $table->timestamps();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('questions');
+ Schema::dropIfExists('quizzes');
+ }
+};
\ No newline at end of file
diff --git a/laravel/laravel.webp b/laravel/laravel.webp
new file mode 100644
index 0000000..e69de29
diff --git a/laravel/metadata.json b/laravel/metadata.json
new file mode 100644
index 0000000..278efa3
--- /dev/null
+++ b/laravel/metadata.json
@@ -0,0 +1,9 @@
+{
+ "Workspace": "free",
+ "Links": {
+ "Laravel": "https://codesphere.com/articles/laravel"
+ },
+ "Categories": ["Framework", "PHP"],
+ "Contributors": ["opencode-MiniMaxM27"],
+ "Title": "Laravel Quiz App"
+}
\ No newline at end of file
diff --git a/laravel/public/index.php b/laravel/public/index.php
new file mode 100644
index 0000000..6311fb8
--- /dev/null
+++ b/laravel/public/index.php
@@ -0,0 +1,11 @@
+handleRequest(Request::capture());
\ No newline at end of file
diff --git a/laravel/resources/views/layouts/app.blade.php b/laravel/resources/views/layouts/app.blade.php
new file mode 100644
index 0000000..90c4576
--- /dev/null
+++ b/laravel/resources/views/layouts/app.blade.php
@@ -0,0 +1,50 @@
+
+
+
+
+
+ @yield('title', 'Laravel Quiz App')
+
+
+
+
+
+ @if(session('success'))
+
{{ session('success') }}
+ @endif
+ @yield('content')
+
+
+
\ No newline at end of file
diff --git a/laravel/resources/views/quizzes/create.blade.php b/laravel/resources/views/quizzes/create.blade.php
new file mode 100644
index 0000000..d543985
--- /dev/null
+++ b/laravel/resources/views/quizzes/create.blade.php
@@ -0,0 +1,27 @@
+@extends('layouts.app')
+
+@section('title', 'Create Quiz')
+
+@section('content')
+
+@endsection
\ No newline at end of file
diff --git a/laravel/resources/views/quizzes/index.blade.php b/laravel/resources/views/quizzes/index.blade.php
new file mode 100644
index 0000000..90787f0
--- /dev/null
+++ b/laravel/resources/views/quizzes/index.blade.php
@@ -0,0 +1,46 @@
+@extends('layouts.app')
+
+@section('title', 'All Quizzes')
+
+@section('content')
+
+
Available Quizzes
+
Create New Quiz
+
+ @if($quizzes->count())
+
+
+
+ Title
+ Questions
+ Actions
+
+
+
+ @foreach($quizzes as $quiz)
+
+
+ {{ $quiz->title }}
+ @if($quiz->description)
+ {{ $quiz->description }}
+ @endif
+
+ {{ $quiz->questions_count }} questions
+
+ View
+
+
+ @endforeach
+
+
+
+
+ {{ $quizzes->links() }}
+
+ @else
+
+ No quizzes yet. Create the first one!
+
+ @endif
+
+@endsection
\ No newline at end of file
diff --git a/laravel/resources/views/quizzes/result.blade.php b/laravel/resources/views/quizzes/result.blade.php
new file mode 100644
index 0000000..c08086d
--- /dev/null
+++ b/laravel/resources/views/quizzes/result.blade.php
@@ -0,0 +1,28 @@
+@extends('layouts.app')
+
+@section('title', 'Quiz Results')
+
+@section('content')
+
+
{{ $quiz->title }} - Results
+
+
+ {{ $score }} / {{ $total }}
+
+
+
+ @if($score >= $total * 0.7)
+ Great job! You passed!
+ @elseif($score >= $total * 0.4)
+ Not bad! Keep practicing.
+ @else
+ Keep learning and try again!
+ @endif
+
+
+
+
+@endsection
\ No newline at end of file
diff --git a/laravel/resources/views/quizzes/show.blade.php b/laravel/resources/views/quizzes/show.blade.php
new file mode 100644
index 0000000..6b602fb
--- /dev/null
+++ b/laravel/resources/views/quizzes/show.blade.php
@@ -0,0 +1,70 @@
+@extends('layouts.app')
+
+@section('title', $quiz->title)
+
+@section('content')
+
+
{{ $quiz->title }}
+ @if($quiz->description)
+
{{ $quiz->description }}
+ @endif
+
+ @if($quiz->questions->count() > 0)
+
+ @else
+
+ No questions yet. Add some questions to make the quiz playable.
+
+ @endif
+
+
+
+@endsection
\ No newline at end of file
diff --git a/laravel/routes/console.php b/laravel/routes/console.php
new file mode 100644
index 0000000..32dab09
--- /dev/null
+++ b/laravel/routes/console.php
@@ -0,0 +1,8 @@
+comment(Inspiring::quote());
+})->purpose('Display an inspiring quote');
\ No newline at end of file
diff --git a/laravel/routes/web.php b/laravel/routes/web.php
new file mode 100644
index 0000000..031f2fd
--- /dev/null
+++ b/laravel/routes/web.php
@@ -0,0 +1,16 @@
+except(['index']);
+Route::post('/quizzes/{quiz}/take', [QuizController::class, 'take'])->name('quizzes.take');
\ No newline at end of file
diff --git a/laravel/start.sh b/laravel/start.sh
new file mode 100644
index 0000000..f2efe52
--- /dev/null
+++ b/laravel/start.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -e
+
+echo "Installing dependencies..."
+composer install --no-interaction --no-scripts
+
+echo "Creating SQLite database..."
+touch database/database.sqlite
+
+echo "Running migrations..."
+php artisan migrate --force
+
+echo "Starting Laravel development server..."
+php artisan serve --host=0.0.0.0 --port=3000
\ No newline at end of file