diff --git a/.github/workflows/design-system.yml b/.github/workflows/design-system.yml new file mode 100644 index 0000000..25a17db --- /dev/null +++ b/.github/workflows/design-system.yml @@ -0,0 +1,24 @@ +name: Design system + +on: + pull_request: + push: + branches: + - main + +jobs: + design-contract: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - name: Install dependencies + run: npm ci + - name: Check design-system contract + run: npm run design:check diff --git a/.gitignore b/.gitignore index 5a409c5..b2e0e60 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ # next.js /.next/ /out/ +/public/monaco/ +/public/excalidraw/ # production /build @@ -35,6 +37,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.example # vercel .vercel @@ -42,3 +45,4 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts +/public/syntax/ diff --git a/AGENTS.md b/AGENTS.md index 8bd0e39..643577d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,9 @@ + # This is NOT the Next.js you know -This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/README.md b/README.md index 6952762..41ca0c1 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,122 @@
-logo
-
-Learn programming the smart way.

+ ScripticX +

Learn programming visually, one small idea at a time.

+

+ Open the platform · + Visit the landing page +

+
+ +# ScripticX platform + +ScripticX is a bilingual (Romanian / English) learning platform for students, teachers and independent learners. It combines the MiniScript+ language with guided lessons, automatically graded problems, a collaborative community and a browser-based editor. + +The current release adds the platform experiences that were not part of the original pre-alpha: dedicated workspaces, Groups, Competitions, the Rewards Shop, a structured learning roadmap, accessibility mode and a new editor with GitHub integration. + +## What is included -[![GitHub stars](https://img.shields.io/github/stars/Sank34/scripticx?style=social)](https://github.com/Sank34/scripticx/stargazers) -[![License](https://img.shields.io/github/license/Sank34/scripticx)](https://github.com/Sank34/scripticx/blob/main/LICENSE) -[![Version](https://img.shields.io/github/package-json/v/Sank34/scripticx)](https://github.com/Sank34/scripticx/blob/main/package.json) -[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-red)](https://buymeacoffee.com/scripticx) +| Area | What users can do | +| --- | --- | +| **MiniScript+ editor** | Write, run and debug code in the browser with step-through execution, live diagnostics, syntax highlighting and custom editor settings. | +| **Learning roadmap** | Follow localized paths, chapters and lessons with quizzes, progress gates and recommended practice. | +| **Problems** | Search and solve automatically graded problems, browse chapters and download a branded PDF statement. | +| **Groups** | Chat in channels, share images and GIFs, use named custom emoji and preview media in a focused modal. | +| **Competitions** | Join public or invite-only contests, with participant invitations managed by username search or CSV upload. | +| **Rewards Shop** | Spend points on cosmetic items and manage owned items in Inventory. | +| **Workspaces** | Personal, Student and Teacher workspaces expose the tools and navigation relevant to each role. | +| **Community** | Share posts and snippets, mention users, follow progress and compare results on leaderboards. | +| **Accessibility** | Turn on a higher-contrast visual mode designed for projectors and colour-vision differences. | +| **Administration** | Manage content, chapters, announcements, roles and granular permissions from one secure admin surface. | -

ScripticX is a modern programming learning platform built around MiniScript+, a language built specifically for beginners, avoiding technical barriers. It features an in-browser code editor, auto-graded problems, classes & lessons, live coding sessions, and a full community feed for students to share their progress. The platform is fully bilingual (RO/EN) and runs entirely client-side (private code execution). +## Screenshots + +
+ ScripticX editor +

+ ScripticX problems and roadmap chapters +

+ ScripticX Rewards Shop +

