Merge branch 'main' into large-storage-custom-nas

This commit is contained in:
engineershamrock
2024-07-03 19:18:38 +01:00
committed by GitHub
73 changed files with 1073 additions and 61 deletions

5
.github/CODEOWNERS vendored
View File

@@ -2,4 +2,7 @@
* @leigh-hackspace/infra
# Website content is managed by the Web Editors team
content/* @leigh-hackspace/web-editors
/content/ @leigh-hackspace/web-editors
# Membership data is managed by the directors
/data/memberships.yaml @leigh-hackspace/directors

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -31,7 +31,7 @@ jobs:
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.122.0
HUGO_VERSION: 0.124.1
steps:
- name: Install Hugo CLI
run: |
@@ -46,7 +46,7 @@ jobs:
fetch-depth: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v4
uses: actions/configure-pages@v5
- name: Install Node.js dependencies
run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
- name: Build with Hugo

View File

@@ -1,5 +1,5 @@
# Run tests on the website build
name: Test
name: Test - Run a test build
on:
push:
@@ -17,7 +17,7 @@ jobs:
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.122.0
HUGO_VERSION: 0.124.1
steps:
- name: Install Hugo CLI
run: |

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
public
resources
.hugo_build.lock
.DS_Store

11
.vscode/tasks.json vendored
View File

@@ -2,11 +2,12 @@
"version": "2.0.0",
"tasks": [
{
"type": "hugo",
"task": "server draft",
"group": "build",
"problemMatcher": [],
"label": "hugo: Serve draft site"
"label": "Test Site Locally",
"command": "make",
"args": [
"serve"
],
"problemMatcher": []
}
]
}

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Leigh Hackspace
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,21 +1,23 @@
# Leigh Hackspace Website - Hugo Edition
Hugo version: 0.122
Hugo version: 0.124.1
## Dev Mode
## Contributing
To run the site locally you can do the following:
Looking for something to contribute to the website? Check out the ["Good First Issues"](https://github.com/leigh-hackspace/website-hugo/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) tag in the Issues section for tasks that are simple, but need doing.
All changes to the website must be done on a branch and pushed through the GitHub pull requests workflow. If you have any questions about this process then contact the [Tech Infrastructure](https://wiki.leighhack.org/membership/useful_contacts/#tech-infrastructure) people.
### Build the site locally
To build the site locally you can do the following:
* Download [Hugo extended edition](https://github.com/gohugoio/hugo/releases/) (named hugo_extended).
* Check out repo
* Check out repo (`git clone https://github.com/leigh-hackspace/website-hugo`)
* Run `hugo serve -D --gc -w -F` (add -F to show content with future dates) or `make serve` (if you have `make` installed)
* Go to `http://localhost:1313/` to view the local instance.
The site will be updated in real time with any changes made to the site.
## Making Changes
All changes to the website must be done on a branch and pushed through the GitHub pull requests workflow. If you have any questions about this process then contact the [Tech Infrastructure](https://wiki.leighhack.org/membership/useful_contacts/#tech-infrastructure) people.
The site will be updated in real-time with any changes made to the site files.
## Deployment
@@ -23,18 +25,62 @@ Branches are automatically deployed to [https://web-test.leighhack.org](https://
## Common Tasks
### New Blog Post
### How do I add images to posts / What custom shortcodes are available?
* Download and install Hugo
* Run `hugo new blog/<year>/name-of-post/index.md`, and a new file will be created in the right folder.
We have a few shortcodes that you can use:
#### `image`
`image` adds a image and manages the sizing and formatting.
```
{{< image src="netatalk.png" width="400x" class="is-pulled-right" title="The Netatalk logo.">}}
```
* `src` - The name of the image file, this can be a PNG, JPEG, or WEBP, the path is relevant to the file you're adding it into.
* `class` - Is a CSS class that'll be applied to the `figure` created to show this image, common ones are `is-pulled-left` and `is-pulled-right`, more can be found in the [Bulma helpers](https://bulma.io/documentation/helpers).
* `title` - This is the title and alt text used for the image.
* `width` - The maximum dimensions of the image, this can be used in a few ways, either defining just the width (`400`), defining scaling to a width `400x`, or a specific width and height (`400x600`). Ideally try to use `400x` to keep image scaling working as expected.
#### `gallery`
`gallery` surrounds a group of image tags and makes a rotating gallery of the images:
```
{{< gallery >}}
{{< image src="network-browser.jpg" title="Mac OS 9.2.2 'Network Browser' showing the 'nas-afp' service available via AFP over AppleTalk.">}}
{{< image src="osx-finder.png" title="Mac OS X 10.4 Finder showing the 'nas-afp' service available via AFP over TCP/IP.">}}
{{< image src="sonoma-finder.png" title="macOS Sonoma Finder showing the 'nas-afp' service available via AFP over TCP/IP.">}}
{{< /gallery >}}
```
#### `rawhtml`
`rawhtml` can be used to inject HTML from your Markdown post into the finished page. **It is really not advised to do this, the retro theme will ignore any HTML in these tags**.
For example, this is used on the map page to inject the `div` required to render to OpenLayers map:
```
{{< rawhtml >}}
<div id="map" class="map"></div>
{{</ rawhtml >}}
```
### How to create a new blog post
* Download and install [Hugo](https://github.com/gohugoio/hugo/releases/) (the extended edition)
* Run `hugo new blog/<year>/name-of-post`, and a new folder will be created in the year folder with a `index.md` with the post.
* Update the `author` and `author_email` values
* Add a `subtitle`
* If you've posted the blog elsewhere, add the `original_url` value to link to your original post URL.
* Place any images in the folder that was created for your post.
* Set `listing_image` to the image you'll want on the blog listing page ([https://www.leighhack.org/blog/](https://www.leighhack.org/blog/))
* Run Dev Mode (above), or `make serve` and view your post.
### Updating Membership Plans
### How to update the membership plans
The membership plan data is held in a YAML file, this is used by the Hackspace API and other tools as well.
* Edit [data/memberships.yaml](data/memberships.yaml), follow the format of existing entries.
* Edit [data/memberships.yaml](data/memberships.yaml), following the format of existing entries.
* Links are standard URIs and can support any of the normal formats (mailto:, etc).

View File

@@ -1,6 +1,7 @@
var events = [];
$(document).ready(function () {
$('div#calendar p#nojs').hide(); // Hide the NoJS message
$.getJSON('https://api.leighhack.org/events', function (data) {
data.forEach(function (event) {
events.push({

View File

@@ -19,6 +19,7 @@ $(document).ready(function () {
} else {
$('span#hackspace-status').html('<b>Closed</b>');
}
$('div#hackspace-open').fadeIn('slow');
}
// 'printers' shortcode

View File

@@ -69,6 +69,12 @@ name = "Events"
pageRef = "events"
weight = 6
[[menu.main]]
name = "Donate"
pageRef = "Donate"
URL = "https://www.paypal.com/donate/?hosted_button_id=G9AJ2HR3SDQ3J"
weight = 7
[[menu.policies]]
name = "Code of Conduct"
pageRef = "policies/code_of_conduct"

View File

@@ -2,19 +2,21 @@
title: Welcome!
subtitle: Leigh Hackspace is a social enterprise created for the benefit of our members and the wider Leigh community.
layout: home
hero_image: rose_logo.svg
hero_image: long_logo_solo_whitebg.svg
---
{{< eventbrite >}}
{{< openstatus >}}
| Day | Opening Times |
| --------- | ------------- |
| Monday | Closed |
| Tuesday | 14:00 - 20:00 |
| Wednesday | 14:00 - 20:00 |
| Monday | 18:30 - 21:00 |
| Tuesday | 14:00 - 21:00 |
| Wednesday | 14:00 - 21:00 |
| Thursday | Closed |
| Friday | Closed |
| Saturday | 12:00 - 17:00 |
| Sunday | Closed |
We currently operate reduced opening hours due to member availability. The hackspace can be open outside of these hours and a banner above will appear when it is open, otherwise please check on [Slack](https://join.slack.com/t/leighhack/shared_invite/enQtNDYzMjEyMDMxNDExLTE1MWY5N2IwMzdhMzQ0ZWFiNDkyNzJmMGM1ZmFkODcwMGM5ODFmYmI4MjhmM2JiMWEyY2E3NTRjMTQzMzljZWU).
We currently operate reduced opening hours due to member availability. The hackspace can be open outside of these hours and a banner above will appear when it is open, otherwise please check on [Slack](https://join.slack.com/t/leighhack/shared_invite/enQtNDYzMjEyMDMxNDExLTE1MWY5N2IwMzdhMzQ0ZWFiNDkyNzJmMGM1ZmFkODcwMGM5ODFmYmI4MjhmM2JiMWEyY2E3NTRjMTQzMzljZWU).

View File

@@ -11,6 +11,7 @@ tags:
author: Andrew Williams
author_email: andy@tensixtyone.com
listing_image: camera.png
original_url: https://nikdoof.com/posts/2023/old-webcam-on-modern-linux/
---
{{< image src="camera.png" width="400x" class="is-pulled-right" title="The Trust WB-1200P, a webcam from the early days of USB devices.">}}

View File

@@ -11,6 +11,7 @@ draft: false
author: Andrew Williams
author_email: andy@tensixtyone.com
listing_image: open.jpg
original_url: https://nikdoof.com/posts/2023/powerbook-g4-disk-replacement/
---
In October 2003, I made my first leap into using an Apple device. For quite some time I'd been trying to find a reasonable and portable machine for daily use, and I had slowly gotten frustrated with the current offerings by Dell, HP, and other major laptop manufacturers. In the hunt for something new, I picked a Powerbook G4 12". This machine was my daily workhorse for several years and at the end of its life, it was stuffed into a draw and forgotten about. Sometime around 2014 when I was purchasing a new Macbook Pro I decided to grab my old laptop out of storage and get it booted to hopefully pull a few files from the system. I had lost the power adapter and (obviously) the battery had given up. I purchased a new power adapter on eBay and ended up throwing everything back in the drawer to sort out another day.

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 KiB

View File

@@ -0,0 +1,147 @@
---
title: "Can You Make It Bigger? - A Journey In Building Arcade Cabinets"
subtitle: ""
date: 2024-06-23T07:40:38Z
tags:
- CNC
- Electronics
- Raspberry Pi
draft: false
author: Kian Ryan
author_email: kian@orangetentacle.co.uk
listing_image: images/final_cabinet_full.jpg
---
__This one started out as an idea.__
Dan Hardiker from [Devoxx UK](https://www.devoxx.co.uk/) contacted me with an idea:
> _"We want to make a bunch of games with our sponsors, and play them on a bunch of small arcade cabinets. But we also want to
> take the cabinets to a some other events."_
I like small, well defined projects, and this one fitted the bill. We can do this.
_Small, well defined projects._
Okay. So first thoughts immediately went to the [Picade](https://shop.pimoroni.com/products/picade). The Picade is a small arcade cabinet
from [Pimoroni](https://shop.pimoroni.com/). It's great, I have one.
It lives upstairs in my second bedroom, and when I need a bit of quiet time, I use it to play Frogger. I'm a Frogger demon.
But while it's quite small, it's not easy to store. It's arcade cabinet shaped, and doesn't pack or stack well.
What if we could build an arcade laptop? Something that could be folded down between events and stored away easily?
{{< clearfix >}}
{{<image src="images/note-01.png" title="Notebook Sketch 1 - Picade and folding model" width="300x" class="is-pulled-left">}}
{{<image src="images/note-02.png" title="Notebook Sketch 2 - Console and folding case" width="300x" class="is-pulled-left">}}
{{<image src="images/fusion_design_1.jpg" title="Fusion 360 - Initial working concept for folding case" width="300x" class="is-pulled-left">}}
{{< clearfix >}}
When I start a project, I sketch, rather than go straight to CAD. I like to have ideas on paper, or more recently,
on digital paper, before I start opening up a CAD program. It won't be perfect, but I'll have some idea of the shape
of the thing before I start working through something I plan on making. CAD software can occassionally be unforgiving,
and it likes to have a plan of what you want to build. You can vary that plan - but having at least part of that plan up
front helps.
We start with a "Picade in a case". 10" screen, Raspberry Pi 4, and an arcade console with a removable stick to allow the case
to be closed. Technically it works, and I take it to the team. It fills the portable part, but doesn't look "Arcade-y" enough.
Fair. Can we make it look more like an arcade cabinet.
{{< clearfix >}}
{{<image src="images/note-03.png" title="Notebook Sketch 1 - Picade and folding model" width="400x" class="is-pulled-left">}}
{{<image src="images/note-04.png" title="Notebook Sketch 2 - Console and folding case" width="400x" class="is-pulled-left">}}
{{< clearfix >}}
This conversation goes forwards and backwards for a few iterations where we play with bartop designs, etc until we hit
what they _really_ want.
> "You want full size arcade cabinets, don't you?"
So how do we deliver full size arcade cabinets, that are still ultimately, _portable_ and _storable_.
The answer is you do it in parts. The idea of "all the bits in the case" still works, somewhere for all the electronics to live. Monitor,
Raspberry Pi and controls. Then we build a separate cabinet for the case to slot in to. Because our CNC bed is 80cm square,
the cabinet is split in 2, giving a total height of 1.6m. Added benefit - if you want a bartop cabinet for some events, you just use
the top half. The cabinet slots together like flat pack furniture, using slots and furniture bolts for assembly. At the
end of the event, remove the bolts, flatten the case and store between events.
Once we were happy with the general idea, we designed the prototype in Fusion 360, and cut the prototype on our Shapeoko XXL.
The electronics case is cut from 9mm MDF and the cabinet from 18mm MDF. The console and display frame are cut from 5mm acrylic.
Assembly of the electronics case is done with glue, with the console and surround mounted using M3 bolts and self tapping inserts.
{{< clearfix >}}
{{<image src="images/fusion_design_2.jpg" title="Fusion 360 Design - Arcade Cabinet Final" width="300x" class="is-pulled-left">}}
{{<image src="images/cutting_cases.jpg" title="Cutting a side panel on the Shapeoko XXL" width="300x" class="is-pulled-left">}}
{{<image src="images/prototype_case.jpg" title="Testing the prototype - Cat for scale" width="300x" class="is-pulled-left">}}
{{< clearfix >}}
[An archive of the Fusion 360 project is available on Github.](https://github.com/leigh-hackspace/arcade-cabinet)
To kit the electronics, we used an off the shelf monitor - a Cooler Master GA241, a Raspberry Pi 4
running RetroArch, an Sanwa JLF arcade stick modified with a Link EX Groove Quick Release and 10 buttons. The GA241 monitor is powered
by 12V, which allows us to nicely split a single 12V/4A power supply for monitor and Pi (using a buck converter).
> Note on suppliers: We used Arcade World UK for a large amount of this build, but they appear to have disappeared. Since
> the original build, we've been using [Arcade Express](https://www.arcadexpress.com), a Spanish Company. Import charges
> may apply when using them.
{{< clearfix >}}
{{<image src="images/wiring_loom.jpg" title="Wiring up the power for the test case" width="400x" class="is-pulled-left">}}
{{<image src="images/wiring_up_case.jpg" title="Testing a nearly finished electronics case" width="400x" class="is-pulled-left">}}
{{< clearfix >}}
The Devoxx UK games were built using [PyGame](https://www.pygame.org/) - [Dan Hardiker](https://twitter.com/dhardiker) came down the weekend before the
event and spent time getting the games working on the machines. There's nothing like a deadline. Running right up
against it, we painted the cabinets black and drove them down for setup at the Business Design Centre in London.
{{< clearfix >}}
{{<image src="images/primed_cases.jpg" title="Priming upper cabinets for painting" width="300x" class="is-pulled-left">}}
{{<image src="images/case_production_line.jpg" title="Lining up finished cases for wiring" width="300x" class="is-pulled-left">}}
{{<image src="images/loading_cabinets.jpg" title="Loading up flattened cabinets ready for transport" width="300x" class="is-pulled-left">}}
{{< clearfix >}}
They were received well, and performed great for the duration of the event. Dan and the crew then did exactly what the
cabinets were designed to do - they removed the electronic cases, removed the bolts, dropped the cabinets flat and packed
them for the next event.
{{< clearfix >}}
{{<image src="images/cabinets_lined_up.jpg" title="Arcade cabinets assembled" width="400x" class="is-pulled-left">}}
{{<image src="images/cabinets_played.jpg" title="Arcade cabinets being played" width="400x" class="is-pulled-left">}}
{{< clearfix >}}
But we're not quite done. The event had gone well, but our prototype was still looking ... well, like a prototype. And
a Hackspace without an Arcade Cabinet isn't really a Hackspace. So we recut the side panels to the same profile as the Devoxx cabinets,
gave ours a lick of paint, and using a Player-X board, some more components and a trackball, added some extra rizz for two player action and more game modes.
{{< clearfix >}}
{{<image src="images/final_cabinet_full.jpg" title="Our final cabinet - full length shot" width="400x" class="is-pulled-left">}}
{{<image src="images/final_cabinet_console.jpg" title="Up close shot of two player console and trackball" width="400x" class="is-pulled-left">}}
{{< clearfix >}}
It's already been to [Elecromagnetic Field](https://www.emfcamp.org/), where it was used to run [Pico-8](https://www.lexaloffle.com/pico-8.php) games from [Johan Peitz](https://johanpeitz.itch.io/) in the Family Tent, and it'll be making an appearance at the
[International Discworld Convention](https://dwcon.org/) in August, playing the original Discworld point and click games using [ScummVM](https://www.scummvm.org/).
If you drop by the [Hackspace](/index.md), you're more than welcome to play on it.
Leigh Hackspace is open to commissions, and we're also keen on teaching people the skills to make for themselves.
Our [Summer of Making]({{< ref "/blog/2024/summer-of-making/index.md" >}}), has a range of skills that can help get you started, or if
you have a project in mind, please [come and talk to us](mailto:directors@leighhack.org).

View File

@@ -10,6 +10,7 @@ draft: false
author: Andrew Williams
author_email: andy@tensixtyone.com
listing_image: network-browser.jpg
original_url: https://nikdoof.com/posts/2024/creating-an-appletalk-nas/
---
{{< image src="netatalk.png" width="400x" class="is-pulled-right" title="The Netatalk logo.">}}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 KiB

View File

@@ -0,0 +1,188 @@
---
title: "The Hackbots Project II"
subtitle: "Making Simple Robots That Anyone Can Build (Pt. 2)"
date: 2024-03-18T07:40:38Z
tags:
- Rasberry Pi Pico
- Robots
- Electronics
draft: false
author: Paul Williams
author_email: phyushin@gmail.com
listing_image: images/hackbot.jpg
---
## Continuing the Bot Building Process
So, we'll continue from where we left on last a little while ago with our bot building blog [posts][1].
We'd got to the MK IV if memory serves... Next on the list of things to do is to make our bot interface page nice and pretty.
## Enter, CSS
Because we're using a very simple webserver on the [Raspbery Pi Pico W][2] and because the code handily returned from our `generateHTML()` function is effectively the page that's served by the websever; we know this is a good place to add a little customisation for our robot - make our page a little _prettier_.
## CodePen
When prototyping, it's always much more satisfying to see the changes happen quickly, as opposed to editing our `generateHTML()` function, uploading to the bot, connecting to our bot, visiting the url... it's a lot of steps - so, to make this a bit easier we're going to use a nice tool called [CodePen][3], our first step is to rip out the HTML from the `generateHTML()` function and paste it into the HTML window, like so:
{{< image src="images/codepen_screenshot.png" title="HTML & CSS editor windows above, results below">}}
The result of the code is shown underneath the HTML and CSS editor windows, We've made a couple of modifications from our original `generateHTML()` function to make it easier to work with CSS:
```python
html = f"""
<!--Snip-->
<style>{style}</style>
<!--Snip-->"""
return html
```
The above code is snipped to keep things simple, but what it does is use python's [_string format_][5] functionality to add the variable `style` with the the style we read into the variable from the `style.css` file (more on that a little later).
We've also moved `generateHTML()` into its own file (`html.py`) and used parameters to drop in from the main program; we import the function into `main.py` by adding the following code to the top of our `main.py`:
```python
from html import generateHTML
```
This allows us to call `generateHTML()` like we did previously, it's just tidied away in its own file now... We've also added the following code to the beginning of the function - which will allow us to use an _exteral_ style sheet (see I told you more on that later):
```python
style = ""
with open("./style.css","r") as f:
style = f.read()
```
Now, once we're done with making the code look _pretty_ in CodePen we can just drop the code from the _CSS_ window into the `style.css` file and it will make the controller page all nice and pretty too! Great Stuff!
## Paletton
A good place to grab some colours that go well together is [Paletton][3], For the purposes of this guide however we're only going to pick a primary colour but don't let that stop you from adding a little extra _flare_, pick a colour you like the look of like so:
{{< image src="images/paletton1.png" title="Paletton Colour Picker">}}
Then, once you're happy with your colourcscheme - go to the export and select _as CSS_:
{{< image src="images/export_as_css.png" title="Export - listing colours that go well together">}}
Don't worry if the export doesn't work, as all the relevant colour information (Hex values) can be grabbed right off this page too!
You should end up with something like this in your `style.css` file:
```css
:root{
--color-primary-0 : #679933 ;
--color-primary-1 : #C0E699 ;
--color-primary-2 : #90BF60 ;
--color-primary-3 : #437313 ;
--color-primary-4 : #274D00 ;
--color-white : #ffffff ;
--color-black : #000000 ;
}
button {
width:175px;
height:100px;
background-color: var(--color-primary-0);
color: var(--color-white);
font-size:25pt
}
```
Where the `:root` _selector_ contains the variable namnes used for the colours - you don't have to do it exactly like this but it's done here for clarity.
## The generateHTML() function
Once you're finished, you should end up with something like this in your `generateHTML()` function:
```python
def generateHTML():
style = ""
with open("./style.css","r") as f:
style = f.read()
html = f"""<!DOCTYPE html>
<html>
<head>
<title>Hackspace Bot</title>
<style>
{style}
</style>
</head>
<body>
<div>
<form action="" method="post">
<table class="controller">
<tr>
<td></td>
<td>
<button type="submit" formaction="forwards">&#8593</button>
</td>
<td></td>
</tr>
<tr>
<td><button type="submit" formaction="left">&#8592</button></td>
<td>
<button type="submit" formaction="stop">Stop</button>
</td>
<td>
<button type="submit" formaction="right">&#8594</button>
</td>
</tr>
<tr>
<td></td>
<td>
<button type="submit" formaction="backwards" >&#8595</button>
</td>
<td></td>
</tr>
</table>
</div>
"""
# this bit is for debugging we can remove in finished branch
html = html + f"""
<div>
<table>
<tr>
<td>SSID</td>
<td>PASSWORD</td>
<td>IP</td>
</tr>
<tr>
<td>{ssid}</td>
<td>{password}</td>
<td>{ap.ifconfig()}</td>
</tr>
</table>
</div>
</form>
</body>
</html>
"""
return html
```
_Note: we already have the external stylesheet file `stlye.css` generated_ which the code opens and reads the contents into the `style` variable, this, in turn is replaced using python's _format string_ functionality we talked about earlier. We write the code in this way as it allows us to easily change the _style_ of our buttons simply by replacing the colours in the `style.css`
## Finally, secrets.py
The `secrets.py` file is where we, well... store our secrets - sounds pretty obvious right?
The benefit of doing it this way is that we only need to make changes to the one file and they'll be reflected everywhere, which is a common theme in programming sometimes referred to as the [DRY Principle][6].
Our `secrets.py` should look something like this:
```python
secrets = {
'ssid': 'Hackbots_Demo',
'pw': 'Really_Insecure_Password!',
}
```
That's it just a simple [python dictionary][7] in a file! The beauty of this approach is that we can import this file (much like we did with the `html.py`) and access the settings easily, a brief example is shown below:
```python
from secrets import secrets # This imports the `secrets.py` code as `secrets` into the current file
### We can then read the values into variables
### using the 'key' from the dictionary like so:
ssid = secrets['ssid']
password = secrets['pw']
```
Using this approach allows us to make changes to the configuration easily simply by changing the values in the dictionary and saving it to the device. which will help later on!
Once we've saved our configuration and other files, pushed them to the [Pico W][2] we can visit the url (by default it's `http://192.168.4.1`) and we'll see the page we designed earlier all nice and pretty!
Thanks for reading! - Stay tuned for part 3 where we'll go through the wiring up and building of the bot.
PW
[1]: https://www.leighhack.org/blog/2024/the-hackbots-project/ "Original Hackbot Adventures"
[2]: https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html "Raspberry Pi Pico"
[3]: https://codepen.io/pen/ "CodePen"
[4]: https://paletton.com/ "Paletton"
[5]: https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals "Format Strings"
[6]: https://en.wikipedia.org/wiki/Don't_repeat_yourself "DRY programming"
[7]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries "Python Dictionary"

View File

@@ -39,6 +39,7 @@ If you open the large cover you find it has a location for 3 1/2 45 disks, see t
{{< bimage src="images/IMG_2994.jpg" width="500" height="400" zone="60">}}
The drives sit in the grid and the vibration of the disks spinning is dampened by some rubber bands, you can see a couple in the picture.
The drives are hot swappable and plug directly into a PCB, of which there are 9, each controlling 5 drives. The controller cards are actually just SATA port expanders, and in comparison to many port expanders work relatively well.
@@ -85,6 +86,7 @@ We also have 3 of these
{{< bimage src="images/IMG_3009.jpg" width="400" height="300" zone="30">}}
Nothing amazing, but simple 4 port SATA controllers.
# Comparing drive sizes
@@ -100,6 +102,7 @@ I created a 3d printed flat platform that the drives could stand on, just to tes
{{< bimage src="images/IMG_2497.jpg" width="400" height="300" zone="30">}}
# Cabling
At this point I realized the cabling would not fit under the platform, so any new location for the drives would either need to be custom with driver chip (like the previous items) or just connectors with drivers elsewhere, but also with the SSDs being smaller (hence shorter) there is now more room to move things upwards, as it turns out about 35mms of room. I then 3d printed a mask, that would allow me to use the nylong screws into the positions in the chassis but also allow me to add additional holes for anything I wanted to attach, so removing the need to match holes but allow me to extend upwards
@@ -120,6 +123,7 @@ As it turns they are little rubbish. Not because they do not work, or that they
{{< bimage src="images/IMG_3012.jpg" width="400" height="300" zone="30">}}
Then if you put it back with heat transfer epoxy, it will stop restarting, but remains incredibly slow!
# Drive Connectors
@@ -139,6 +143,7 @@ So in my wisdom I thought I could fit more connectors on the PCB, so I went for
{{< bimage src="images/IMG_2752.jpg" width="400" height="300" zone="30">}}
So a completed PCB, it is a very simple design, two locations to power the drives and then pass through connectors for SATA
{{< bgallery width="60" >}}
@@ -153,6 +158,7 @@ It looks pretty, and did work, 20 drives and a boot drive, so 21 drives.
{{< bimage src="images/IMG_2762 (1).jpg" width="400" height="300" zone="30">}}
At this point, which was quite a bit of work, I realized with much distress, it was slower than a snail, at one point I was getting an underwhelming 10Mb/s !!!
# The current status
@@ -186,6 +192,7 @@ To make the best use out of it you also need to expand the number of ports avail
{{< bimage src="images/s-l1600 (2).jpg" width="400" height="300" zone="30">}}
It is an Intel RES2SV240 RAID card. It is not really a RAID card in this case, but provides 24 ports, of which 4 are inbound and 20 outbound. This card is relatvely good as you can then use SFF8087 cables to SATA ports, keeping the cabling manageable, rather than individual SATA cables
So let's do the maths
@@ -199,6 +206,7 @@ Even better the RES240 cards do not actually need to plug into the motherboard,
{{< bimage src="images/s-l1600 (2).jpg" width="400" height="300" zone="30">}}
This is an amazing win so I started the build out as follows
{{< bgallery width="80" >}}
@@ -211,6 +219,7 @@ Add some drive location testing
{{< bimage src="images/IMG_2883.jpg" width="400" height="300" zone="30">}}
It is brilliant what could go wrong!
As it turns out ... there is always something!
@@ -237,6 +246,7 @@ I am now going to do this
{{< bimage src="images/IMG_2905.jpg" width="400" height="300" zone="30">}}
Instead of using the 9 locations for drives I am going for 6. The last 3 I can use for the RES240 cards and allow some space for cabling, air flow and as it turns out some boot space as well.
In this picture you can see 84 drives, but I did mention 72, where did the other 12 come from ? Remember the 3 original controller cards, as it turns out they fit into the remaining PCI slots.
@@ -247,6 +257,7 @@ We now end up with this
{{< bimage src="images/IMG_2906.jpg" width="400" height="300" zone="30">}}
To show that it all works under Linux
It does take about 4 minutes to boot though!
@@ -542,4 +553,4 @@ Interesting things to note - the read IOPS was 21k and the write IOPS was 5k, th
I need to add in the power pictures and some other things etc

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

View File

@@ -0,0 +1,75 @@
---
title: "Making Stage Props for the Lottery Winners"
subtitle: ""
date: 2024-06-23T07:40:38Z
tags:
- CNC
- Electronics
- Pi Pico
draft: false
author: Kian Ryan
author_email: kian@orangetentacle.co.uk
listing_image: images/on_stage.jpg
---
Before Christmas, a group of musicians walked in to the space to talk about designing stage props for their upcoming UK tour.
Up front I'm going to be honest, I had briefly heard of the [Lottery Winners](https://www.thelotterywinners.co.uk/) but
had no sense of how big the band had become. [The Lottery Winners](https://en.wikipedia.org/wiki/The_Lottery_Winners) are a local band made good, with a Number 1 album -
[Anxiety Replacement Therapy](https://en.wikipedia.org/wiki/Anxiety_Replacement_Therapy), and had performed last year at Glastonbury. They're kind of a big deal. They asked if we
could make some stage props for them, giant daisies to be lit with stage lights for their Manchester O2 Apollo gig.
We had been doing work with the CNC recently and I've made a few pieces for stage previously so agreed to draft up some ideas.
While the band focused on their tour, we worked on designing the props, working with their lighting designer to come up
with a design compatible with the lights that would be used on stage.
{{< image src="images/fusion_1.jpg" title="Model design in Fusion 360" width="400x" class="is-pulled-left" >}}
{{< image src="images/test_fit.jpg" title="Test fit on head and lighting stand" width="400x" class="is-pulled-right" >}}
Using Fusion 360, we designed a model to be cut on our Shapeoko XXL, and performed some test cuts on 5mm acrylic.
The outer shape was cut from 5mm opaque white
and the inner shape from 3mm opaque yellow. They were bonded using Tensol 70. Using some generic angle brackets, we
tested the fit on the sample spot head and adjusted the design a bit, the band were happy with the design.
{{< clearfix >}}
{{< youtube UqzpV7Pt8ho >}}
Then the band asked if we could design a portable lighting pack to use on their other tour dates.
We needed a one-size fits all solution. The same daisies would need to be used for all tour dates, so we needed a system
that would allow for switching between the portable packs, and the standing lamps. We agreed to use the same mounting
hardware - a lighting stand and angle bracket, and switch out the lighting for a portable USB powered LED system. We also
needed a system that could be easily charged on tour - regular LiPo battery packs USB charging were ideal, and could be
replaced on tour if needed.
{{< image src="images/light_pack.jpg" title="Lighting Pack Light Ring and Mount" width="400x" class="is-pulled-left" >}}
We used a [Plasma 2040 board from Pimoroni](https://shop.pimoroni.com/products/plasma-2040?variant=39410354847827) combined with [these WS2812B RGB rings from Cool Components](https://coolcomponents.co.uk/products/241-led-172mm-complete-ring-ws2812b-5050-rgb-led-with-integrated-drivers-adafruit-neopixel-compatible). We couldn't use all the rings, nor could we power all the LEDs at the same time, so with a bit of careful maths, we worked
out how many LEDs we could drive from the Plasma and the power supply. 3D printed housings in PETG were attached with magnets
to the back of a select number of the daisies, allowing the lighting packs to be attached and removed.
Some simple Micropython allowed us to to design a few different lighting patterns controllable from the onboard buttons
of the Plasma 2040. I'm quite pleased with the results.
{{< clearfix >}}
{{< youtube EGnIsF4EzsA >}}
For final stage dressing, and to hide cabling, we made green wrap sleeves sleeves for the lighting stands with hook and loop
closings and an over the top loop to hang from the top of the stand.
These were shipped in two batches, first batch to the band on tour, and then a final delivery to the band at the
O2 Apollo Manchester. They very kindly offered us tickets to come and watch, and we made an evening to see the props and the band,
on stage.
{{< clearfix >}}
{{< image src="images/on_stage.jpg" title="Lottery Winners and Daisies on Stage in Manchester" class="middle" >}}
Leigh Hackspace is open to commissions, and we're also keen on teaching people the skills to make for themselves.
Our [Summer of Making]({{< ref "/blog/2024/summer-of-making/index.md" >}}), has a range of skills that can help get you started, or if
you have a project in mind, please [come and talk to us](mailto:directors@leighhack.org).

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 KiB

View File

@@ -0,0 +1,29 @@
---
title: "Summer of Making"
date: 2024-06-24T07:40:38Z
tags:
- Events
- Making
- Programme
draft: false
author: Kian Ryan
author_email: kian@orangetentacle.co.uk
listing_image: images/summer_of_making.jpg
---
{{< eventbrite >}}
Alongside the opening of [Leigh Spinners Mill](https://www.spinnersmill.co.uk), [Leigh Hackspace](http://leighhack.org)
has launched our Summer Of Making programme of events open to members and non-members
from July to September.
{{< image src="images/summer_of_making.jpg" title="Leigh Hackspace Summer of Making Flyer" width="400x" class="is-pulled-right" >}}
We're offering the opportunity to try a new range of skills from 3d printing to garment making.
Events are heavily discounted for [members]({{< ref "/membership/index.md" >}}), and members also
have access to the Hackspace for their own projects at other times.
[You're welcome to visit for a chat or a tour.]({{< ref "/visit.md" >}})
If you have any questions, please [contact us](mailto:info@leighhack.org).

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

View File

@@ -0,0 +1,268 @@
---
title: "The Hackbots Project"
subtitle: "Making Simple Robots That Anyone Can Build (Pt. 1)"
date: 2024-01-01T07:40:38Z
tags:
- Rasberry Pi Pico
- Robots
- Electronics
draft: false
author: Paul Williams
author_email: phyushin@gmail.com
listing_image: images/hackbot.jpg
---
## The Beginning
We'll start at the beginning, after all, it is the very best place to start!
The inspiration for the robots came from wanting to make a simple project using fairly _off the shelf_ and _reasonably priced_ parts that young people could also get their hands on and follow allong with.
_Note: This post has been written a little "after the fact" so some parts will be skipped... for brevity_
## The Prototype
The initial prototype used the following components
- [Raspberry Pi Pico][1] * 1
- [L29XN Motor Controller][2] * 1
- [DC motors][3] * 2
- [Bluetooth Module][4] * 1
- [Breadboard][5] * 1
- A Piece of wood (to strap all the relevant bits too)
- A Caster (ideally, roughly the same size as the wheels attached to the DC motors)
So, the initial idea was to connect up the Bluetooth Module to the Pico and read data coming _over_ bluetooth to send signals based on the data - if the _forward_ command was sent over bluetooth, call the _forward_ function, sounds super simple right? right!
Below is an a code snippet of the functions (if you're following along i'd suggest having the [Github Repo][6] open in a different tab)
```python
from machine import Pin,PWM,UART
import time
uart= UART(0,9600)
In1=Pin(6,Pin.OUT) #IN1
In2=Pin(7,Pin.OUT) #IN2
In3=Pin(4,Pin.OUT) #IN3
In4=Pin(3,Pin.OUT) #IN4
EN_A=PWM(Pin(8))
EN_B=PWM(Pin(2))
# Defining frequency for enable pins
EN_A.freq(1500)
EN_B.freq(1500)
# Set maximum duty cycle, well go with max speed for now! (0 to 65025)
EN_A.duty_u16(65025)
EN_B.duty_u16(65025)
# Backward
def move_backward():
print("Back up Back up")
In1.low()
In2.high()
In3.low()
In4.high()
# Forward
def move_forward():
print("Onwards!")
In1.high()
In2.low()
In3.high()
In4.low()
# Stop
def stop():
print("All Stop")
In1.low()
In2.low()
In3.low()
In4.low()
while True:
if uart.any(): #Checking if data available
data=uart.read() #Getting data
data=str(data) #Converting bytes to str type
print(data)
if('forward' in data):
move_forward() #Forward
elif('backward' in data):
move_backward() #Backward
```
Below is the initial schematic:
{{<image src="images/initial_schematic.png" title="The prototype">}}
As you can see above, this is roughly how the prototype fit together ... you connected to the bluetooth module, send the correct commands, the pico reads them over _[uart][7]_ and calls the respective functions... well that was the plan at least - it turns out that iOS devices don't work as _out of the box_ as android devices when it comes to serial over bluetooth shenanigans, so back to the drawing board on how we get the signals - after all it's no good to us if only some kids can use it! the idea was it could be done all by your phone.
## MK II, III, and IV
So, now we've a relative idea of how it fits together we've got to overcome the issue of only being able to control robots using androids [is that meta?].
`MK II` we tried an ESP32 instead of the Pico and HC-05 combination... same issue it didn't like iOS devices :( .
In `MK III` we tried to use a different bluetooth module with a bluetooth pad, but quickly felt that this process was a little too involved for the simple pick it up and play style we were going for.
`MK IV`! we settled for replacing the Pico with a Pico W so that the wireless comms are all in the one (relatively cheap) package and instead of listening for serial commands over bluetooth; switched to using the WiFi that the Pico W has and created our very own web server, with the contols on it! - this has the added bonus of being able to customise the look [to some extent] as well as being _i-device_ compatible ... I'd call that a win!
## MK IV Explained
With our Pico W wired in we needed to make some modifications to the program running on the Pico - thankfully most of it can stay the same - that's the handy thing about writing things in functions they're all nice and contained and you can just change the way you call them rather than reimplementing them.
The main change is that instead of using bluetooth to communicate over serial we're now using the web server (this means upgrading to the Pico W for it's handy wireless functionality) to do the _talking_ and we just interact with _it_
Below is a very basic sequence diagram of how this works - did I mention it was basic?
{{<image src="images/basic_phone_to_bot_comms.png" title="Basic Sequence Diagram of the communication from phone to the _bot_">}}
Now that we've got the idea for how the communication works we can start to build the web _frontend_ for our bot... Keeping in mind that all the control functionality we already have from the `MK I` to `MK III` we just need to change the way the Pico [W now that we've _upgraded_] gets the instructions to _call_ the functions we need, we can think of this somewhat like the _frontend_ and _backend_ of any other web app really!
### Connecting to the Pico W
So first things first; we need to configure the wireless functionality of our Pico W, I've opted to do this by using splitting this out into it's own file [secrets.py][8].
An example `secrets.py` could be as follows:
```python
config = {
'ssid': 'Hackbot',
'pw': 'wonderful password'
}
```
By keeping the config _dictionary_ in a separate file we can add this file to our `.gitignore` to avoid checking in our password for our config, we can then read these config values with the following code
```python
from secrets import config
# SNIP
# ...
ssid = config['ssid']
password = config['pw']
```
This would read the config files in to variables which our code can then _use_.
_Note: You don't necessarily need to name the dictionary in `secrets.py` `config` ... you don't even need to name the file `secrets.py`!_
_Just make sure what ever you name it is reflected in the `from <secrets.py> import <config>` statement_
Now that we've got our config data into our main program file we can use this data to set up our Wifi access point on the Pico W, this is done by using code like:
```python
ap = network.WLAN(network.AP_IF)
ap.config(essid=ssid, password=password)
ap.active(True)
while ap.active() == False:
pass
print('Connection successful')
print(ap.ifconfig())
```
If your Pico is powered, you should now see it broadcasting an SSID like this:
{{ <image src="images/Wifi.png" title="Hackbots Wifi AP"> }}
Fantastic!
### Creating the Web App
The web application doesn't need to be anything fancy, after all we're going to just send get requests and read the URL for the direction.
So, the initial webserver is created using a [socket][9] like so:
```python
import socket
# SNIP
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
```
This sets up a socket and begins _listening_; next, we need to create a webpage for it to _serve_. We can use python here too as it allows us to generate something a little more _dynamic_ later on; but for now, we'll just have the `generateHTML()` function return some static html:
```python
def generateHTML():
return """<!DOCTYPE html>
<html>
<head>
<title>Hackspace Bot</title>
<style>
button {
width:175px;
height:100px;
background-color:#0000ff;
color:#ffffff;
font-size:25pt
}
</style>
</head>
<body>
<div>
<form action="" method="post">
<table class="controller">
<tr>
<td></td>
<td>
<button type="submit" formaction="forwards">&#8593</button>
</td>
<td></td>
</tr>
<tr>
<td><button type="submit" formaction="left">&#8592</button></td>
<td>
<button type="submit" formaction="stop">Stop</button>
</td>
<td>
<button type="submit" formaction="right">&#8594</button>
</td>
</tr>
<tr>
<td></td>
<td>
<button type="submit" formaction="backwards" >&#8595</button>
</td>
<td></td>
</tr>
</table>
</div>
"""
```
Finally we want to set up a loop that parses data from the website requests to decide which direction to go in this is achieved like so:
```python
while True:
try:
led.toggle() # this toggles the LED on the Pico on and off so we have some external sign that things are working
cl, addr = s.accept()
print('client connected from', addr)
request = cl.recv(1024)
data = str(request)
direction = (data[1:20].split(' ')[1].replace('/','')) # this extracts the direction from the _end_ of the url in the POST request.
if(direction =='forwards'):
move_forward()
elif(direction == 'left'):
turn_left()
elif(direction == 'right'):
turn_right()
elif(direction == 'backwards'):
move_backward()
elif(direction == 'stop'):
stop()
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
time.sleep(0.2)
cl.send(generateHTML())
cl.close()
```
What the above code does is accepts connections from clients (`cl`) of the Wifi access point and sends the control web page to them... from there, users issue commands via the buttons on the webform.
The whole project code is available on the [Github repo][6]
Thanks for reading!
[1]: https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html "Raspberry Pi Pico Family"
[2]: https://components101.com/modules/l293n-motor-driver-module "L29xN Motor Controller"
[3]: https://www.amazon.co.uk/dp/B07VBXXT9M/ref=cm_sw_r_api_i_BB50HXYKHPBAT04PZ3PT_0 "DC Motors"
[4]: https://components101.com/wireless/hc-05-bluetooth-module "HC-05 Bluetooth Module"
[5]: https://www.ebay.co.uk/itm/203599232851 "Solderless breadboard"
[6]: https://github.com/leigh-hackspace/hackspace-bots "Project Code"
[7]: https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter "UART"
[8]: https://github.com/leigh-hackspace/hackspace-bots/blob/main/example_secrets.py" "Secrets.py"
[9]: "https://docs.python.org/3/library/socket.html" "Python Sockets"

View File

@@ -14,4 +14,4 @@ Being a member is being part of a social making and learning community. Our memb
We suggest that you [visit the hackspace]({{< ref "/visit" >}}) in person before you commit to be a member. This will allow you to see the space, understand what is available, and how it can work for you. We have further information on our [wiki](https://wiki.leighhack.org/membership/joining/).
All memberships are collected on the 1st of the month, but if you wish to arrange an alternative date then please [contact us](mailto:info@leighhack.org).
All memberships are collected within 5 working days of signing up, but if you wish to arrange an alternative date then please [contact us](mailto:info@leighhack.org).

View File

@@ -11,13 +11,13 @@
{{ end }}
{{ define "extra_js" }}
<script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@2.4.1/event-calendar.min.js" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@2.4.1/event-calendar.min.js"></script>
{{ $js := resources.Get "js/calendar.js" | resources.Minify }}
{{ $secureJS := $js | resources.Fingerprint "sha512" }}
<script src="{{ $secureJS.Permalink }}" integrity="{{ $secureJS.Data.Integrity }}"></script>
{{ end }}
{{ define "content" }}
<div id="calendar"></div>
<div id="calendar"><p id="nojs">Your browser doesn't support (or has disabled) Javascript. If you wish to see the upcoming event calendar you can use our <a href="https://api.leighhack.org/events.ics">iCal Feed</a> with your calendar or mail software.</p></div>
{{ printf "<!--# include virtual='%s' -->" ("/cgi/events.cgi" | relURL) | safeHTML }}
{{ end }}

View File

@@ -21,7 +21,7 @@
<table border="1">
<tr>
<td>
<img src="{{ $image.RelPermalink}}">
<img src="{{ $image.RelPermalink}}" alt="">
</td>
<td>
<p><a href="{{ .RelPermalink }}">{{.Title}}</a> - {{ .Params.author }}<br />

View File

@@ -16,8 +16,10 @@
<img src="{{ $avatar.RelPermalink }}" alt="{{ .Params.author }}'s avatar">
</td>
<td>
<p><i>This is a post by <b>{{ .Params.author }}</b>.<br>Originally
posted <b>{{ .PublishDate | time.Format ":date_full" }}</b></i></p>
<p><i>This is a post by <b>{{ .Params.author }}</b>.<br>Posted <b>{{ .PublishDate | time.Format ":date_full" }}</b></i>
{{ if .Params.original_url }}<br>Originally posted at <a href="{{ .Params.original_url }}" rel="canonical">{{
.Params.original_url }}</a>{{ end }}
</p>
</td>
</tr>
</table>

View File

@@ -1,5 +1,5 @@
{{ with resources.Get "images/rose_logo.gif" }}
<h1><a href="{{ absURL "" }}" border="0"><img src="{{ .RelPermalink }}" alt="The logo of Leigh Hackspace" width="70px"></a> Leigh
<h1><a href="{{ absURL "" }}"><img src="{{ .RelPermalink }}" alt="The logo of Leigh Hackspace" width="70px"></a> Leigh
Hackspace</h1>
{{ end }}
<p>

View File

@@ -4,6 +4,8 @@ subtitle: ""
date: {{ .Date }}
tags: []
draft: true
author:
author: # Name to show on the post
author_email: # used for Gravatar icon
listing_image: # Image to use in the post list on the website
original_url: # If cross-posted from a blog, link to the original.
---

View File

@@ -6,7 +6,7 @@
src: url('../fonts/transport-medium.woff2') format('woff2');
}
// Hackspace Branding
// Hackspace Branding
//$family-sans-serif: "Roboto", sans-serif;
$primary: #d41246;
$accent: #fbf3ee;
@@ -92,7 +92,7 @@ p {
}
// -------------------------------------------------------
// Base
// Base
// -------------------------------------------------------
a {
text-decoration: underline;
@@ -315,7 +315,7 @@ address {
}
// -------------------------------------------------------
// Footer
// Footer
// -------------------------------------------------------
footer {
@@ -368,4 +368,20 @@ footer {
// Fix syntax highlighting to match Bulma pre
div.highlight {
padding-bottom: 1.25em;
}
// Hackspace Status
div#hackspace-open {
display: none;
}
.events {
background-image: linear-gradient(red, orange);
a {
color: white;
}
border: 2px solid red;
border-radius: 5px;;
padding: 2rem 0;
margin-bottom: 2rem;
}

View File

@@ -30,7 +30,7 @@
<div class="column is-half">
{{ block "hero-image" . }}
{{ $hero := printf "%s/%s" "images/" .Params.hero_image }}
<img class="image hero-img" src="{{ absURL $hero }}">
<img class="image hero-img" src="{{ absURL $hero }}" alt="" height="300px">
{{ end }}
</div>
{{ end }}
@@ -48,10 +48,10 @@
{{ block "content" . }}
{{ end }}
</div>
<div class="is-clearfix"></div>
</section>
<div class="is-clearfix"></div>
{{ block "cta" . }}
{{ if (default true .Params.show_cta) }}
{{ if .Params.show_big_cta }}

View File

@@ -15,12 +15,14 @@
<h3 id="{{ .Key }}">{{ .Key }}</h3>
{{- range .Pages }}
{{ $image := .Resources.GetMatch .Params.listing_image }}
{{ $image = $image.Fill "512x512 Center jpg" }}
<div class="box">
<div class="columns">
<div class="column is-one-quarter has-text-centered is-hidden-mobile">
<img src="{{ $image.RelPermalink}}" class="image is-inline-block">
{{ with .Resources.GetMatch .Params.listing_image }}
{{ $image := . }}
{{ $image = $image.Fill "512x512 Center jpg" }}
<img src="{{ $image.RelPermalink }}" class="image is-inline-block" alt="">
{{ end }}
</div>
<div class="column">
<p><a href="{{ .RelPermalink }}">{{.Title}}</a> - {{ .Params.author }}<br />
@@ -32,4 +34,4 @@
</div>
{{- end }}
{{- end }}
{{ end }}
{{ end }}

View File

@@ -17,8 +17,10 @@
</figure>
<div class="media-content">
<div class="content">
<p class="is-size-5 is-italic">This is a post by <b>{{ .Params.author }}</b>.<br />Originally
posted <b>{{ .PublishDate | time.Format ":date_full" }}</b></p>
<p class="is-size-6 is-italic">This is a post by <b>{{ .Params.author }}</b>.<br />
Posted <b>{{ .PublishDate | time.Format ":date_full" }}</b>
{{ if .Params.original_url }}<br/>Originally posted at <a href="{{ .Params.original_url }}" rel="canonical">{{ .Params.original_url }}</a>{{ end }}
</p>
</div>
</div>
</article>

View File

@@ -3,7 +3,7 @@
<div class="columns is-vcentered has-text-centered-mobile">
<div class="column">
<img class="cta-img" src="{{ absURL "images/hero-img.svg" }}">
<img class="cta-img" src="{{ absURL "images/hero-img.svg" }}" height="560px" alt="">
</div>
<div class="column">

View File

@@ -1,8 +1,8 @@
<section class="small_cta">
<div class="container ">
<div class="columns is-centered is-multiline is-vcentered is-half-desktop has-text-centered py-4">
<div class="column is-12-mobile _is-9-desktop _is-6-widescreen has-text-weight-bold" markdown="1">
Leigh Hackspace is open to all.<br>Being a member gives you access to our space, tools, and community.
<div class="column is-12-mobile _is-9-desktop _is-6-widescreen has-text-weight-bold">
<p>Leigh Hackspace is open to all.<br>Being a member gives you access to our space, tools, and community.</p>
</div>
<div class="column is-4-tablet _is-2-desktop is-3-widescreen">
<a href="{{ ref . "membership" }}" class="button is-primary is-fullwidth is-medium has-box-shadow">Join Leigh Hackspace</a>

View File

@@ -2,7 +2,7 @@
<div class="container">
<div class="columns">
<div class="column is-1 is-pull-right-touch is-hidden-mobile">
<img src="{{ absURL "images/rose_logo.svg" }}" alt="The logo of Leigh Hackspace">
<img src="{{ absURL "images/rose_logo.svg" }}" alt="The logo of Leigh Hackspace" width="90px">
</div>
<div class="column is-4">

View File

@@ -1,12 +1,11 @@
<nav class="navbar is-spaced" role="navigation" aria-label="main navigation">
<nav class="navbar is-spaced">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item" href="{{ absURL "" }}">
<img class="site-logo" src="{{ absURL "images/rose_logo.svg" }}" alt="The logo of Leigh Hackspace" width="70">
<span class="site-logo-text">Leigh<br/>Hackspace</span>
<img class="site-logo" src="{{ absURL "images/long_logo_solo_whitebg.svg" }}" alt="The logo of Leigh Hackspace" width="150">
</a>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbar">
<a role="button" class="navbar-burger" aria-label="open menu" aria-expanded="false" data-target="navbar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
@@ -18,7 +17,6 @@
{{- range site.Menus.main }}
<a href="{{ .URL }}" class="active navbar-item has-shadow is-size-5">{{ .Name }}</a>
</a>
{{- end }}
<div class="navbar-item has-shadow">

View File

@@ -0,0 +1 @@
<div class="is-clearfix"></div>

View File

@@ -0,0 +1,3 @@
<div class="events has-text-centered" id="eventbrite-events">
<a href="https://leighhack.eventbrite.com">☀️ See and book for our Summer of Making! ☀️</a>
</div>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -16,5 +16,5 @@
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone",
"start_url": "https://leighhack.org"
"start_url": "https://www.leighhack.org"
}