Activity

Zain Marshall

v1.0.0 Devlog IV: All Panic Modes

All 8 SwiftUI panic challenges ported to Tauri.


Games

Feature

Minesweeper, Wordle, 2048, Sudoku, Simon Says, and Pipes - all faithfully recreated. Pipes reuses the same Hamiltonian path + flood-fill algorithm with SVG drag-to-draw.


Competitive programming

Feature

Split-pane IDE: problem statement with LaTeX math on the left, code editor on the right. Initially wrote a custom regex-based highlighter but it choked on C++ - #include was treated as a comment start, leaking raw HTML span tags into the display. Swapped it for CodeMirror 6 with oneDark, which handles C++/Python/Java properly and gives bracket matching and auto-indent for free. Rust backend compiles and judges against test cases.


Config

Feature

All 8 modes in the panic dropdown with per-mode difficulty configs (grid size, guess count, target tile, etc). Configs in localStorage, panic mode in ~/.config/bliss/panic_mode.txt.


Next up: Schedule tab, statistics, and system tray.

Changelog

c572c3d feat(ui): add all panic mode challenges to Tauri GUI

0
Zain Marshall

v1.0.0 Devlog III: Settings & Configs

I started transferring over all of the features from the SwiftUI version almost 1:1, but with web technology I can make some of the UI a lot cooler and better!

What changed


1. Settings panel

Feature

  • Sidebar + detail layout matching the SwiftUI version. Seven sections in the same order: Configs, Panic Challenge, Blocked Websites, Blocked Apps, Browsers, Troubleshooting, Uninstall.
  • Icons from Lucide (Folder, ShieldAlert, Globe, LayoutGrid, Compass, Wrench, Trash2) instead of SF Symbols.
  • Blocked websites has preset packs (Social Media, Entertainment, News, Gaming, Shopping) that toggle green when active. Apps and browsers show real icons extracted from .app bundles via sips.

2. Config profiles

Feature

  • Save current websites/apps/browsers/panic settings as a named config. Configs stored as JSON in ~/.config/bliss/profiles/.
  • Apply swaps everything at once - clears current config and loads the profile’s. Active config highlighted with color dot.
  • Simpler flow than SwiftUI - no color picker, just save/apply/delete.

3. Native file pickers

System

  • “Add App…” and “Add Browser…” open native macOS file dialogs via tauri-plugin-dialog, filtered to .app bundles. Same UX as the SwiftUI fileImporter.
  • App icons extracted server-side in Rust: reads CFBundleIconFile from Info.plist, converts .icns to 64x64 PNG with sips, sends base64 to the frontend. Browser icons resolved via mdfind bundle ID lookup.

Next up: Schedule tab, statistics tab with activity heatmap, and system tray menubar.

Attachment
0
Zain Marshall

v1.0.0 Devlog II: Tauri GUI Scaffold

I decided to use Tauri with Svelte because Svelte compiles to be lightweight and I am familiar with it. I don’t want to use many other web technologies as to keep this lightweight and also look clean and simple, I want to capture the aesthetic of the SwiftUI app.

Scaffolding the cross-platform GUI: timer, session start, and typing panic challenge.


What changed


1. Tauri + Svelte project setup

Framework

  • Tauri v2 inside the existing repo (src-tauri/ for Rust, ui/ for Svelte 5 with runes) — Vite builds to dist/, Tauri serves it in a native webview.
  • Rust backend shells out to the bliss CLI exactly like Swift’s BlissCommandRunner did.

2. Session timer with digit entry

Feature

  • Polls /var/db/bliss_end_time every second; displays HH:MM:SS with an orange pulse in the last minute.
  • No active session → right-to-left digit entry; Start button calls bliss start <minutes> via Rust.

3. Typing panic challenge

Feature

  • Loads a random quote from quotes.txt; character-by-character coloring (green/red/grey) — same MonkeyType feel as Swift.
  • Hidden textarea captures keystrokes; submit calls bliss panic --skip-challenge on completion.

4. Dark minimal UI