+ ScripticX on mobile
+## MiniScript+ -### Main Features +MiniScript+ is a small educational language with readable, beginner-friendly syntax and localized runtime messages. It runs directly in the browser and includes variables, conditions, loops, functions, return values and input/output. - **In-browser Editor**
+```msp +FUNCTION build(x, y) + RETURN x + y +END - **Auto-graded Problems**
+FOR i FROM 1 TO 5 INCR 1 + PRINT build(i, 2) +END +``` - **Classes & Lessons**
+`INCR` is optional. `RETURN` ends the current function immediately and sends its value back to the caller. - **Livecode**
+## Run locally - **Community Feed**
+Requirements: Node.js 20 or newer and npm 10 or newer. - **Progress Tracking**
+```bash +git clone https://github.com/Sank34/scripticx.git +cd scripticx +npm install +``` - **Profiles**
+Create `.env.local` with the Supabase project URL and anonymous key: -
+```dotenv +NEXT_PUBLIC_SUPABASE_URL=... +NEXT_PUBLIC_SUPABASE_ANON_KEY=... +``` -### Sneak Peek -logo
-
-logo
-
+Start the development server at `http://localhost:3000`: -### Tech Stack -![Next.js](https://img.shields.io/badge/Next.js-black?logo=next.js&logoColor=white) -![React](https://img.shields.io/badge/React-20232A?logo=react&logoColor=61DAFB) -![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white) -![Supabase](https://img.shields.io/badge/Supabase-3ECF8E?logo=supabase&logoColor=white) -![Tailwind CSS](https://img.shields.io/badge/Tailwind-06B6D4?logo=tailwindcss&logoColor=white) +```bash +npm run dev +``` -
+For a production build: + +```bash +npm run build +npm run start +``` + +## Project layout + +```text +scripticx/ +├── app/ # Next.js routes and API handlers +│ ├── admin/ # Admin workspace and content management +│ ├── editor/ # MiniScript+ and multi-language editor +│ ├── learn/ # Roadmap, paths and lessons +│ ├── problems/ # Problem library and submissions +│ ├── competitions/ # Contest browsing and participation +│ ├── groups/ # Community groups and channels +│ └── workspace/ # Student and teacher tools +├── components/ # Shared UI, shell and feature components +├── hooks/ # Client data and interaction hooks +├── lib/ # Interpreter, permissions, i18n and services +├── public/ # Logos, screenshots and static assets +└── supabase/migrations/ # Database schema and security migrations +``` + +## Architecture and security + +The app uses Next.js App Router with React Server and Client Components, React Query for server-state caching, Tailwind CSS and accessible Radix-based UI primitives. Supabase provides PostgreSQL, authentication, realtime updates and storage. + +Authorization is enforced in API handlers and database policies. Platform access modes, workspace restrictions, competitions and custom roles are checked server-side; UI visibility is only a convenience layer. Custom roles can grant specific tools without exposing unrelated admin capabilities. + +MiniScript+ executes in the browser. Other supported languages are evaluated by an isolated execution service with explicit limits. See [`docs/code-execution.md`](docs/code-execution.md) for the execution model. + +## Internationalization + +The `LanguageProvider` switches the interface between Romanian and English and persists the preference for the signed-in account. Lesson, roadmap and problem content use localized fields, so each language can be edited and saved independently in the admin configurator. + +## Licence + +ScripticX is developed by ScripticX SRL. See the repository licence and the notices included with third-party assets before redistributing the project. diff --git a/app/admin/announcements/page.tsx b/app/admin/announcements/page.tsx new file mode 100644 index 0000000..0c72500 --- /dev/null +++ b/app/admin/announcements/page.tsx @@ -0,0 +1,41 @@ +"use client"; + +import { useState } from "react"; +import { Megaphone } from "lucide-react"; +import { toast } from "sonner"; +import RouteGuard from "@/components/RouteGuard"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { supabase } from "@/lib/supabase"; + +export default function AdminAnnouncementsPage() { + const [title, setTitle] = useState(""); + const [body, setBody] = useState(""); + const [href, setHref] = useState(""); + const [busy, setBusy] = useState(false); + async function send() { + setBusy(true); + try { + const { data: { session }, error } = await supabase.auth.getSession(); + if (error) throw error; + if (!session) throw new Error("Your session has expired. Please sign in again."); + + const response = await fetch("/api/admin/announcements", { + method: "POST", + headers: { + "content-type": "application/json", + Authorization: `Bearer ${session.access_token}`, + }, + body: JSON.stringify({ title, body, href }), + }); + const result = await response.json(); + if (!response.ok) throw new Error(result.error || "Could not send announcement"); + toast.success(`Announcement sent to ${result.created} users`); + setTitle(""); setBody(""); setHref(""); + } catch (error) { toast.error(error instanceof Error ? error.message : "Could not send announcement"); } + finally { setBusy(false); } + } + return
Platform announcements

Send an announcement

The message appears in every user’s ScripticX notifications.

setTitle(event.target.value)} placeholder="Title" maxLength={160} />