Design

  • Dark grey (#1a1a1a), centered layout, big timer — mirrors the Swift version’s aesthetic.
  • SF Pro / system font stack; native on macOS, falls back to system sans-serif on Linux.

Next up: Tab navigation (Session/Settings), blocked sites/apps config UI, and menubar tray with countdown.

1

Comments

grumpymarie
grumpymarie 10 days ago

this looks rly cool!!

Zain Marshall

v1.0.0 Devlog I: Linux Time!!

Its finally time to add Linux support! So on the macOS version I wrote it in Swift so it would be native and super fast, and I didn’t want to use electron as its slow, so for the cross platform I decided to rewrite the GUI to Tauri so it can support macOS, now Linux, and later Windows!

Platform-abstracting the C++ backend: firewall, DNS flush, and process management.


What changed


1. Linux firewall implementation

Feature

  • firewall_linux.cpp: full iptables/ip6tables impl mirroring macOS pfctl via a dedicated bliss chain.
  • firewall_block.cpp wrapped in #ifdef __APPLE__; works on modern distros via the iptables-nft shim.

2. DNS cache flush

System

  • Platform-guarded flush_dns(): macOS uses dscacheutil + mDNSResponder, Linux tries resolvectl, falls back to systemd-resolve, pokes nscd for legacy setups. Fails silently throughout.

3. Browser killing

Feature

  • kill_browser_apps() now cross-platform via pkill -x. macOS-only helpers guarded behind #ifdef __APPLE__.

4. Build system

System

  • CMakeLists.txt picks firewall source per platform. Best tested on Ubuntu 24.04 in UTM/VirtualBox; Docker needs --privileged for iptables.

Next up: Platform-abstract the daemon - systemd service files instead of launchd plists, and reworking the root helper socket.

Attachment
0
Zain Marshall

Bliss v1.0.0 idea

One of the most requested features on Bliss has been Linux support. So that is what I have decided to do from now one! Here is the plan:

  1. Make sure the CLI works on Linux (the daemon, the firewall filters, etc)
  2. Convert the SwiftUI frontend to Tauri and Svelte
Attachment
1

Comments

elifeldman769
elifeldman769 13 days ago

so excited

Zain Marshall

Zen++ Devlog XVIII - C++ Transpiler

New Feature

Started building a C++ Transpiler so that you can write Zen++ and get C++ out. Similar to a compiler, but instead of going to assembly it goes to a higher level language which itself can be compiled down to assembly so I don’t have to code all the low-level optimizations.

The transpiler walks the same AST the interpreter uses, but emits C++ instead of evaluating. The interpreter is completely unchanged.

What Changed

  1. C++ transpiler

    • New CLI flag: zenpp --emit-cpp solution.zpp outputs valid C++ to stdout.
    • All binary operators, bitwise ops, comparisons, and logical ops are supported.
    • Variables get auto type inference.
    • Control flow: if/else, while, for loops.
    • Functions with default arguments and recursion.
    • IO: println/print map to cout, read() maps to cin.
    • Builtins mapped: len, push, sort, min, max, abs, gcd.
    • Ternary, break, continue, return.
  2. Generated output

    • Outputs a complete C++ file with includes, fast IO, and int64_t types.
    • Pipe to g++ and you have a native binary ready for Codeforces.

What’s next

Vectors, strings, for-each, maps, lambdas, and a “Generate C++” button in the web IDE.

Attachment
0
Zain Marshall

Shipped this project!

Hours: 28.47
Cookies: 🍪 763
Multiplier: 26.81 cookies/hr

Zen++ v0.2.0

A fast interpreted language for competitive programming. C-style syntax, no semicolons, auto type inference, stdlib with data structures and algorithms.

Try it in your browser

New since v0.1.0

Language: bulk I/O (read(n)), type casting, ternary, negative indexing, multiple assignment & swap, lambdas, slicing (v[1:4], v[::-1]), tuple unpacking, default args, bitwise shifts, string builtins (replace, upper, lower, trim, contains, startswith, endswith, substr), multi-dim fill, f-strings, chained comparisons (1 < x < 10), destructuring, min(v)/max(v), all/any, reverse, unique, sorted, flatten, zip, rand, randvec, string iteration.

Stdlib: lcm, modpow, prefix, sum, lowerBound, upperBound, binarySearch, dijkstra, bfs, graph builtins, FenwickTree, SegTree, MinPriorityQueue.

11x faster interpreter - flag-based control flow, arena allocator, scope frame reuse, constant folding. Optimizations.

Web IDE - 6 themes, intellisense with signatures, f-string highlighting, 22 samples.

VS Code v0.2.3 - f-string highlighting, run button (Cmd+Enter), file icons.

Runs as CLI (zenpp file.zpp), browser, or VS Code.

Zain Marshall

Zen++ Devlog XVII - v0.2.0 polishing

What Changed

  1. New builtins

    • rand(lo, hi), randvec(n, lo, hi) - random number generation.
    • exit() - terminate program.
    • reverse(v) - reverse vector or string in-place.
    • unique(v) - remove consecutive duplicates.
    • sorted(v) - return a sorted copy without modifying the original.
    • flatten(v) - flatten one level of nesting.
    • zip(a, b) - pair up two vectors into [[a[0],b[0]], ...].
  2. String iteration - for c in s { } iterates over each character in a string.

  3. FenwickTree and SegTree (import std)

    • FenwickTree - point update + prefix/range sum queries in O(log n).
    • SegTree - range sum queries + point updates in O(log n). Build from an array with st.build(arr).
  4. VS Code extension v0.2.0 + web IDE syntax highlighting

    • F-string interpolation highlighting - expressions inside {} are colored normally, string parts stay green.
    • All new builtins highlighted (sorted, unique, flatten, zip, rand, replace, upper, lower, all, any, etc.).
    • Stdlib classes highlighted as types (FenwickTree, SegTree, MinPriorityQueue, etc.).
    • Bitwise shift (<<, >>) and NOT (~) operator highlighting.
    • User-defined function calls get their own highlight color in VS Code.
    • VS Code extension and web IDE are now in sync.
  5. Web IDE intellisense overhaul

    • Added code snippets for fn, for, while, if, struct.
  6. Samples cleanup

  7. No need for import std anymore

Attachment
Attachment
Attachment
0
Zain Marshall

Zen++ Devlog XVI - Website

Two small website improvements:

  1. Sample dropdown label - selecting a sample now updates the dropdown text to show what’s loaded instead of always saying “Samples”.
  2. Settings / theme switcher - added a settings cog in the toolbar that opens a theme picker. Ships with 6 themes: Tokyo Night (default), Dracula, Catppuccin Mocha, GitHub Dark, Gruvbox, and Nord. Selection persists via localStorage.

Changelog

Attachment
Attachment
Attachment
0
Zain Marshall

Zen++ Devlog XV - Optimization Time!

Four optimizations to the interpreter. Combined: 11x speedup on composite benchmark (33.7s → 3.05s).

What Changed

  1. Flag-based control flow - replaced C++ throw/catch for return/break/continue with a Signal enum. Function calls: 7.5s → 0.4s (17x).
  2. Arena allocator - AST nodes allocated from contiguous 4096-node blocks instead of individual new. Better cache locality.
  3. Scope frame reuse - function calls reuse cleared unordered_map frames instead of alloc/free each call. Variable ops: 1.14s → 1.00s.
  4. Constant folding - 1 + 2 + 3 folds to 6 at parse time.

Benchmarks (before → after)

  • Simple loop (1M): 1.08s → 0.95s (1.1x)
  • Function calls (100K): 7.53s → 0.36s (21x)
  • Variable read/write (500K): 1.14s → 1.00s (1.1x)
  • Vector push (100K): 0.16s → 0.14s (1.1x)
  • Composite (all + fib(25)): 33.67s → 3.05s (11x)

Changelog

Attachment
0
Zain Marshall

Zen++ Devlog XIV

More language features. Bitwise NOT, f-strings, chained comparisons, destructuring, min/max on vectors, and all/any predicates.

What Changed

  1. Bitwise NOT (~)

    • ~x gives bitwise complement. clearBit is now just n & ~(1 << i).
  2. min(v) / max(v) on vectors

    • min([3, 1, 4]) returns 1. max([3, 1, 4]) returns 4.
    • Still works with 2 args: min(a, b). No import std needed anymore.
  3. String interpolation

    • f"hello {name}, {1 + 2} = {3}" - expressions inside {} are evaluated and stringified.
  4. all(v, fn) / any(v, fn)

    • all(v, fn(x) { x > 0 }) - true if every element passes.
    • any(v, fn(x) { x > 0 }) - true if at least one passes. Short-circuits.
  5. Chained comparisons

    • 1 < x < 10 works like 1 < x && x < 10. Any number of comparisons can be chained.
  6. Destructuring assignment

    • [a, b, c] = v unpacks a vector into variables. Supports _ to discard.
    • [x, _, z] = getPoint() - grab first and third, skip second.
  7. Newline-aware postfix parsing

    • Fixed a parser ambiguity where [ on a new line was consumed as an index operator from the previous expression. Indexing with [ now requires it to be on the same line as the expression.
Attachment
Attachment
0
Zain Marshall

Shipped this project!

Hours: 67.74
Cookies: 🍪 1130
Multiplier: 21.97 cookies/hr

Bliss v0.4.0

Bliss is a simple, clean, macOS productivity app that blocks websites & apps and has panic challenges instead of passwords to escape to create a negative incentive against unblocking apps.

  • Configurable blocked lists
  • Timer based blocking
  • Dual-layer blocking (hosts and pf firewall) that survives reboots
  • Clean Swift GUI + Menubar + C++ Backend
  • Weekly session scheduling to autoblock
  • 8 panic challenges: Typing, Competitive Programming, Minesweeper, Pipes, Sudoku, Simon Says, Wordle, 2048
  • Viewable statistics and heatmap for motivation
  • Easy install and uninstall with a Setup Wizard

GitHub: https://github.com/zainmarshall/bliss

curl -fsSL "https://github.com/zainmarshall/bliss/releases/download/v0.4.0/bliss-macos-universal.zip" -o /tmp/bliss.zip && rm -rf /tmp/bliss && mkdir -p /tmp/bliss && unzip -q /tmp/bliss.zip -d /tmp/bliss && bash /tmp/bliss/bliss_release/scripts/install.sh

Video

There is a video both in the Github ReadMe and in the Demo that shows a full demo of Bliss to non-MacOS users of Flavortown.

Zain Marshall

Bliss v0.5.0 Devlog

Ghost Window Fix

  • Menubar “Open Bliss” no longer shows an empty window - intercepts close with orderOut instead of actually closing, keeping SwiftUI’s view tree alive

Scheduling

  • New Schedule tab with 24h weekly calendar grid and schedule list
  • Create schedules tied to saved configs - auto-triggers sessions at the set day/time
  • 12-hour time picker with AM/PM, day-of-week toggles, click-to-type digit editing

Config System

  • Renamed “Profiles” → “Configs” across the UI
  • Color picker per config - popover swatch grid, colors carry through to schedule blocks on the calendar
  • Auto-creates a “Default” config with common social media sites on first launch

Timer UI

  • Replaced text field with a big --:-- display, right-to-left digit entry like a microwave timer
  • Typed digits shift in from the right, backspace removes last digit, Enter starts session
  • Same display becomes the live countdown during active sessions

Typing Panic

  • 100% accuracy required (was 95%), larger text, no background box
  • Wrong characters show underlined in red, extra chars get red background (MonkeyType-style)

Install Script

  • Colored output with numbered steps, checkmarks, and a clean summary
Attachment
Attachment
Attachment
0
Zain Marshall

Zen++ Devlog XIII

This time I added a few nice functionality things and language features from a variety of languages.

What Changed

  1. Lambda functions

    • Anonymous functions as expressions: fn(a, b) { a - b }.
    • sort(v, fn(a, b) { a[1] - b[1] }) - sort a vector of pairs by second element, inline.
  2. Slicing

    • Python-style slicing for vectors and strings: v[1:4], s[0:5], v[::-1].
    • v[::-1] - reversed copy.
  3. Tuple unpacking in for-each

    • for u, v in edges { } - destructure each element when iterating vectors of vectors.
    • for k, v in myMap { } - iterate key-value pairs of a map.
  4. Default function arguments

    • fn solve(n, mod = 1000000007) { ... } - parameters with = value get defaults.
    • Required params must come before optional ones.
  5. Bitwise shift operators

    • << and >>
    • Compound assignments: x <<= 3, x >>= 1.
  6. String manipulation builtins

    • replace(s, old, new) - replace all occurrences.
    • upper(s) / lower(s) - case conversion.
    • startswith(s, prefix) / endswith(s, suffix) - boolean checks.
    • trim(s) - strip leading/trailing whitespace.
    • substr(s, start) or substr(s, start, len) - substring with negative index support.
    • contains(s, sub) - check if string contains substring.
  7. Multi-dimensional fill()

    • fill(n, m, val) creates an n×m grid filled with val.
    • fill(n, m, k, val) creates a 3D array. Works for any number of dimensions.
    • Each row is an independent deep copy, so grid[0][0] = 5 doesn’t affect grid[1][0].
    • Before: grid = fill(n, fill(m, 0)). Now: grid = fill(n, m, 0). Cleaner and fewer mistakes.
Attachment
Attachment
Attachment
0
Zain Marshall

Bliss v0.4.0 devlog

What Changed

  • Added a statistics screen
  • Added a simon says panic mode
  • Merged the seperate blissbar into main GUI
  • Renamed app from BlissGUI to just Bliss
  • 2048 difficulty levels: Easy (128), Medium (512), Hard (2048)
  • Customizable keyboard shortcuts for panic and start session with NSEvent-based recorder
  • Settings sidebar navigation modeled after macOS System Settings
  • Toggleable website preset packs in both settings and wizard
  • Tile pop-in animations on 2048
  • Timer pulse animation in the last minute of a session

Bug fixes and polish

  • Deduplicated website display so www. variants don’t show twice
  • Wizard website list now scrolls with a max height cap
  • Improved add website field with plus icon and clearer placeholder
  • Removed clutter text like keyboard shortcut hints
  • Removed 2048 merge/error sounds, kept unlock sound
  • Lightened stat cards and heatmap empty cells for dark mode visibility
  • Removed focus rings from non-interactive settings elements
  • Removed View Statistics button from main screen
  • Removed heatmap background panel

Testing

  • Built UI test suite covering all 6 game modes
  • 60 tests, 203 assertions, all passing
  • 255 total assertions across both test files

Known issues

  • Wordle backspace key doesn’t work
0
Zain Marshall

Zen++ Devlog XII

Big batch of language features, new builtins, and stdlib additions.

What Changed

  1. Ternary operator

    • x = a > b ? a : b - inline conditionals, nestable.
    • Added ? and : tokens to lexer, TERNARY node type, and right-associative parsing so a ? b : c ? d : e works as expected.
  2. Negative indexing

    • v[-1] for last element, v[-2] for second-to-last.
  3. Multiple assignment

    • a, b = 1, 2 assigns multiple variables at once.
  4. _ in for loops

    • for _ n { } when you don’t need the loop variable. Works in for-each too.
  5. String repeat

    • "ha" * 3 gives "hahaha". Works both ways: 3 * "ha".
  6. New builtins

    • split(s, delim) - split string into vector of strings.
    • join(v, delim) - join vector elements into a string.
    • find(v, x) - first index of x in vector or string, -1 if not found.
    • count(v, x) - count occurrences in vector or string.
    • swap(v, i, j) - swap two elements in a vector (supports negative indices).
    • fill(n, val) - fills a vector of size n with val
  7. Graph builtins

    • graph(n) - create adjacency list with n empty vectors.
    • graph(n, m) - read m undirected edges (u v) from stdin, build adjacency list.
    • dgraph(n, m) - read m directed edges.
    • wgraph(n, m) - read m undirected weighted edges (u v w), stores [v, w] pairs.
    • dwgraph(n, m) - read m directed weighted edges.
  8. New stdlib functions (import std)

    • sum(v) - sum a vector.
    • lowerBound(v, x) / upperBound(v, x) - binary search returning insertion index in a sorted vector.
    • modpow(base, exp, mod) - modular exponentiation.
    • bfs(adj, start) - BFS shortest paths on unweighted graph, returns distance array.
  9. Internal fix

    • push(v[i], x) now works - you can push to indexed vectors directly (needed for manual adjacency list building).
Attachment
Attachment
Attachment
0
Zain Marshall

Zen++ Devlog XI

I compared my C++ competitive programming macro/template with Zen++ and realized there were a bunch of things the macro could do that Zen++ couldn’t. So I went through and added them.

What Changed

  1. Bulk I/O

    • read(n) reads n integers from stdin and returns a vector. No more manual loops to read input.
    • read(v) reads len(v) integers directly into an existing vector.
    • Same for readFloat(n) and readFloat(v).
    • Before: a = [] then for i n { push(a, read()) }. Now: a = read(n). One line.
  2. Type casting

    • str(x) converts any value (int, float, vector) to a string.
    • int(x) converts a string or float to an integer (truncates floats, parses strings).
    • float(x) converts a string or int to a float.
    • These replace the old parseInt() pattern with cleaner, more general casts.
  3. New stdlib math functions (import std)

    • lcm(a, b) - least common multiple.
    • mid(a, b) - midpoint, equivalent to (a + b) / 2.
    • ckmin(a, b) - returns the smaller of two values.
    • ckmax(a, b) - returns the larger of two values.
    • prefix(v) - builds a prefix sum array. Returns array of length len(v) + 1 where p[i] = sum of first i elements.
  4. Binary search (import std)

    • binarySearch(v, target) - searches a sorted vector for target, returns index or -1.
  5. Dijkstra’s algorithm

    • dijkstra(adj, start) - runs Dijkstra’s shortest path from start.
    • adj[u] is a list of [v, w] pairs (neighbor, weight).
    • Returns a distance array.
Attachment
Attachment
Attachment
0
Zain Marshall

Even More Panic Mode Challenges

I added a few more such as Sudoku, 2048, and Wordle!

Added Challs

Sudoku

  • Fill in a 9x9 grid so ever row, col, and box has digits 1-9
  • Three difficulties based on number of cells revealed
  • Random generated puzzles + always solvable

2048

  • Use arrow keys to slide tiles around
  • Matching tiles add up and double
  • Mimicked the normal UI

Wordle

  • From New York Times Games.
  • Guess five-letter word in six tries
  • Green for right, yellow for wrong spot, grey for not in the word.
Attachment
Attachment
Attachment
0
Zain Marshall

More Panic Mode Challenges

I made it easier to write new panic mode challenges and then I added two: minesweeper and that pipes / flow game
I also went and fixed some bugs with the uninstall and made the panic modes auto complete and no longer need confirmation. I also speed up the install script a lot (the old one tried to compile the whole thing instead of use the precompiled binary)

Panic Mode Abstraction

  • Each challenge is in a single .swift file that defines an enum with a static PanicChallengeDefinition which has a bunch of details, a wrapper view that reads config from BlissViewModel via @EnvironmentObject, and the game view itself which takes an onUnlock: () async -> Bool callback.
  • It is registered in PanicChallengeRegistry.all, with a size/difficulty @Published property + sync/save methods to BlissViewModel, and a @Published property to SetupWizardState.

Added Challs

  • Minesweeper:
    • Left click to dig, right click to flag
    • Mines are placed down after the first click
    • Three sizes for 8x8, 12x12, 16x16
    • Uses the google doodle color scheme because its fire
  • Pipes
    • Draw paths between dots of the same color and fill every cell
    • Puzzles randomly generated and always solvable
0
Zain Marshall

Bliss v0.3.0 release

There is now a github release for version v0.3.0! I won’t ship this on flavortown just yet and will most likely wait till v0.4.0 (more panic modes!), but it is on github for you to download: https://github.com/zainmarshall/bliss/releases/tag/v0.3.0

Setup Wizard

  • Since I’ve moved from CLI to GUI, the setup process can be a lot better
  • There is now a setup wizard that takes you through each step: blocking websites, apps, browsers, picking panic mode and configuring its difficulty.

Competitive Programming Panic Mode

  • I edited the Codeforces panic mode a bit and renamed it to competetive programming. I then used CSES problems beacuse they were easier to parse than codeforces problems.
  • I added Zen++ language support in it (my custom language)
  • LaTeX rendering!

Config Menu Redesign

  • Made it look more like an apple settings menu, so a lot cleaner
  • Aligned dropdowns, added keyboard shortcuts
  • The config menu shows the App Icons next to the apps so it looks nice
  • Added a panic challenge to uninstallation

CLI Fix

  • Now that it is a GUI based and not CLI I made the CLI redirect to the GUI on most tasks and then also they are synced now.
0
Zain Marshall

Shipped this project!

Hours: 38.8
Cookies: 🍪 1117
Multiplier: 28.8 cookies/hr

Zen++ v0.1.0 Ship

Zen++ is a fast, lightweight interpreted language designed for competitive programming.

Zen++ features C-style syntax with curly braces, no semicolons, automatic type inference, and a standard library with common data structures out of the box.

Try it in your browser

What’s in v0.1.0

The language has everything you need for competitive programming and then some:

  • Implicit variable declarations, 64-bit integers, floats, strings, booleans
  • Vectors, maps, sets with bracket indexing
  • Structs with fields, methods, and defaults
  • For loops (for i n, for i a b, for i a b step), for-each, while, break, continue
  • Functions with recursion, closures over global scope
  • Standard library: Stack, Queue, DSU, PriorityQueue, min/max/abs/gcd
  • Built-in IO: read(), readInt(), readFloat(), readLine(), print(), println()

It runs three ways:

  1. CLI interpreterzenpp file.zpp or just zenpp for the REPL
  2. Browser — full web IDE at zainmarshall.github.io/zen-plus-plus with syntax highlighting, autocomplete, and the interpreter compiled to WebAssembly
  3. VS Code — syntax highlighting extension on the Marketplace

I also solved a the full Codeforces Round 1084 (Div. 3) with Zen++ to prove it works.

Zain Marshall

Zen++ Devlog IX — v1 Polish

Big batch of changes getting ready for v1.

What Changed

  1. Map/Set bracket indexing

    • Maps now support m[key] for reading and m[key] = val for writing, like C++.
  2. Struct field definitions

    • Structs can now declare fields with default values directly in the body:
      struct Point {
          x = 0
          y = 0
          fn init(a, b) { self.x = a  self.y = b }
      }
      
  3. Break, continue, for-each

    • Added break and continue for loops.
    • Added for-each syntax: for x in collection { } to iterate over vectors, maps, and sets.
  4. Website: fixed intellisense

    • Added better intellisnse and removed filler words
  5. Website: docs button

    • Added a “Docs” link in the toolbar of website
  6. Packaging / install script

    • Added install.sh
  7. VSCode extension

    • Published it to VSCode Extnsion Marketplace
  8. Docs polish

    • Fixed some errors in the docs

Attachments

  1. A screenshot of the extnension in the VSCode Marketplace (so cool!!!)
  2. A screenshot of intellsense in the web interpreter
  3. Here is the link to the documentation: https://github.com/zainmarshall/zen-plus-plus/blob/master/docs/language-reference.md

Changelog

Attachment
Attachment
0
Zain Marshall

Zen++ Devlog VIII

I compiled the C++ Interpreter over to Web Assembly so I could make a web interpreter for it. Now that there is a website, you can demo it yourself and the screenshots on devlogs will be prettier! I am planning on shipping soon once I iron it out more and test it on actual codeforces problems.

What Changed

  1. Made a web UI inspired by USACO IDE, with Input and Output
  2. Added syntax highlighting to it (Tokyo night most goated theme)
  3. Added runtime error messages
  4. Fixed bugs in the language
  5. Added tests for the website

Changelog

Attachment
0
Zain Marshall

Zen++ Devlog VII

This batch saw a lot of new, big features, and some minor ones. Big: data structures, structs, imports. Small: bitwise operators, numerical type fixes, IO expansion.

What changed

  1. Numeric types

    • Integers are now 64-bit.
    • Added float
  2. Operators

    • Exponent operator is now **.
    • ^, &, | are bitwise operators.
    • Added compound assignments for bitwise ops.
  3. IO

    • Added readInt(), readFloat(), and readLine().
    • read() maps to readInt().
  4. Structs + methods + member access

    • New struct Name { fn ... } syntax.
    • Method calls with obj.method(...) and field access with obj.field.
    • Assignment to fields supported (obj.field = x).
  5. Imports + stdlib bundle

    • New import file and import std.
    • Stdlib is bundled via stdlib/manifest.txt and loaded by import std.
  6. Data structures

    • Hash table in runtime (map/set) for O(1).
    • Exposed as stdlib Map and Set structs.
    • Added DSU, PriorityQueue, Stack, Queue, Pair, Tuple in stdlib.
  7. Tests

    • Test runner has more complete coverage.
  8. Math functions

    • Added standard math functions like min(a,b), gcd(a,b) and abs(a) to stdlib bundle
Attachment
Attachment
0
Zain Marshall

Ok I know the last few changes have been UI changes and bug fixes, and this one will be the last of those.

  • I added a makefile so like I can just run make all and it recompiles and reinstalls everything, which is very nice.
  • I polished the UI a bit more and removed most bugs.
  • Added difficulty tags to codeforces problems
  • Panic mode randomly gives you a codeforces problem of matching difficulty
  • The thing I want to figure out now is the best way to get problems into the app, as right now I am manually copying and pasting codeforces problems over and tagging them by difficulty, I need to find a systematic way to do this
  • There is one bug in the timer in the UI I need to fix. In the menubar it counts down smoothly, but in the GUI its buggy, I need to do and fix that. Thats all thanks for reading!
Attachment
0
Zain Marshall
  1. I reworked the UI to be cleaner and moved all the configuration stuff to its own tab.
  2. You can also now configure which panic mode you want.
  3. There were also some bugs in the codeforces, that has been resolved now.
  4. You can open the GUI from the menu bar by clicking Command + O when it is open or clicking Open Menubar
0
Zain Marshall

From the start I never really wanted to do the typing challenge as the panic mode, I kinda just did it because I wanted to see the reaction to Bliss without pouring too much time into it. What I had always wanted to do was for you to be forced o solve a codeforce or a leetcode problem, but the logistics of this confused me. Would I just call and api or would I make the testcase runner work locally? How would I prevent just copying and pasting code which makes the panic easier to bypass? A lot of questions I still need to answer. But I did get a bit of the codeforces implemented! I parsed quite a few questions from the website and I also made a nice swift ui.

Changelog

  1. Codeforces panic mode
  2. UI for codeforces panic mode
Attachment
0
Zain Marshall

First, I want to say thank you everyone for the incredible votes! I’m very grateful that people liked this project :)

Now two things I observed from the feedback:

  1. A GUI would be nice
  2. Linux support would be nice

So of those two linux support is probably the more difficult one given that my software is pretty nicely integrated with MacOS, so what I think I’ll do is polish up the MacOS version and then given all that I have already done port it to Linux. This would involve changing a bit of the code, but not that much.

I started working on the GUI:

  1. (almost) every CLI command is now in the GUI, you can start, you can panic, and you can config
  2. The GUI is made using Swift so its super fast and just MacOS native, and the menubar was already native.
  3. The way it works is like the GUI is essentially just running CLI commands because like that was the easiest way to make it, I already spent a long time making the CLI commands so nice, so I added a few more for the GUI to use and then yeah thats how it works
  4. I made a UI for the typing test, and I do say this is an improvement over the CLI version and I do see how a GUI will positively benefit bliss.

Note the UI is very buggy and sometimes just desyncs with the CLI version and idk why so um yeah this update may take a while to get fully finished. Anyways, thanks again for all the support!

0
Zain Marshall

Zen++ Devlog VI

This was a pretty big update but I didn’t add anything that is syntaxically weird. I added functions, vectors, and strings.

What changed:

  1. Functions + Returns

    • Added parsing/eval support for fn name(args){...} and return expr.
    • Added scope
    • Added built-in functions like read() and print()
  2. Strings

    • Strings are defined with "string"
    • Can store/print/concatenate strings.
    • You can index into strings (s[i]) and use len(s).
  3. Vectors (Dynamic Arrays)

    • Added vector syntax: [1, 2, 3].
    • Added vector indexing: v[i].
    • Added built-ins:
      • len(v)
      • push(v, x)
      • pop(v)
    • Added vector concatenation
  4. Multidimensional vectors

    • Because vectors can contain vectors, nested structures like [[1,2],[3,4]] just work.
    • Nested indexing works (m[1][0]).
  5. Comments + Illegal Character Throwing

    • Added support for comments like // or /* ... */
    • Added stricter behavior for unknown/invalid characters so bad input doesn’t silently pass.
  6. Reorganization

    • src/ has source code
    • test/ has tests
    • build/ now contains the compiled binaries
    • docs/ contains docs/devlogs.
  7. Makefile + Testing

    • Added a Makefile with nice commands
    • make run launches REPL.
    • make run <file.zpp> runs a file directly.
    • Made test.zpp as a file with every command in the language and then wrote the expected output and made make test run the test script and compare output.

Changelog

Attachment
0
Zain Marshall

Zen++ Devlog V

Ok so in this devlog I spent a lot of time thinking about syntax and I would like some feedback about for loops.
First though, while loops were simple (not simple to implement these loops cooked me in coding but syntaxically simple), its just.

while boolean {
do this code here yeah
}

So while loops are very simple. Now for loops were a pain. I wanted them to be simple as this is meant to be super fast to write for competitive programming and the likes. So for this I took inspiration from my C++ template file.

#define FOR(i, a) for(int i = 0; i < a; i++)
#define ROF(i, a) for(int i = a; i >= 0; i--)
#define FORA(i, a, b) for(int i = a; i <= b; i++)
#define ROFA(i, a, b) for(int i = a; i >= b; i--)

That’s how I macro for loops during Codeforces contests. So instead of
for(int i=0;i<n;i++){...} I can just do FOR(i,n). Now I wanted something nice and simple for Zen++ to. So I landed on this:
A four loop has four components, the variable used, the start, the end, and the step. So why not instead of writing those as a declaration, a boolean, and an incrementation like in C++, just treat those almost as paramateres to a method. So thats what I did.
for i start end step {...}
Thats the syntax. If you want a reverse for loop you just make end bigger than start and step will be negative.
There is a 3-arg version which defaults step to 1 or -1 depending on direction and looks like: for i start end{...} and there is a 2-arg one which is: for i end{...} and defaults step to +1 and start to 0. So for codeforces you can just write for i n{...}. Very simple, but leave comments if you think its ugly. Its exclusive by default rn with no way to make it inclusive, I’ll fix that later.

Changelog

Attachment
Attachment
0
Zain Marshall

Zen++ Devlog IV

I added if else statments to the code! The way an if else-if else statment will be written is like tihs:

if bool1{
    x=1
}else if bool2{
    x=2
}else{
    x=3
}

Note the lack of parantehsis, you don’t rly need them beacuse you know your condition is just gonna be sandwiched between the if and the next curly brace. Also now that I added braces I made the parser handle the braces and the AST handle blocks of code.

What changed:

  1. The lexer recognizes if, else, { and }.
  2. The parser builds block nodes and full if/else chains, and parses the full program instead of a single statement.
  3. The evaluator now runs blocks and if/else nodes.
  4. The REPL buffers lines and runs the program when you submit a blank line.

Changelog

Attachment
0
Zain Marshall

Zen++ Devlog III

This step adds booleans and comparisons so I can start building if/else statements later. Booleans are just like they are in C++, a true boolean is a 1 and a false boolean is a 0.

What changed:

  1. The lexer now recognizes true/false and multi-character operators like ==, !=, <=, >=.
  2. The AST got boolean literals, comparison operators, and logical NOT.
  3. The parser now handles comparison expressions and prefix !, while keeping postfix ! for factorial.
  4. The evaluator now returns 0/1 for comparisons and supports logical NOT.

Changelog

Attachment
0
Zain Marshall

Zen++ Devlog II

I added variables and assignment. You can declare a variable like x=4 and reassign it like x=5

What changed:

  1. The lexer now recognizes identifiers and the = token
  2. The AST supports variable nodes and assignment nodes.
  3. The parser now uses a lookahead to treat identifier = expr as an assignment, and it also lets identifiers show up inside normal expressions.
  4. The evaluator keeps a small variable map so assignments store values and identifiers read them back.

Changelog

Attachment
0
Zain Marshall

Zen++ Devlog I

So I did a few things:

  1. I decided on the syntax of Zen++. Since I want to use it for like codeforces and stuff it should be very fast to type out while still being fast. So I decided on the syntax of the language. It will use curly braces to delineate blocks of code, no semicolons, for variables no let keyword and optional type so like x=1 for now. For loops and if statements no need for parentheses, just do while tc– or if bool. See idea.md for more.
  2. I decided it’ll be interpreted and I got started on basic math. So the way it works is you start with the statement in code, then a lexer tokenizes it (it identifies what is a parenthesis what is a plus sign, stuff like that), and then a parser takes the tokens and creates a hierarchy (so like pemdas) by making an Abstract Syntax Tree which we then evaluate by going to the bottom nodes, evaluating them and then propagating upwards. So very cool things. So far I just did basic binary arithmetic operations like + - * / % ^ and also a unary operator !. The code is made so its decently easy to add more tokens.

Changelog

Attachment
0
Zain Marshall

Ok so this devlog addresses the feedback given in my ship of this project. Also note:
When you’re demoing it, you have to type in the right url, youtube.com is not the full thing its www.youtube.com, but now the code should auto handle that but just in case.

Changelog

  • Added configurable browser close list (bliss config browser add/remove/list)
  • Browsers now close and automatically reopen on session start to reset connections
  • When adding a website (eg youtube.com auto add both youtube.com and www.youtube.com)
  • Added bliss repair to restart the root helper and clear stale state
  • Added config ownership auto‑repair via root helper
  • Fixed session “already running” mismatch between CLI and root helper
  • Added PF state drop for HTTP/HTTPS to reset active connections
  • Improved installer quickstart + added unsaved work warning
  • Updated README with new commands and warnings
Attachment
0
Zain Marshall

Ok so I haven’t worked on minimaxing properly in a while (over a month now). Anyways I still worked on it on and off for a few hours a week, so here is the devlog that summarizes all of those changes. Also this devlog was 3.7k chars over so i had to make it rly short now.

Ideas

First, I would like to link a few videos that I watched and got inspiration for this project from.

I have to give credit to these videos for helping me in building minimaxing.

Change 1: Users writing full scripts

  1. Users upload full python scripts that have a think method that takes in the board state as a python-chess object and returns a move in UCI format (a1b2 - starting square, final square).
  2. There is a token limit, right now 2000 tokens on all uploaded scripts using the tokenize method.

Change 2: Less bleak, sad, and depressing looking UI

I made the UI a lot more fun and playful, its a pastel color pallete now.

Change 3: Bots

This is a smaller change ig, but I spent a long time writing a good bot, cuz testing with the basic minimax with material advantage bot was getting boring so I wrote a good bot and now I can test the app with that.

A collection of minor changes

  • I added a makefile so you can run make run in the root and it will run the backend and frontend. I’m tryna add this to a bunch of my projects cuz its so clean and nice to use.
  • Added a docs page that somewhat tells the users what to do (more depth later)
  • Fixed the supabase backend which was broken for a bit

Anyways if you could comment on this post saying how you like the UI and what changes I should make that would be super helpful, thx.

Attachment
Attachment
Attachment
Attachment
0
Zain Marshall

Shipped this project!

Hours: 13.75
Cookies: 🍪 359
Multiplier: 26.08 cookies/hr

Hope you enjoy my project and find it useful!

Bliss

Bliss is a macOS focus lock that blocks websites and force‑closes blocked apps. It runs a background timer, shows a menubar countdown, and makes you solve a typing challenge to escape early. It is fully configurable, from the blocked apps and websites, to the length of the quotes in the typing challenge.

MACOS Only. To all Windows and Linux users of Flavortown, please watch the video demo in the GitHub readme or release notes!

What it does

  • Blocks websites via /etc/hosts + pf firewall table
  • Force‑closes blocked apps during a session
  • Runs a background timer (blissd) so the lock survives terminal close or reboot
  • Menubar timer (always‑on status)
  • Panic mode typing challenge

Quick start

  • Install using this command
curl -fsSL https://github.com/zainmarshall/bliss/releases/download/v0.1.0/bliss-macos-universal.zip -o /tmp/bliss.zip && \

 rm -rf /tmp/bliss && mkdir -p /tmp/bliss && \

 unzip -q /tmp/bliss.zip -d /tmp/bliss && \

 bash /tmp/bliss/bliss_release/scripts/install.sh
  • bliss config website add <domain>
    NOTE: Bliss comes with nothing configured by default, like no apps and websites blocked, so if you start it from the start it’ll block nothing and throw an error. Make sure you configure it.
  • bliss config app add (This will open a menu for you to select apps)
  • bliss start <minutes>

Commands

  • bliss start - Starts a timer for minutes
  • bliss panic - Escape a block early by completing a typing challenge.
  • bliss status - Status of the timer and pf table
  • bliss uninstall - Uninstalls everything. Must run with sudo. Requires a typing challenge.
  • bliss config website add/remove - Add or remove websites from block
  • bliss config website list - list blocked websites
  • bliss config app add/remove - Opens a menu to select apps to add / remove from the block
  • bliss config app list - list blocked apps
  • bliss config quotes short/medium/long/huge - Configure the length of quotes used in the typing challenges.

Devlogs

Learn more about how Bliss works by reading all the devlogs I wrote below!

Hope you guys enjoy!

Zain Marshall

Ok I said the last one would be the last, but there were so many bugs that I fixed. Error messages weren’t working, configs broken, but those all good now :)! Also I spent like 2 hours editing this video (idk why it took so long). This is the demo video to all windows and linux users who would be unable to install the app so they can still see how it would work and vote on it.

0
Zain Marshall

Ok, so I think this will be my final devlog for bliss, at least for the first ship. I have made a bunch of small polishing changes. Here is a list:

  1. Before if bliss was inactive but you ran bliss panic, it would make you solve the puzzle then say “never active”, now it says that before and doesn’t make you do a pointless challenge
  2. I added configurable quote lengths. I took 100 short, medium, long, and huge (what monkeytype calls thicc) quotes from monkey type, stored them in txt files, and then made it so you can type bliss configure quote and then change the length
  3. I made it so you can’t run config anything while bliss is active, so you can’t cheat and try to break out of it, you have to use bliss panic.
  4. Fixed a few errors.
Attachment
Attachment
0
Zain Marshall

I added a config menu for blocked apps. Unlike website where I could just make it a command, bliss config website add , for apps bliss needs the path to the .app, the bundle id, and the process name. Instead of forcing the user to type this out, I thought of a much better solution: all apps live in the Applications folder, so just list out all of those files and let then select which one, and that will give bliss the direct path from where it can get all the rest of the information itself. So the way I went about this first was by using fuzzy finder, fzf, and it would just start an fzf over your apps folder when you typed bliss config app add, and then when you select one it would do all the bliss things. This is nice as fzf is fast and keyboard based, but I want bliss to require as few external installs as possible, so I made a different menu if fzf is not installed, and I think that one works pretty well. I also like made the remove menu very similar but instead of on the apps folder, its on the config file. The no fzf command has a one time search feature than a numbered list which I showed off in the second screen recording.

Attachments

The first attached screen recording shows config app add and config app remove with fzf installed.
The second shows those two without fzf installed.

0
Zain Marshall
  1. I added blocking for desktop apps. It works on like proper apps, which is mostly everything, but for odd things like Minecraft which launches a java thing, which apple screen time is notoriously bad at catching, I have avoided for now.

Implementation

During a low, blissd wakes up every few seconds and checks the blocked apps list. For each app on it, it attempts to force quit the process that matches to the app’s path or process name. MAKE SURE YOU SAVE WORK BEFORE STARTING BLISS AS IT WILL FORCEFULLY SHUTDOWN.

Attachments

I have attached a simple screen recording of me trying to launch a blocked app. In this case the app I have blocked is Prism Launcher (a minecraft launcher).

0
Zain Marshall

I added an install script that installs the bliss cli, blissd, and the menu bar app, and blissroot. It is under scripts/install.sh. To go along with it, I wrote an uninstall script that uninstalls the menu-bar, removes the daemons, and deletes all the config and storage files. It also cleans up /etc/hosts and the pf. It is gated by the same typing puzzle as bliss panic. Also about the blissroot I talked about above, it just makes it so that you don’t have to type sudo each time. Bliss needs to edit protected files, so for start and panic, you used to need to use sudo, but now on install it gives itself a daemon making it so you don’t need to.

Attachment
0
Zain Marshall

Packet filter

I noticed in the blocker, if you already had the tab open, for example youtube, the browser would sometimes cache the ip and thus not need to query the DNS, thus bypassing the filter. So now bliss takes the domains, gets their ips, and then stores them so those ips are blocked on a network level using a packet filter table.

CLI Cleanup

Also, I cleaned up the CLI output and added bliss status. Status now shows remaining time and whether the firewall table is active. Sometimes in the code I had left placeholder output on certain commands, I removed that and made the error messages more helpful.

Attachments

The attached screenshots show bliss –help and bliss status.

Attachment
0
Zain Marshall

I added a real config system for websites. Instead of hardcoding YouTube, Bliss now stores domains in ~/.config/bliss/blocks.txt and the CLI supports add/remove/list. When Bliss starts, it reads this file and blocks everything inside it.
The attached screen shot shows those commands being used.

Attachment
0
Zain Marshall

##Bliss Panic Mode
I implemented what I call “panic” mode. Currently, if you start a block of some amount of minutes, ti will run for that time and it is impossible to exit. However, that can be unsafe or impractical, lets say you end to watch a youtube video for a class assignment or smth, or you just need to break out of the block, panic mode is the way. Instead of typing in a password or just clicking Unblock for 1 hour like it is in other blocks, you have to solve a puzzle. You have to do an activity that makes this feel a lot more painful and tedious, to incentivize you to not.

Future Steps

Right now its very simple, its a typing test where you need to get >=95% on a quote to pass. The quotes are pulled from a quotes.txt file. This is the test I will stick to now, but later I will switch to other puzzle types, maybe solving a leetcode problem. Also for testing purposes the quotes are short, cuz I’m too lazy to type long quotes, but I will prob make them longer on release.

Attachment

I have attached a screen recording showing the test after running bliss panic.

0
Zain Marshall

Formerly, the way bliss worked was just by starting and stopping it (well i hadn’t coded in a real stop, so just starting it) from the terminal, and the block would kinda be this thing in the background. It didn’t feel like it was a real app, and idk that didn’t sit well with me, and also there was no interceptor of how much time had passed. To solve this I added a very very simple menubar item. It says bliss and then it is a minute and seconds countdown. It stays running the background always, and is a launch item, so using LaunchAgent it stays running all the time and launches at computer reboot. So its there any time bliss is working. It will refresh and show the active timer ticking down on a bliss start command. The menu bar is written as a very simple swift application (one main.swift file) compiled to a binary.

I attached a screen recording showing me starting a timer and the menu bar timer ticking down.

0
Zain Marshall
  1. I implemented a background timer so the lock will actually stop after the time you specified when you run bliss start minutes and not just run indefinitely. The lock was already persistent on terminal closure and computer reseting seeing as how /etc/hosts works, but I had to figure out a way to make the timer persistent, so even if you turn off your computer and come back, if the end time is ended I need to make sure to unlock the block and revert the /etc/hosts. To achieve this I added a small daemon (very creatively named blissd) that runs in the background via launchd. When you start a timed lockout, its saved to a file, and blissd reads that file and automatically unblocks when the timer is done. As you can see in the attached screenshot, when running bliss status you can see the time remaining, and that is constantly updating with the daemon.
Attachment
0
Zain Marshall

I got the first block working, this blocks websites on any browser and is independent of the browser because what it does is filter DNS requests and not give certain websites access to the internet.

I have attached three screenshots. The first shows just what happens when you run bliss start and the second shows what it does to /etc/hosts. It modifies it such that all of the websites in the config (I haven’t implemented the config so right now its hard coded to youtube) will be added to /etc/hosts and be blocked from receiving internet. The third image just shows what happens when you try to visit the tab, no internet!

Attachment
Attachment
Attachment
0
Zain Marshall

I decided on the architecture of this project: you will primarily interact with it through a CLI and I will write it in C++ and build using CMake. I added some simple CLI fillers and a help menu with all the commands. The commands that I have so far coded in are start, panic, and config, which all just return a debug message for now. bliss –help will list all available commands.

Attachment
0
Zain Marshall

I fixed the downloading files from the writeups! I moved the folder from src/lib/assests to static. Such a small issue took my a while to debug :(

Attachment
0
Zain Marshall
  1. Updated the way the bots work and take rules to instead of using really long confusing eval statements you just write a method that returns an integer.
  2. Added a bunch of helper functions that are exposed to the bots, so that the users can add them to their rules. For example, my bots used to always stalemate, so there is a function that returns the number of repetitions so that you can add negative incentive for stalemates. Thats one example of a method I added.
  3. You can now see, edit, and delete the version history of bots.
  4. You can upload JSONs to upload bots and rules from files. You can also download old versions as JSON.

To Do:

  1. Add a new way to write bots, instead of just writing the evaluation function to a negamax algorithm, the users can write the full AI from scratch, they get the helper methods and board state as input, and need to output the next move in algebraic chess notation.
Attachment
Attachment
0
Zain Marshall

Added the ability to delete and edit bots.

Attachment
0
Zain Marshall

Thanks for the feedback! In response to it, I added the following things:

  1. Added a element to the website so the tab shows Zain’s Portfolio instead of the url
  2. The “View My Work” button now links to /projects instead of #projects. I forgot to change this from when it used to just autoscroll to when it switches tabs.
  3. Added a bit more to the README.md
  4. Added a header to the technologies section

To Do:

  1. Add images to all the projects
  2. Write more CTF write-ups
  3. Make a favicon
Attachment
Attachment
Attachment
Attachment
0
Zain Marshall

Shipped this project!

Hours: 6.5
Cookies: 🍪 32
Multiplier: 4.88 cookies/hr

This is my portfolio website! I made some cool animations and pretty pages. I have pushed making this off for too long. I’ll probably update it throughout time as I improve my skills, but I learned a lot about frontend development.

Zain Marshall

I improved the visuals of the project section, moved it to its own tab, and changed the way the project cards look. They are now much wider, and horizontally laid out. They each display the title, an image, a description, and the technologies used using the same cool hover effect as they do on the home screen. I also made it so that I can quickly add new projects by just adding objects to an array in a typescript file rather than messing with the svelte files.

Attachment
Attachment
0
Zain Marshall

I added a lot to both the backend and the frontend. The backend works fully with supabase and all of the data tables are set up. There is also user authentication through email, and there should be through GitHub but thats still broken. Then after the backend as done I tested it and it worked, so I mocked up a rough frontend for creating bots, editing them and their rules and evaluations, and then for playing bots against each other. Right now its only your bots, but later I’ll add the multiplayer aspects.

Attachment
Attachment
Attachment
0
Zain Marshall

Switched to negamax as its computationally more efficent than minimax. Implemented the backend and supabase to handle the rules, the evaluation, the match making. Now to work on the frontend! The backend is a very rough draft, it’ll be improved with time.

Attachment
1

Comments

zliskovyi
zliskovyi 3 months ago

holy tuff aura blud

Zain Marshall

Architected most of the project, got the plan done.

Frontend - Sveltekit
Backend - FastAPI

I started coding a bit of the backend like the minimax algorithm

Also I’m brainstorming security measures cuz if ppl are uploading their own code that is very dangerous.

Attachment
0
Zain Marshall

I worked on the CTF writeup section of my project, I also wrote a demo for a chall I did a while ago. There is a cool obfuscated text animation and a system to take in markdown files and render them as html. Also made the code better.

0
Zain Marshall

Added a section to display the technologies I know, use, and love. Has a cool hover affect that displays the tech logo in full color and adds a glow to the border in the accent color. Used devicon for the icons.

Attachment
0
Zain Marshall

Just started the project, got a few things working. So far we have the basic layout of the website, tabs, a section of CTF writeup that renders markdown files, a project section that hasn’t been filled in, and a sick loading animation.

Attachment
0